on fb43331 help sign in
4862 lines 173 kB history raw
1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
3module Reporting.Error.Syntax
4 ( Error(..)
5 --
6 , Module(..)
7 , Exposing(..)
8 --
9 , Decl(..)
10 , DeclType(..)
11 , TypeAlias(..)
12 , CustomType(..)
13 , DeclDef(..)
14 , Port(..)
15 --
16 , Expr(..)
17 , Record(..)
18 , Tuple(..)
19 , List(..)
20 , Func(..)
21 , Case(..)
22 , If(..)
23 , Let(..)
24 , Def(..)
25 , Destruct(..)
26 --
27 , Pattern(..)
28 , PRecord(..)
29 , PTuple(..)
30 , PList(..)
31 --
32 , Type(..)
33 , TRecord(..)
34 , TTuple(..)
35 --
36 , Char(..)
37 , String(..)
38 , Escape(..)
39 , Number(..)
40 --
41 , Space(..)
42 , toReport
43 )
44 where
47import Prelude hiding (Char, String)
48import qualified Data.Char as Char
49import qualified Data.Name as Name
50import Data.Word (Word16)
51import Numeric (showHex)
53import qualified Elm.ModuleName as ModuleName
54import Parse.Primitives (Row, Col)
55import Parse.Symbol (BadOperator(..))
56import qualified Reporting.Annotation as A
57import qualified Reporting.Doc as D
58import qualified Reporting.Report as Report
59import qualified Reporting.Render.Code as Code
63-- ALL SYNTAX ERRORS
66data Error
67 = ModuleNameUnspecified ModuleName.Raw
68 | ModuleNameMismatch ModuleName.Raw (A.Located ModuleName.Raw)
69 | UnexpectedPort A.Region
70 | NoPorts A.Region
71 | ParseError Module
75-- MODULE
78data Module
79 = ModuleSpace Space Row Col
80 | ModuleEndOfFile Row Col
81 --
82 | ModuleProblem Row Col
83 | ModuleName Row Col
84 | ModuleExposing Exposing Row Col
85 --
86 | PortModuleProblem Row Col
87 | PortModuleName Row Col
88 | PortModuleExposing Exposing Row Col
89 --
90 | Effect Row Col
91 --
92 | FreshLine Row Col
93 --
94 | ImportStart Row Col
95 | ImportName Row Col
96 | ImportAs Row Col
97 | ImportAlias Row Col
98 | ImportExposing Row Col
99 | ImportExposingList Exposing Row Col
100 | ImportEnd Row Col -- different based on col=1 or if greater
101 --
102 | ImportIndentName Row Col
103 | ImportIndentAlias Row Col
104 | ImportIndentExposingList Row Col
105 --
106 | Infix Row Col
107 --
108 | Declarations Decl Row Col
111data Exposing
112 = ExposingSpace Space Row Col
113 | ExposingStart Row Col
114 | ExposingValue Row Col
115 | ExposingOperator Row Col
116 | ExposingOperatorReserved BadOperator Row Col
117 | ExposingOperatorRightParen Row Col
118 | ExposingTypePrivacy Row Col
119 | ExposingEnd Row Col
120 --
121 | ExposingIndentEnd Row Col
122 | ExposingIndentValue Row Col
126-- DECLARATIONS
129data Decl
130 = DeclStart Row Col
131 | DeclSpace Space Row Col
132 --
133 | Port Port Row Col
134 | DeclType DeclType Row Col
135 | DeclDef Name.Name DeclDef Row Col
136 --
137 | DeclFreshLineAfterDocComment Row Col
140data DeclDef
141 = DeclDefSpace Space Row Col
142 | DeclDefEquals Row Col
143 | DeclDefType Type Row Col
144 | DeclDefArg Pattern Row Col
145 | DeclDefBody Expr Row Col
146 | DeclDefNameRepeat Row Col
147 | DeclDefNameMatch Name.Name Row Col
148 --
149 | DeclDefIndentType Row Col
150 | DeclDefIndentEquals Row Col
151 | DeclDefIndentBody Row Col
154data Port
155 = PortSpace Space Row Col
156 | PortName Row Col
157 | PortColon Row Col
158 | PortType Type Row Col
159 | PortIndentName Row Col
160 | PortIndentColon Row Col
161 | PortIndentType Row Col
165-- TYPE DECLARATIONS
168data DeclType
169 = DT_Space Space Row Col
170 | DT_Name Row Col
171 | DT_Alias TypeAlias Row Col
172 | DT_Union CustomType Row Col
173 --
174 | DT_IndentName Row Col
177data TypeAlias
178 = AliasSpace Space Row Col
179 | AliasName Row Col
180 | AliasEquals Row Col
181 | AliasBody Type Row Col
182 --
183 | AliasIndentEquals Row Col
184 | AliasIndentBody Row Col
187data CustomType
188 = CT_Space Space Row Col
189 | CT_Name Row Col
190 | CT_Equals Row Col
191 | CT_Bar Row Col
192 | CT_Variant Row Col
193 | CT_VariantArg Type Row Col
194 --
195 | CT_IndentEquals Row Col
196 | CT_IndentBar Row Col
197 | CT_IndentAfterBar Row Col
198 | CT_IndentAfterEquals Row Col
202-- EXPRESSIONS
205data Expr
206 = Let Let Row Col
207 | Case Case Row Col
208 | If If Row Col
209 | List List Row Col
210 | Record Record Row Col
211 | Tuple Tuple Row Col
212 | Func Func Row Col
213 --
214 | Dot Row Col
215 | Access Row Col
216 | OperatorRight Name.Name Row Col
217 | OperatorReserved BadOperator Row Col
218 --
219 | Start Row Col
220 | Char Char Row Col
221 | String String Row Col
222 | Number Number Row Col
223 | Space Space Row Col
224 | EndlessShader Row Col
225 | ShaderProblem [Char.Char] Row Col
226 | IndentOperatorRight Name.Name Row Col
227 | IndentMoreExpr Row Col
230data Record
231 = RecordOpen Row Col
232 | RecordEnd Row Col
233 | RecordField Row Col
234 | RecordEquals Row Col
235 | RecordExpr Expr Row Col
236 | RecordSpace Space Row Col
237 --
238 | RecordIndentOpen Row Col
239 | RecordIndentEnd Row Col
240 | RecordIndentField Row Col
241 | RecordIndentEquals Row Col
242 | RecordIndentExpr Row Col
245data Tuple
246 = TupleExpr Expr Row Col
247 | TupleSpace Space Row Col
248 | TupleEnd Row Col
249 | TupleOperatorClose Row Col
250 | TupleOperatorReserved BadOperator Row Col
251 --
252 | TupleIndentExpr1 Row Col
253 | TupleIndentExprN Row Col
254 | TupleIndentEnd Row Col
257data List
258 = ListSpace Space Row Col
259 | ListOpen Row Col
260 | ListExpr Expr Row Col
261 | ListEnd Row Col
262 --
263 | ListIndentOpen Row Col
264 | ListIndentEnd Row Col
265 | ListIndentExpr Row Col
268data Func
269 = FuncSpace Space Row Col
270 | FuncArg Pattern Row Col
271 | FuncBody Expr Row Col
272 | FuncArrow Row Col
273 --
274 | FuncIndentArg Row Col
275 | FuncIndentArrow Row Col
276 | FuncIndentBody Row Col
279data Case
280 = CaseSpace Space Row Col
281 | CaseOf Row Col
282 | CasePattern Pattern Row Col
283 | CaseArrow Row Col
284 | CaseExpr Expr Row Col
285 | CaseBranch Expr Row Col
286 --
287 | CaseIndentOf Row Col
288 | CaseIndentExpr Row Col
289 | CaseIndentPattern Row Col
290 | CaseIndentArrow Row Col
291 | CaseIndentBranch Row Col
292 | CasePatternAlignment Word16 Row Col
295data If
296 = IfSpace Space Row Col
297 | IfThen Row Col
298 | IfElse Row Col
299 | IfElseBranchStart Row Col
300 --
301 | IfCondition Expr Row Col
302 | IfThenBranch Expr Row Col
303 | IfElseBranch Expr Row Col
304 --
305 | IfIndentCondition Row Col
306 | IfIndentThen Row Col
307 | IfIndentThenBranch Row Col
308 | IfIndentElseBranch Row Col
309 | IfIndentElse Row Col
312data Let
313 = LetSpace Space Row Col
314 | LetIn Row Col
315 | LetDefAlignment Word16 Row Col
316 | LetDefName Row Col
317 | LetDef Name.Name Def Row Col
318 | LetDestruct Destruct Row Col
319 | LetBody Expr Row Col
320 | LetIndentDef Row Col
321 | LetIndentIn Row Col
322 | LetIndentBody Row Col
325data Def
326 = DefSpace Space Row Col
327 | DefType Type Row Col
328 | DefNameRepeat Name.Name Row Col
329 | DefNameMatch Name.Name Name.Name Row Col
330 | DefArg Pattern Row Col
331 | DefEquals Row Col
332 | DefBody Expr Row Col
333 | DefIndentEquals Row Col
334 | DefIndentType Row Col
335 | DefIndentBody Row Col
336 | DefAlignment Word16 Row Col
339data Destruct
340 = DestructSpace Space Row Col
341 | DestructPattern Pattern Row Col
342 | DestructEquals Row Col
343 | DestructBody Expr Row Col
344 | DestructIndentEquals Row Col
345 | DestructIndentBody Row Col
349-- PATTERNS
352data Pattern
353 = PRecord PRecord Row Col
354 | PTuple PTuple Row Col
355 | PList PList Row Col
356 --
357 | PStart Row Col
358 | PChar Char Row Col
359 | PString String Row Col
360 | PNumber Number Row Col
361 | PFloat Word16 Row Col
362 | PAlias Row Col
363 | PWildcardNotVar Name.Name Int Row Col
364 | PSpace Space Row Col
365 --
366 | PIndentStart Row Col
367 | PIndentAlias Row Col
370data PRecord
371 = PRecordOpen Row Col
372 | PRecordEnd Row Col
373 | PRecordField Row Col
374 | PRecordSpace Space Row Col
375 --
376 | PRecordIndentOpen Row Col
377 | PRecordIndentEnd Row Col
378 | PRecordIndentField Row Col
381data PTuple
382 = PTupleOpen Row Col
383 | PTupleEnd Row Col
384 | PTupleExpr Pattern Row Col
385 | PTupleSpace Space Row Col
386 --
387 | PTupleIndentEnd Row Col
388 | PTupleIndentExpr1 Row Col
389 | PTupleIndentExprN Row Col
392data PList
393 = PListOpen Row Col
394 | PListEnd Row Col
395 | PListExpr Pattern Row Col
396 | PListSpace Space Row Col
397 --
398 | PListIndentOpen Row Col
399 | PListIndentEnd Row Col
400 | PListIndentExpr Row Col
404-- TYPES
407data Type
408 = TRecord TRecord Row Col
409 | TTuple TTuple Row Col
410 --
411 | TStart Row Col
412 | TSpace Space Row Col
413 --
414 | TIndentStart Row Col
417data TRecord
418 = TRecordOpen Row Col
419 | TRecordEnd Row Col
420 --
421 | TRecordField Row Col
422 | TRecordColon Row Col
423 | TRecordType Type Row Col
424 --
425 | TRecordSpace Space Row Col
426 --
427 | TRecordIndentOpen Row Col
428 | TRecordIndentField Row Col
429 | TRecordIndentColon Row Col
430 | TRecordIndentType Row Col
431 | TRecordIndentEnd Row Col
434data TTuple
435 = TTupleOpen Row Col
436 | TTupleEnd Row Col
437 | TTupleType Type Row Col
438 | TTupleSpace Space Row Col
439 --
440 | TTupleIndentType1 Row Col
441 | TTupleIndentTypeN Row Col
442 | TTupleIndentEnd Row Col
446-- LITERALS
449data Char
450 = CharEndless
451 | CharEscape Escape
452 | CharNotString Word16
455data String
456 = StringEndless_Single
457 | StringEndless_Multi
458 | StringEscape Escape
461data Escape
462 = EscapeUnknown
463 | BadUnicodeFormat Word16
464 | BadUnicodeCode Word16
465 | BadUnicodeLength Word16 Int Int
468data Number
469 = NumberEnd
470 | NumberDot Int
471 | NumberHexDigit
472 | NumberNoLeadingZero
476-- MISC
479data Space
480 = HasTab
481 | EndlessMultiComment
485-- TO REPORT
488toReport :: Code.Source -> Error -> Report.Report
489toReport source err =
490 case err of
491 ModuleNameUnspecified name ->
492 let
493 region = toRegion 1 1
494 in
495 Report.Report "MODULE NAME MISSING" region [] $
496 D.stack
497 [ D.reflow $
498 "I need the module name to be declared at the top of this file, like this:"
499 , D.indent 4 $ D.fillSep $
500 [ D.cyan "module", D.fromName name, D.cyan "exposing", "(..)" ]
501 , D.reflow $
502 "Try adding that as the first line of your file!"
503 , D.toSimpleNote $
504 "It is best to replace (..) with an explicit list of types and\
505 \ functions you want to expose. When you know a value is only used\
506 \ within this module, you can refactor without worrying about uses\
507 \ elsewhere. Limiting exposed values can also speed up compilation\
508 \ because I can skip a bunch of work if I see that the exposed API\
509 \ has not changed."
510 ]
512 ModuleNameMismatch expectedName (A.At region actualName) ->
513 Report.Report "MODULE NAME MISMATCH" region [ModuleName.toChars expectedName] $
514 Code.toSnippet source region Nothing
515 (
516 "It looks like this module name is out of sync:"
517 ,
518 D.stack
519 [ D.reflow $
520 "I need it to match the file path, so I was expecting it to see `"
521 ++ ModuleName.toChars expectedName
522 ++ "` here. Make the following change, and you should be all set!"
523 , D.indent 4 $
524 D.dullyellow (D.fromName actualName) <> " -> " <> D.green (D.fromName expectedName)
525 , D.toSimpleNote $
526 "I require that module names correspond to file paths. This makes it much\
527 \ easier to explore unfamiliar codebases! So if you want to keep the current\
528 \ module name, try renaming the file instead."
529 ]
530 )
532 UnexpectedPort region ->
533 Report.Report "UNEXPECTED PORTS" region [] $
534 Code.toSnippet source region Nothing
535 (
536 D.reflow $
537 "You are declaring ports in a normal module."
538 ,
539 D.stack
540 [ D.fillSep
541 ["Switch","this","to","say",D.cyan "port module","instead,"
542 ,"marking","that","this","module","contains","port","declarations."
543 ]
544 , D.link "Note"
545 "Ports are not a traditional FFI for calling JS functions directly. They need a different mindset! Read"
546 "ports"
547 "to learn the syntax and how to use it effectively."
548 ]
549 )
551 NoPorts region ->
552 Report.Report "NO PORTS" region [] $
553 Code.toSnippet source region Nothing
554 (
555 D.reflow $
556 "This module does not declare any ports, but it says it will:"
557 ,
558 D.fillSep
559 ["Switch","this","to",D.cyan "module"
560 ,"and","you","should","be","all","set!"
561 ]
562 )
564 ParseError modul ->
565 toParseErrorReport source modul
568toParseErrorReport :: Code.Source -> Module -> Report.Report
569toParseErrorReport source modul =
570 case modul of
571 ModuleSpace space row col ->
572 toSpaceReport source space row col
574 ModuleEndOfFile row col ->
575 case Code.whatIsNext source row col of
576 Code.Keyword keyword ->
577 let
578 region = toKeywordRegion row col keyword
579 in
580 Report.Report "RESERVED WORD" region [] $
581 Code.toSnippet source region Nothing
582 (
583 D.reflow $
584 "I got stuck on this reserved word:"
585 ,
586 D.reflow $
587 "The name `" ++ keyword ++ "` is reserved, so try using a different name?"
588 )
590 Code.Operator op ->
591 let
592 region = toKeywordRegion row col op
593 in
594 Report.Report "UNEXPECTED SYMBOL" region [] $
595 Code.toSnippet source region Nothing
596 (
597 D.reflow $
598 "I ran into an unexpected symbol:"
599 ,
600 D.reflow $
601 "I was not expecting to see a " ++ op ++ " here. Try deleting it? Maybe\
602 \ I can give a better hint from there?"
603 )
605 Code.Close term bracket ->
606 let
607 region = toRegion row col
608 in
609 Report.Report ("UNEXPECTED " ++ map Char.toUpper term) region [] $
610 Code.toSnippet source region Nothing
611 (
612 D.reflow $
613 "I ran into an unexpected " ++ term ++ ":"
614 ,
615 D.reflow $
616 "This " ++ bracket : " does not match up with an earlier open " ++ term ++ ". Try deleting it?"
617 )
619 Code.Other ->
620 let
621 region = toRegion row col
622 in
623 Report.Report "SYNTAX PROBLEM" region [] $
624 Code.toSnippet source region Nothing
625 (
626 D.reflow $
627 "I got stuck here:"
628 ,
629 D.reflow $
630 "Whatever I am running into is confusing me a lot! Normally I can give fairly\
631 \ specific hints, but something is really tripping me up this time."
632 )
634 ModuleProblem row col ->
635 let
636 region = toRegion row col
637 in
638 Report.Report "UNFINISHED MODULE DECLARATION" region [] $
639 Code.toSnippet source region Nothing
640 (
641 D.reflow $
642 "I am parsing an `module` declaration, but I got stuck here:"
643 ,
644 D.stack
645 [ D.reflow $
646 "Here are some examples of valid `module` declarations:"
647 , D.indent 4 $ D.vcat $
648 [ D.fillSep [D.cyan "module","Main",D.cyan "exposing","(..)"]
649 , D.fillSep [D.cyan "module","Dict",D.cyan "exposing","(Dict, empty, get)"]
650 ]
651 , D.reflow $
652 "I generally recommend using an explicit exposing list. I can skip compiling a bunch\
653 \ of files when the public interface of a module stays the same, so exposing fewer\
654 \ values can help improve compile times!"
655 ]
656 )
658 ModuleName row col ->
659 let
660 region = toRegion row col
661 in
662 Report.Report "EXPECTING MODULE NAME" region [] $
663 Code.toSnippet source region Nothing
664 (
665 D.reflow $
666 "I was parsing an `module` declaration until I got stuck here:"
667 ,
668 D.stack
669 [ D.reflow $
670 "I was expecting to see the module name next, like in these examples:"
671 , D.indent 4 $ D.vcat $
672 [ D.fillSep [D.cyan "module","Dict",D.cyan "exposing","(..)"]
673 , D.fillSep [D.cyan "module","Maybe",D.cyan "exposing","(..)"]
674 , D.fillSep [D.cyan "module","Html.Attributes",D.cyan "exposing","(..)"]
675 , D.fillSep [D.cyan "module","Json.Decode",D.cyan "exposing","(..)"]
676 ]
677 , D.reflow $
678 "Notice that the module names all start with capital letters. That is required!"
679 ]
680 )
682 ModuleExposing exposing row col ->
683 toExposingReport source exposing row col
685 PortModuleProblem row col ->
686 let
687 region = toRegion row col
688 in
689 Report.Report "UNFINISHED PORT MODULE DECLARATION" region [] $
690 Code.toSnippet source region Nothing
691 (
692 D.reflow $
693 "I am parsing an `port module` declaration, but I got stuck here:"
694 ,
695 D.stack
696 [ D.reflow $
697 "Here are some examples of valid `port module` declarations:"
698 , D.indent 4 $ D.vcat $
699 [ D.fillSep [D.cyan "port",D.cyan "module","WebSockets",D.cyan "exposing","(send, listen, keepAlive)"]
700 , D.fillSep [D.cyan "port",D.cyan "module","Maps",D.cyan "exposing","(Location, goto)"]
701 ]
702 , D.link "Note" "Read" "ports" "for more help."
703 ]
704 )
706 PortModuleName row col ->
707 let
708 region = toRegion row col
709 in
710 Report.Report "EXPECTING MODULE NAME" region [] $
711 Code.toSnippet source region Nothing
712 (
713 D.reflow $
714 "I was parsing an `module` declaration until I got stuck here:"
715 ,
716 D.stack
717 [ D.reflow $
718 "I was expecting to see the module name next, like in these examples:"
719 , D.indent 4 $ D.vcat $
720 [ D.fillSep [D.cyan "port",D.cyan "module","WebSockets",D.cyan "exposing","(send, listen, keepAlive)"]
721 , D.fillSep [D.cyan "port",D.cyan "module","Maps",D.cyan "exposing","(Location, goto)"]
722 ]
723 , D.reflow $
724 "Notice that the module names start with capital letters. That is required!"
725 ]
726 )
728 PortModuleExposing exposing row col ->
729 toExposingReport source exposing row col
731 Effect row col ->
732 let
733 region = toRegion row col
734 in
735 Report.Report "BAD MODULE DECLARATION" region [] $
736 Code.toSnippet source region Nothing
737 (
738 D.reflow $
739 "I cannot parse this module declaration:"
740 ,
741 D.reflow $
742 "This type of module is reserved for the @elm organization. It is used to\
743 \ define certain effects, avoiding building them into the compiler."
744 )
746 FreshLine row col ->
747 let
748 region = toRegion row col
750 toBadFirstLineReport keyword =
751 Report.Report "TOO MUCH INDENTATION" region [] $
752 Code.toSnippet source region Nothing
753 (
754 D.reflow $
755 "This `" ++ keyword ++ "` should not have any spaces before it:"
756 ,
757 D.reflow $
758 "Delete the spaces before `" ++ keyword ++ "` until there are none left!"
759 )
761 in
762 case Code.whatIsNext source row col of
763 Code.Keyword "module" -> toBadFirstLineReport "module"
764 Code.Keyword "import" -> toBadFirstLineReport "import"
765 Code.Keyword "type" -> toBadFirstLineReport "type"
766 Code.Keyword "port" -> toBadFirstLineReport "port"
767 _ ->
768 Report.Report "SYNTAX PROBLEM" region [] $
769 Code.toSnippet source region Nothing
770 (
771 D.reflow $
772 "I got stuck here:"
773 ,
774 D.stack
775 [ D.reflow $
776 "I am not sure what is going on, but I recommend starting an Elm\
777 \ file with the following lines:"
778 , D.vcat
779 [ D.fillSep [D.cyan "import","Html"]
780 , ""
781 , D.fillSep [D.green "main","="]
782 , D.indent 2 $ D.fillSep [D.cyan "Html" <> ".text",D.dullyellow "\"Hello!\""]
783 ]
784 , D.reflow $
785 "You should be able to copy those lines directly into your file. Check out\
786 \ some of the examples on https://elm-lang.org for more help getting started!"
787 , D.toSimpleNote $
788 "This can also happen when something is indented too much!"
789 ]
790 )
792 ImportStart row col ->
793 toImportReport source row col
795 ImportName row col ->
796 let
797 region = toRegion row col
798 in
799 Report.Report "EXPECTING IMPORT NAME" region [] $
800 Code.toSnippet source region Nothing
801 (
802 D.reflow $
803 "I was parsing an `import` until I got stuck here:"
804 ,
805 D.stack
806 [ D.reflow $
807 "I was expecting to see a module name next, like in these examples:"
808 , D.indent 4 $ D.vcat $
809 [ D.fillSep [D.cyan "import","Dict"]
810 , D.fillSep [D.cyan "import","Maybe"]
811 , D.fillSep [D.cyan "import","Html.Attributes"]
812 , D.fillSep [D.cyan "import","Json.Decode"]
813 ]
814 , D.reflow $
815 "Notice that the module names all start with capital letters. That is required!"
816 ]
817 )
819 ImportAs row col ->
820 toImportReport source row col
822 ImportAlias row col ->
823 let
824 region = toRegion row col
825 in
826 Report.Report "EXECTING IMPORT ALIAS" region [] $
827 Code.toSnippet source region Nothing
828 (
829 D.reflow $
830 "I was parsing an `import` until I got stuck here:"
831 ,
832 D.stack
833 [ D.reflow $
834 "I was expecting to see an alias next, like in these examples:"
835 , D.indent 4 $ D.vcat $
836 [ D.fillSep [D.cyan "import","Html.Attributes",D.cyan "as","Attr"]
837 , D.fillSep [D.cyan "import","WebGL.Texture",D.cyan "as","Texture"]
838 , D.fillSep [D.cyan "import","Json.Decode",D.cyan "as","D"]
839 ]
840 , D.reflow $
841 "Notice that the alias always starts with a capital letter. That is required!"
842 ]
843 )
845 ImportExposing row col ->
846 toImportReport source row col
848 ImportExposingList exposing row col ->
849 toExposingReport source exposing row col
851 ImportEnd row col ->
852 toImportReport source row col
854 ImportIndentName row col ->
855 toImportReport source row col
857 ImportIndentAlias row col ->
858 toImportReport source row col
860 ImportIndentExposingList row col ->
861 let
862 region = toRegion row col
863 in
864 Report.Report "UNFINISHED IMPORT" region [] $
865 Code.toSnippet source region Nothing
866 (
867 D.reflow $
868 "I was parsing an `import` until I got stuck here:"
869 ,
870 D.stack
871 [ D.reflow $
872 "I was expecting to see the list of exposed values next. For example, here\
873 \ are two ways to expose values from the `Html` module:"
874 , D.indent 4 $ D.vcat $
875 [ D.fillSep [D.cyan "import","Html",D.cyan "exposing","(..)"]
876 , D.fillSep [D.cyan "import","Html",D.cyan "exposing","(Html, div, text)"]
877 ]
878 , D.reflow $
879 "I generally recommend the second style. It is more explicit, making it\
880 \ much easier to figure out where values are coming from in large projects!"
881 ]
882 )
884 Infix row col ->
885 let
886 region = toRegion row col
887 in
888 Report.Report "BAD INFIX" region [] $
889 Code.toSnippet source region Nothing
890 (
891 D.reflow $
892 "Something went wrong in this infix operator declaration:"
893 ,
894 D.reflow $
895 "This feature is used by the @elm organization to define the\
896 \ languages built-in operators."
897 )
899 Declarations decl _ _ ->
900 toDeclarationsReport source decl
904-- IMPORTS
907toImportReport :: Code.Source -> Row -> Col -> Report.Report
908toImportReport source row col =
909 let
910 region = toRegion row col
911 in
912 Report.Report "UNFINISHED IMPORT" region [] $
913 Code.toSnippet source region Nothing
914 (
915 D.reflow $
916 "I am partway through parsing an import, but I got stuck here:"
917 ,
918 D.stack
919 [ D.reflow $
920 "Here are some examples of valid `import` declarations:"
921 , D.indent 4 $ D.vcat $
922 [ D.fillSep [D.cyan "import","Html"]
923 , D.fillSep [D.cyan "import","Html",D.cyan "as","H"]
924 , D.fillSep [D.cyan "import","Html",D.cyan "as","H",D.cyan "exposing","(..)"]
925 , D.fillSep [D.cyan "import","Html",D.cyan "exposing","(Html, div, text)"]
926 ]
927 , D.reflow $
928 "You are probably trying to import a different module, but try to make it look like one of these examples!"
929 ]
930 )
934-- EXPOSING
937toExposingReport :: Code.Source -> Exposing -> Row -> Col -> Report.Report
938toExposingReport source exposing startRow startCol =
939 case exposing of
940 ExposingSpace space row col ->
941 toSpaceReport source space row col
943 ExposingStart row col ->
944 let
945 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
946 region = toRegion row col
947 in
948 Report.Report "PROBLEM IN EXPOSING" region [] $
949 Code.toSnippet source surroundings (Just region)
950 (
951 D.reflow $
952 "I want to parse exposed values, but I am getting stuck here:"
953 ,
954 D.stack
955 [ D.fillSep $
956 ["Exposed","values","are","always","surrounded","by","parentheses."
957 ,"So","try","adding","a",D.green "(","here?"
958 ]
959 , D.toSimpleNote "Here are some valid examples of `exposing` for reference:"
960 , D.indent 4 $ D.vcat $
961 [ D.fillSep [D.cyan "import","Html",D.cyan "exposing","(..)"]
962 , D.fillSep [D.cyan "import","Html",D.cyan "exposing","(Html, div, text)"]
963 ]
964 , D.reflow $
965 "If you are getting tripped up, you can just expose everything for now. It should\
966 \ get easier to make an explicit exposing list as you see more examples in the wild."
967 ]
968 )
970 ExposingValue row col ->
971 case Code.whatIsNext source row col of
972 Code.Keyword keyword ->
973 let
974 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
975 region = toKeywordRegion row col keyword
976 in
977 Report.Report "RESERVED WORD" region [] $
978 Code.toSnippet source surroundings (Just region)
979 (
980 D.reflow $
981 "I got stuck on this reserved word:"
982 ,
983 D.reflow $
984 "It looks like you are trying to expose `" ++ keyword ++ "` but that is a reserved word. Is there a typo?"
985 )
987 Code.Operator op ->
988 let
989 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
990 region = toKeywordRegion row col op
991 in
992 Report.Report "UNEXPECTED SYMBOL" region [] $
993 Code.toSnippet source surroundings (Just region)
994 (
995 D.reflow $
996 "I got stuck on this symbol:"
997 ,
998 D.stack
999 [ D.reflow $
1000 "If you are trying to expose an operator, add parentheses around it like this:"
1001 , D.indent 4 $ D.dullyellow (D.fromChars op) <> " -> " <> D.green ("(" <> D.fromChars op <> ")")
1005 _ ->
1006 let
1007 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1008 region = toRegion row col
1009 in
1010 Report.Report "PROBLEM IN EXPOSING" region [] $
1011 Code.toSnippet source surroundings (Just region)
1013 D.reflow $
1014 "I got stuck while parsing these exposed values:"
1016 D.stack
1017 [ D.reflow $
1018 "I do not have an exact recommendation, so here are some valid examples\
1019 \ of `exposing` for reference:"
1020 , D.indent 4 $ D.vcat $
1021 [ D.fillSep [D.cyan "import","Html",D.cyan "exposing","(..)"]
1022 , D.fillSep [D.cyan "import","Basics",D.cyan "exposing","(Int, Float, Bool(..), (+), not, sqrt)"]
1024 , D.reflow $
1025 "These examples show how to expose types, variants, operators, and functions. Everything\
1026 \ should be some permutation of these examples, just with different names."
1030 ExposingOperator row col ->
1031 let
1032 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1033 region = toRegion row col
1034 in
1035 Report.Report "PROBLEM IN EXPOSING" region [] $
1036 Code.toSnippet source surroundings (Just region)
1038 D.reflow $
1039 "I just saw an open parenthesis, so I was expecting an operator next:"
1041 D.fillSep $
1042 ["It","is","possible","to","expose","operators,","so","I","was","expecting"
1043 ,"to","see","something","like",D.dullyellow "(+)","or",D.dullyellow "(|=)"
1044 ,"or",D.dullyellow "(||)","after","I","saw","that","open","parenthesis."
1048 ExposingOperatorReserved op row col ->
1049 let
1050 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1051 region = toRegion row col
1052 in
1053 Report.Report "RESERVED SYMBOL" region [] $
1054 Code.toSnippet source surroundings (Just region)
1056 D.reflow $
1057 "I cannot expose this as an operator:"
1059 case op of
1060 BadDot -> D.reflow "Try getting rid of this entry? Maybe I can give you a better hint after that?"
1061 BadPipe -> D.fillSep ["Maybe","you","want",D.dullyellow "(||)","instead?"]
1062 BadArrow -> D.reflow "Try getting rid of this entry? Maybe I can give you a better hint after that?"
1063 BadEquals -> D.fillSep ["Maybe","you","want",D.dullyellow "(==)","instead?"]
1064 BadHasType -> D.fillSep ["Maybe","you","want",D.dullyellow "(::)","instead?"]
1067 ExposingOperatorRightParen row col ->
1068 let
1069 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1070 region = toRegion row col
1071 in
1072 Report.Report "PROBLEM IN EXPOSING" region [] $
1073 Code.toSnippet source surroundings (Just region)
1075 D.reflow $
1076 "It looks like you are exposing an operator, but I got stuck here:"
1078 D.fillSep $
1079 ["I","was","expecting","to","see","the","closing","parenthesis","immediately"
1080 ,"after","the","operator.","Try","adding","a",D.green ")","right","here?"
1084 ExposingEnd row col ->
1085 let
1086 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1087 region = toRegion row col
1088 in
1089 Report.Report "UNFINISHED EXPOSING" region [] $
1090 Code.toSnippet source surroundings (Just region)
1092 D.reflow $
1093 "I was partway through parsing exposed values, but I got stuck here:"
1095 D.reflow $
1096 "Maybe there is a comma missing before this?"
1099 ExposingTypePrivacy row col ->
1100 let
1101 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1102 region = toRegion row col
1103 in
1104 Report.Report "PROBLEM EXPOSING CUSTOM TYPE VARIANTS" region [] $
1105 Code.toSnippet source surroundings (Just region)
1107 D.reflow $
1108 "It looks like you are trying to expose the variants of a custom type:"
1110 D.stack
1111 [ D.fillSep $
1112 ["You","need","to","write","something","like"
1113 ,D.dullyellow "Status(..)","or",D.dullyellow "Entity(..)"
1114 ,"though.","It","is","all","or","nothing,","otherwise","`case`"
1115 ,"expressions","could","miss","a","variant","and","crash!"
1117 , D.toSimpleNote $
1118 "It is often best to keep the variants hidden! If someone pattern matches on\
1119 \ the variants, it is a MAJOR change if any new variants are added. Suddenly\
1120 \ their `case` expressions do not cover all variants! So if you do not need\
1121 \ people to pattern match, keep the variants hidden and expose functions to\
1122 \ construct values of this type. This way you can add new variants as a MINOR change!"
1126 ExposingIndentEnd row col ->
1127 let
1128 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1129 region = toRegion row col
1130 in
1131 Report.Report "UNFINISHED EXPOSING" region [] $
1132 Code.toSnippet source surroundings (Just region)
1134 D.reflow $
1135 "I was partway through parsing exposed values, but I got stuck here:"
1137 D.stack
1138 [ D.fillSep $
1139 ["I","was","expecting","a","closing","parenthesis."
1140 ,"Try","adding","a",D.green ")","right","here?"
1142 , D.toSimpleNote $
1143 "I can get confused when there is not enough indentation, so if you already\
1144 \ have a closing parenthesis, it probably just needs some spaces in front of it."
1148 ExposingIndentValue row col ->
1149 let
1150 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1151 region = toRegion row col
1152 in
1153 Report.Report "UNFINISHED EXPOSING" region [] $
1154 Code.toSnippet source surroundings (Just region)
1156 D.reflow $
1157 "I was partway through parsing exposed values, but I got stuck here:"
1159 D.reflow $
1160 "I was expecting another value to expose."
1165-- SPACES
1168toSpaceReport :: Code.Source -> Space -> Row -> Col -> Report.Report
1169toSpaceReport source space row col =
1170 case space of
1171 HasTab ->
1172 let
1173 region = toRegion row col
1174 in
1175 Report.Report "NO TABS" region [] $
1176 Code.toSnippet source region Nothing
1178 D.reflow $
1179 "I ran into a tab, but tabs are not allowed in Elm files."
1181 D.reflow $
1182 "Replace the tab with spaces."
1185 EndlessMultiComment ->
1186 let
1187 region = toWiderRegion row col 2
1188 in
1189 Report.Report "ENDLESS COMMENT" region [] $
1190 Code.toSnippet source region Nothing
1192 D.reflow $
1193 "I cannot find the end of this multi-line comment:"
1195 D.stack -- "{-"
1196 [ D.reflow "Add a -} somewhere after this to end the comment."
1197 , D.toSimpleHint
1198 "Multi-line comments can be nested in Elm, so {- {- -} -} is a comment\
1199 \ that happens to contain another comment. Like parentheses and curly braces,\
1200 \ the start and end markers must always be balanced. Maybe that is the problem?"
1206-- DECLARATIONS
1209toRegion :: Row -> Col -> A.Region
1210toRegion row col =
1211 let
1212 pos = A.Position row col
1213 in
1214 A.Region pos pos
1217toWiderRegion :: Row -> Col -> Word16 -> A.Region
1218toWiderRegion row col extra =
1219 A.Region
1220 (A.Position row col)
1221 (A.Position row (col + extra))
1224toKeywordRegion :: Row -> Col -> [Char.Char] -> A.Region
1225toKeywordRegion row col keyword =
1226 A.Region
1227 (A.Position row col)
1228 (A.Position row (col + fromIntegral (length keyword)))
1231toDeclarationsReport :: Code.Source -> Decl -> Report.Report
1232toDeclarationsReport source decl =
1233 case decl of
1234 DeclStart row col ->
1235 case Code.whatIsNext source row col of
1236 Code.Close term _ ->
1237 let
1238 region = toRegion row col
1239 in
1240 Report.Report ("STRAY " ++ map Char.toUpper term) region [] $
1241 Code.toSnippet source region Nothing
1243 D.reflow $
1244 "I was not expecting to see a " ++ term ++ " here:"
1245 , D.reflow $
1246 "It does not match up with anything. Maybe try deleting it?"
1249 Code.Keyword keyword ->
1250 let
1251 region = toKeywordRegion row col keyword
1252 in
1253 Report.Report "RESERVED WORD" region [] $
1254 Code.toSnippet source region Nothing
1256 D.reflow $
1257 "I was not expecting to run into the `" ++ keyword ++ "` keyword here:"
1259 case keyword of
1260 "import" ->
1261 D.reflow $
1262 "It is reserved for declaring imports at the top of your module. If you want\
1263 \ another import, try moving it up top with the other imports. If you want to\
1264 \ define a value or function, try changing the name to something else!"
1266 "case" ->
1267 D.stack
1268 [ D.reflow $
1269 "It is reserved for writing `case` expressions. Try using a different name?"
1270 , D.toSimpleNote $
1271 "If you are trying to write a `case` expression, it needs to be part of a\
1272 \ definition. So you could write something like this instead:"
1273 , D.vcat $
1274 [ D.indent 0 $ D.fillSep [D.green "getWidth","maybeWidth","="]
1275 , D.indent 2 $ D.fillSep [D.cyan "case","maybeWidth",D.cyan "of"]
1276 , D.indent 4 $ D.fillSep [D.blue "Just","width","->"]
1277 , D.indent 6 $ D.fillSep ["width","+",D.dullyellow "200"]
1278 , ""
1279 , D.indent 4 $ D.fillSep [D.blue "Nothing","->"]
1280 , D.indent 6 $ D.fillSep [D.dullyellow "400"]
1282 , D.reflow $
1283 "This defines a `getWidth` function that we can use elsewhere in our program."
1286 "if" ->
1287 D.stack
1288 [ D.reflow $
1289 "It is reserved for writing `if` expressions. Try using a different name?"
1290 , D.toSimpleNote $
1291 "If you are trying to write an `if` expression, it needs to be part of a\
1292 \ definition. So you could write something like this instead:"
1293 , D.vcat $
1294 [ D.indent 0 $ D.fillSep [D.green "reviewPowerLevel","powerLevel","="]
1295 , D.indent 2 $ D.fillSep $
1296 [D.cyan "if","powerLevel",">",D.dullyellow "9000"
1297 ,D.cyan "then",D.dullyellow "\"OVER 9000!!!\""
1298 ,D.cyan "else",D.dullyellow "\"not bad\""
1301 , D.reflow $
1302 "This defines a `reviewPowerLevel` function that we can use elsewhere in our program."
1305 _ ->
1306 D.reflow $
1307 "It is a reserved word. Try changing the name to something else?"
1310 _ ->
1311 let
1312 region = toRegion row col
1313 in
1314 Report.Report "SYNTAX PROBLEM" region [] $
1315 Code.toSnippet source region Nothing
1317 D.reflow $
1318 "I was expecting to see a new declaration here:"
1320 D.stack
1321 [ D.reflow $
1322 "I am not sure what is going wrong exactly, but here are a couple valid\
1323 \ declarations for reference:"
1324 , D.vcat
1325 [ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
1326 , D.fillSep [D.green "add","x","y","="]
1327 , D.fillSep [" ","x","+","y"]
1329 , D.fillSep [D.cyan "type",D.green "User","=","Anonymous","|","LoggedIn String"]
1330 , D.reflow $
1331 "Note that all declarations start with lower-case letters in Elm. Capitalization\
1332 \ makes a difference, so be consious of that if you are working from examples!"
1336 DeclSpace space row col ->
1337 toSpaceReport source space row col
1339 Port port_ row col ->
1340 toPortReport source port_ row col
1342 DeclType declType row col ->
1343 toDeclTypeReport source declType row col
1345 DeclDef name declDef row col ->
1346 toDeclDefReport source name declDef row col
1348 DeclFreshLineAfterDocComment row col ->
1349 let
1350 region = toRegion row col
1351 in
1352 Report.Report "EXPECTING DECLARATION" region [] $
1353 Code.toSnippet source region Nothing
1355 D.reflow $
1356 "I just saw a doc comment, but then I got stuck here:"
1358 D.reflow $
1359 "I was expecting to see the corresponding declaration next, starting on a fresh\
1360 \ line with no indentation."
1365-- PORT
1368toPortReport :: Code.Source -> Port -> Row -> Col -> Report.Report
1369toPortReport source port_ startRow startCol =
1370 case port_ of
1371 PortSpace space row col ->
1372 toSpaceReport source space row col
1374 PortName row col ->
1375 case Code.whatIsNext source row col of
1376 Code.Keyword keyword ->
1377 let
1378 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1379 region = toKeywordRegion row col keyword
1380 in
1381 Report.Report "RESERVED WORD" region [] $
1382 Code.toSnippet source surroundings (Just region)
1384 D.reflow $
1385 "I cannot handle ports with names like this:"
1387 D.reflow $
1388 "You are trying to make a port named `" ++ keyword
1389 ++ "` but that is a reserved word. Try using some other name?"
1392 _ ->
1393 let
1394 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1395 region = toRegion row col
1396 in
1397 Report.Report "PORT PROBLEM" region [] $
1398 Code.toSnippet source surroundings (Just region)
1400 D.reflow $
1401 "I just saw the start of a `port` declaration, but then I got stuck here:"
1403 D.stack
1404 [ D.fillSep
1405 ["I","was","expecting","to","see","a","name","like"
1406 ,D.dullyellow "send","or",D.dullyellow "receive","next."
1407 ,"Something","that","starts","with","a","lower-case","letter."
1409 , portNote
1413 PortColon row col ->
1414 let
1415 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1416 region = toRegion row col
1417 in
1418 Report.Report "PORT PROBLEM" region [] $
1419 Code.toSnippet source surroundings (Just region)
1421 D.reflow $
1422 "I just saw the start of a `port` declaration, but then I got stuck here:"
1424 D.stack
1425 [ D.reflow $
1426 "I was expecting to see a colon next. And then a type that tells me\
1427 \ what type of values are going to flow through."
1428 , portNote
1432 PortType tipe row col ->
1433 toTypeReport source TC_Port tipe row col
1435 PortIndentName row col ->
1436 let
1437 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1438 region = toRegion row col
1439 in
1440 Report.Report "UNFINISHED PORT" region [] $
1441 Code.toSnippet source surroundings (Just region)
1443 D.reflow $
1444 "I just saw the start of a `port` declaration, but then I got stuck here:"
1446 D.stack
1447 [ D.fillSep
1448 ["I","was","expecting","to","see","a","name","like"
1449 ,D.dullyellow "send","or",D.dullyellow "receive","next."
1450 ,"Something","that","starts","with","a","lower-case","letter."
1452 , portNote
1456 PortIndentColon row col ->
1457 let
1458 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1459 region = toRegion row col
1460 in
1461 Report.Report "UNFINISHED PORT" region [] $
1462 Code.toSnippet source surroundings (Just region)
1464 D.reflow $
1465 "I just saw the start of a `port` declaration, but then I got stuck here:"
1467 D.stack
1468 [ D.reflow $
1469 "I was expecting to see a colon next. And then a type that tells me\
1470 \ what type of values are going to flow through."
1471 , portNote
1475 PortIndentType row col ->
1476 let
1477 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1478 region = toRegion row col
1479 in
1480 Report.Report "UNFINISHED PORT" region [] $
1481 Code.toSnippet source surroundings (Just region)
1483 D.reflow $
1484 "I just saw the start of a `port` declaration, but then I got stuck here:"
1486 D.stack
1487 [ D.reflow $
1488 "I was expecting to see a type next. Here are examples of outgoing and\
1489 \ incoming ports for reference:"
1490 , D.vcat
1491 [ D.fillSep [D.cyan "port","send",":","String -> Cmd msg"]
1492 , D.fillSep [D.cyan "port","receive",":","(String -> msg) -> Sub msg"]
1494 , D.reflow $
1495 "The first line defines a `send` port so you can send strings out to JavaScript.\
1496 \ Maybe you send them on a WebSocket or put them into IndexedDB. The second line\
1497 \ defines a `receive` port so you can receive strings from JavaScript. Maybe you\
1498 \ get receive messages when new WebSocket messages come in or when an entry in\
1499 \ IndexedDB changes for some external reason."
1504portNote :: D.Doc
1505portNote =
1506 D.stack
1507 [ D.toSimpleNote $
1508 "Here are some example `port` declarations for reference:"
1509 , D.vcat
1510 [ D.fillSep [D.cyan "port","send",":","String -> Cmd msg"]
1511 , D.fillSep [D.cyan "port","receive",":","(String -> msg) -> Sub msg"]
1513 , D.reflow $
1514 "The first line defines a `send` port so you can send strings out to JavaScript.\
1515 \ Maybe you send them on a WebSocket or put them into IndexedDB. The second line\
1516 \ defines a `receive` port so you can receive strings from JavaScript. Maybe you\
1517 \ get receive messages when new WebSocket messages come in or when the IndexedDB\
1518 \ is changed for some external reason."
1523-- DECL TYPE
1526toDeclTypeReport :: Code.Source -> DeclType -> Row -> Col -> Report.Report
1527toDeclTypeReport source declType startRow startCol =
1528 case declType of
1529 DT_Space space row col ->
1530 toSpaceReport source space row col
1532 DT_Name row col ->
1533 let
1534 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1535 region = toRegion row col
1536 in
1537 Report.Report "EXPECTING TYPE NAME" region [] $
1538 Code.toSnippet source surroundings (Just region)
1540 D.reflow $
1541 "I think I am parsing a type declaration, but I got stuck here:"
1543 D.stack
1544 [ D.fillSep $
1545 ["I","was","expecting","a","name","like",D.dullyellow "Status","or",D.dullyellow "Style"
1546 ,"next.","Just","make","sure","it","is","a","name","that","starts","with","a","capital","letter!"
1548 , customTypeNote
1552 DT_Alias typeAlias row col ->
1553 toTypeAliasReport source typeAlias row col
1555 DT_Union customType row col ->
1556 toCustomTypeReport source customType row col
1558 DT_IndentName row col ->
1559 let
1560 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1561 region = toRegion row col
1562 in
1563 Report.Report "EXPECTING TYPE NAME" region [] $
1564 Code.toSnippet source surroundings (Just region)
1566 D.reflow $
1567 "I think I am parsing a type declaration, but I got stuck here:"
1569 D.stack
1570 [ D.fillSep $
1571 ["I","was","expecting","a","name","like",D.dullyellow "Status","or",D.dullyellow "Style"
1572 ,"next.","Just","make","sure","it","is","a","name","that","starts","with","a","capital","letter!"
1574 , customTypeNote
1579toTypeAliasReport :: Code.Source -> TypeAlias -> Row -> Col -> Report.Report
1580toTypeAliasReport source typeAlias startRow startCol =
1581 case typeAlias of
1582 AliasSpace space row col ->
1583 toSpaceReport source space row col
1585 AliasName row col ->
1586 let
1587 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1588 region = toRegion row col
1589 in
1590 Report.Report "EXPECTING TYPE ALIAS NAME" region [] $
1591 Code.toSnippet source surroundings (Just region)
1593 D.reflow $
1594 "I am partway through parsing a type alias, but I got stuck here:"
1596 D.stack
1597 [ D.fillSep $
1598 ["I","was","expecting","a","name","like",D.dullyellow "Person","or",D.dullyellow "Point"
1599 ,"next.","Just","make","sure","it","is","a","name","that","starts","with","a","capital","letter!"
1601 , typeAliasNote
1605 AliasEquals row col ->
1606 case Code.whatIsNext source row col of
1607 Code.Keyword keyword ->
1608 let
1609 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1610 region = toKeywordRegion row col keyword
1611 in
1612 Report.Report "RESERVED WORD" region [] $
1613 Code.toSnippet source surroundings (Just region)
1615 D.reflow $
1616 "I ran into a reserved word unexpectedly while parsing this type alias:"
1618 D.stack
1619 [ D.reflow $
1620 "It looks like you are trying use `" ++ keyword
1621 ++ "` as a type variable, but it is a reserved word. Try using a different name?"
1622 , typeAliasNote
1626 _ ->
1627 let
1628 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1629 region = toRegion row col
1630 in
1631 Report.Report "PROBLEM IN TYPE ALIAS" region [] $
1632 Code.toSnippet source surroundings (Just region)
1634 D.reflow $
1635 "I am partway through parsing a type alias, but I got stuck here:"
1637 D.stack
1638 [ D.reflow $
1639 "I was expecting to see a type variable or an an equals sign next."
1640 , typeAliasNote
1644 AliasBody tipe row col ->
1645 toTypeReport source TC_TypeAlias tipe row col
1647 AliasIndentEquals row col ->
1648 let
1649 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1650 region = toRegion row col
1651 in
1652 Report.Report "UNFINISHED TYPE ALIAS" region [] $
1653 Code.toSnippet source surroundings (Just region)
1655 D.reflow $
1656 "I am partway through parsing a type alias, but I got stuck here:"
1658 D.stack
1659 [ D.reflow $
1660 "I was expecting to see a type variable or an an equals sign next."
1661 , typeAliasNote
1665 AliasIndentBody row col ->
1666 let
1667 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1668 region = toRegion row col
1669 in
1670 Report.Report "UNFINISHED TYPE ALIAS" region [] $
1671 Code.toSnippet source surroundings (Just region)
1673 D.reflow $
1674 "I am partway through parsing a type alias, but I got stuck here:"
1676 D.stack
1677 [ D.fillSep $
1678 ["I","was","expecting","to","see","a","type","next.","Something","as","simple"
1679 ,"as",D.dullyellow "Int","or",D.dullyellow "Float","would","work!"
1681 , typeAliasNote
1686typeAliasNote :: D.Doc
1687typeAliasNote =
1688 D.stack
1689 [ D.toSimpleNote $
1690 "Here is an example of a valid `type alias` for reference:"
1691 , D.vcat $
1692 [ D.indent 0 $ D.fillSep [D.cyan "type",D.cyan "alias",D.green "Person","="]
1693 , D.indent 2 $ D.vcat $
1694 ["{ name : String"
1695 ,", age : Int"
1696 ,", height : Float"
1697 ,"}"
1700 , D.reflow $
1701 "This would let us use `Person` as a shorthand for that record type. Using this\
1702 \ shorthand makes type annotations much easier to read, and makes changing code\
1703 \ easier if you decide later that there is more to a person than age and height!"
1707toCustomTypeReport :: Code.Source -> CustomType -> Row -> Col -> Report.Report
1708toCustomTypeReport source customType startRow startCol =
1709 case customType of
1710 CT_Space space row col ->
1711 toSpaceReport source space row col
1713 CT_Name row col ->
1714 let
1715 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1716 region = toRegion row col
1717 in
1718 Report.Report "EXPECTING TYPE NAME" region [] $
1719 Code.toSnippet source surroundings (Just region)
1721 D.reflow $
1722 "I think I am parsing a type declaration, but I got stuck here:"
1724 D.stack
1725 [ D.fillSep $
1726 ["I","was","expecting","a","name","like",D.dullyellow "Status","or",D.dullyellow "Style"
1727 ,"next.","Just","make","sure","it","is","a","name","that","starts","with","a","capital","letter!"
1729 , customTypeNote
1733 CT_Equals row col ->
1734 case Code.whatIsNext source row col of
1735 Code.Keyword keyword ->
1736 let
1737 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1738 region = toKeywordRegion row col keyword
1739 in
1740 Report.Report "RESERVED WORD" region [] $
1741 Code.toSnippet source surroundings (Just region)
1743 D.reflow $
1744 "I ran into a reserved word unexpectedly while parsing this custom type:"
1746 D.stack
1747 [ D.reflow $
1748 "It looks like you are trying use `" ++ keyword
1749 ++ "` as a type variable, but it is a reserved word. Try using a different name?"
1750 , customTypeNote
1754 _ ->
1755 let
1756 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1757 region = toRegion row col
1758 in
1759 Report.Report "PROBLEM IN CUSTOM TYPE" region [] $
1760 Code.toSnippet source surroundings (Just region)
1762 D.reflow $
1763 "I am partway through parsing a custom type, but I got stuck here:"
1765 D.stack
1766 [ D.reflow $
1767 "I was expecting to see a type variable or an an equals sign next."
1768 , customTypeNote
1772 CT_Bar row col ->
1773 let
1774 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1775 region = toRegion row col
1776 in
1777 Report.Report "PROBLEM IN CUSTOM TYPE" region [] $
1778 Code.toSnippet source surroundings (Just region)
1780 D.reflow $
1781 "I am partway through parsing a custom type, but I got stuck here:"
1783 D.stack
1784 [ D.reflow $
1785 "I was expecting to see a vertical bar like | next."
1786 , customTypeNote
1790 CT_Variant row col ->
1791 let
1792 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1793 region = toRegion row col
1794 in
1795 Report.Report "PROBLEM IN CUSTOM TYPE" region [] $
1796 Code.toSnippet source surroundings (Just region)
1798 D.reflow $
1799 "I am partway through parsing a custom type, but I got stuck here:"
1801 D.stack
1802 [ D.fillSep $
1803 ["I","was","expecting","to","see","a","variant","name","next."
1804 ,"Something","like",D.dullyellow "Success","or",D.dullyellow "Sandwich" <> "."
1805 ,"Any","name","that","starts","with","a","capital","letter","really!"
1807 , customTypeNote
1811 CT_VariantArg tipe row col ->
1812 toTypeReport source TC_CustomType tipe row col
1814 CT_IndentEquals row col ->
1815 let
1816 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1817 region = toRegion row col
1818 in
1819 Report.Report "UNFINISHED CUSTOM TYPE" region [] $
1820 Code.toSnippet source surroundings (Just region)
1822 D.reflow $
1823 "I am partway through parsing a custom type, but I got stuck here:"
1825 D.stack
1826 [ D.reflow $
1827 "I was expecting to see a type variable or an an equals sign next."
1828 , customTypeNote
1832 CT_IndentBar row col ->
1833 let
1834 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1835 region = toRegion row col
1836 in
1837 Report.Report "UNFINISHED CUSTOM TYPE" region [] $
1838 Code.toSnippet source surroundings (Just region)
1840 D.reflow $
1841 "I am partway through parsing a custom type, but I got stuck here:"
1843 D.stack
1844 [ D.reflow $
1845 "I was expecting to see a vertical bar like | next."
1846 , customTypeNote
1850 CT_IndentAfterBar row col ->
1851 let
1852 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1853 region = toRegion row col
1854 in
1855 Report.Report "UNFINISHED CUSTOM TYPE" region [] $
1856 Code.toSnippet source surroundings (Just region)
1858 D.reflow $
1859 "I am partway through parsing a custom type, but I got stuck here:"
1861 D.stack
1862 [ D.reflow $
1863 "I just saw a vertical bar, so I was expecting to see another variant defined next."
1864 , customTypeNote
1868 CT_IndentAfterEquals row col ->
1869 let
1870 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1871 region = toRegion row col
1872 in
1873 Report.Report "UNFINISHED CUSTOM TYPE" region [] $
1874 Code.toSnippet source surroundings (Just region)
1876 D.reflow $
1877 "I am partway through parsing a custom type, but I got stuck here:"
1879 D.stack
1880 [ D.reflow $
1881 "I just saw an equals sign, so I was expecting to see the first variant defined next."
1882 , customTypeNote
1887customTypeNote :: D.Doc
1888customTypeNote =
1889 D.stack
1890 [ D.toSimpleNote $
1891 "Here is an example of a valid `type` declaration for reference:"
1892 , D.vcat $
1893 [ D.indent 0 $ D.fillSep [D.cyan "type",D.green "Status"]
1894 , D.indent 2 $ D.fillSep ["=","Failure"]
1895 , D.indent 2 $ D.fillSep ["|","Waiting"]
1896 , D.indent 2 $ D.fillSep ["|","Success","String"]
1898 , D.reflow $
1899 "This defines a new `Status` type with three variants. This could be useful if\
1900 \ we are waiting for an HTTP request. Maybe we start with `Waiting` and then\
1901 \ switch to `Failure` or `Success \"message from server\"` depending on how\
1902 \ things go. Notice that the Success variant has some associated data, allowing\
1903 \ us to store a String if the request goes well!"
1908-- DECL DEF
1911toDeclDefReport :: Code.Source -> Name.Name -> DeclDef -> Row -> Col -> Report.Report
1912toDeclDefReport source name declDef startRow startCol =
1913 case declDef of
1914 DeclDefSpace space row col ->
1915 toSpaceReport source space row col
1917 DeclDefEquals row col ->
1918 case Code.whatIsNext source row col of
1919 Code.Keyword keyword ->
1920 let
1921 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1922 region = toKeywordRegion row col keyword
1923 in
1924 Report.Report "RESERVED WORD" region [] $
1925 Code.toSnippet source surroundings (Just region)
1927 D.reflow $
1928 "It looks like you are trying to use `" ++ keyword ++ "` as an argument:"
1930 D.reflow $
1931 "This is a reserved word! Try using some other name?"
1934 Code.Operator op ->
1935 let
1936 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1937 region = toKeywordRegion row col op
1938 in
1939 Report.Report "UNEXPECTED SYMBOL" region [] $
1940 Code.toSnippet source surroundings (Just region)
1942 D.reflow $
1943 "I was not expecting to see this symbol here:"
1945 D.stack
1946 [ D.reflow $
1947 "I am not sure what is going wrong exactly, so here is a valid\
1948 \ definition (with an optional type annotation) for reference:"
1949 , D.vcat
1950 [ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
1951 , D.fillSep [D.green "add","x","y","="]
1952 , D.fillSep [" ","x","+","y"]
1954 , D.reflow $
1955 "Try to use that format with your `" ++ Name.toChars name ++ "` definition!"
1959 _ ->
1960 let
1961 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1962 region = toRegion row col
1963 in
1964 Report.Report "PROBLEM IN DEFINITION" region [] $
1965 Code.toSnippet source surroundings (Just region)
1967 D.reflow $
1968 "I got stuck while parsing the `" ++ Name.toChars name ++ "` definition:"
1970 D.stack
1971 [ D.reflow $
1972 "I am not sure what is going wrong exactly, so here is a valid\
1973 \ definition (with an optional type annotation) for reference:"
1974 , D.vcat
1975 [ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
1976 , D.fillSep [D.green "add","x","y","="]
1977 , D.fillSep [" ","x","+","y"]
1979 , D.reflow $
1980 "Try to use that format!"
1984 DeclDefType tipe row col ->
1985 toTypeReport source (TC_Annotation name) tipe row col
1987 DeclDefArg pattern row col ->
1988 toPatternReport source PArg pattern row col
1990 DeclDefBody expr row col ->
1991 toExprReport source (InDef name startRow startCol) expr row col
1993 DeclDefNameRepeat row col ->
1994 let
1995 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1996 region = toRegion row col
1997 in
1998 Report.Report "EXPECTING DEFINITION" region [] $
1999 Code.toSnippet source surroundings (Just region)
2001 D.reflow $
2002 "I just saw the type annotation for `" ++ Name.toChars name
2003 ++ "` so I was expecting to see its definition here:"
2005 D.stack
2006 [ D.reflow $
2007 "Type annotations always appear directly above the relevant\
2008 \ definition, without anything else (even doc comments) in between."
2009 , declDefNote
2013 DeclDefNameMatch defName row col ->
2014 let
2015 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2016 region = toRegion row col
2017 in
2018 Report.Report "NAME MISMATCH" region [] $
2019 Code.toSnippet source surroundings (Just region)
2021 D.reflow $
2022 "I just saw a type annotation for `" ++ Name.toChars name ++ "`, but it is followed by a definition for `" ++ Name.toChars defName ++ "`:"
2024 D.stack
2025 [ D.reflow $
2026 "These names do not match! Is there a typo?"
2027 , D.indent 4 $ D.fillSep $
2028 [D.dullyellow (D.fromName defName),"->",D.green (D.fromName name)]
2032 DeclDefIndentType row col ->
2033 let
2034 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2035 region = toRegion row col
2036 in
2037 Report.Report "UNFINISHED DEFINITION" region [] $
2038 Code.toSnippet source surroundings (Just region)
2040 D.reflow $
2041 "I got stuck while parsing the `" ++ Name.toChars name ++ "` type annotation:"
2043 D.stack
2044 [ D.reflow $
2045 "I just saw a colon, so I am expecting to see a type next."
2046 , declDefNote
2050 DeclDefIndentEquals row col ->
2051 let
2052 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2053 region = toRegion row col
2054 in
2055 Report.Report "UNFINISHED DEFINITION" region [] $
2056 Code.toSnippet source surroundings (Just region)
2058 D.reflow $
2059 "I got stuck while parsing the `" ++ Name.toChars name ++ "` definition:"
2061 D.stack
2062 [ D.reflow $
2063 "I was expecting to see an argument or an equals sign next."
2064 , declDefNote
2068 DeclDefIndentBody row col ->
2069 let
2070 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2071 region = toRegion row col
2072 in
2073 Report.Report "UNFINISHED DEFINITION" region [] $
2074 Code.toSnippet source surroundings (Just region)
2076 D.reflow $
2077 "I got stuck while parsing the `" ++ Name.toChars name ++ "` definition:"
2079 D.stack
2080 [ D.reflow $
2081 "I was expecting to see an expression next. What is it equal to?"
2082 , declDefNote
2087declDefNote :: D.Doc
2088declDefNote =
2089 D.stack
2090 [ D.reflow $
2091 "Here is a valid definition (with a type annotation) for reference:"
2092 , D.vcat
2093 [ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
2094 , D.fillSep [D.green "add","x","y","="]
2095 , D.fillSep [" ","x","+","y"]
2097 , D.reflow $
2098 "The top line (called a \"type annotation\") is optional. You can leave it off\
2099 \ if you want. As you get more comfortable with Elm and as your project grows,\
2100 \ it becomes more and more valuable to add them though! They work great as\
2101 \ compiler-verified documentation, and they often improve error messages!"
2106-- CONTEXT
2109data Context
2110 = InNode Node Row Col Context
2111 | InDef Name.Name Row Col
2114data Node
2115 = NRecord
2116 | NParens
2117 | NList
2118 | NFunc
2119 | NCond
2120 | NThen
2121 | NElse
2122 | NCase
2123 | NBranch
2124 deriving (Eq)
2127getDefName :: Context -> Name.Name
2128getDefName context =
2129 case context of
2130 InDef name _ _ -> name
2131 InNode _ _ _ c -> getDefName c
2134isWithin :: Node -> Context -> Bool
2135isWithin desiredNode context =
2136 case context of
2137 InDef _ _ _ -> False
2138 InNode actualNode _ _ _ -> desiredNode == actualNode
2142-- EXPR REPORTS
2145toExprReport :: Code.Source -> Context -> Expr -> Row -> Col -> Report.Report
2146toExprReport source context expr startRow startCol =
2147 case expr of
2148 Let let_ row col ->
2149 toLetReport source context let_ row col
2151 Case case_ row col ->
2152 toCaseReport source context case_ row col
2154 If if_ row col ->
2155 toIfReport source context if_ row col
2157 List list row col ->
2158 toListReport source context list row col
2160 Record record row col ->
2161 toRecordReport source context record row col
2163 Tuple tuple row col ->
2164 toTupleReport source context tuple row col
2166 Func func row col ->
2167 toFuncReport source context func row col
2169 Dot row col ->
2170 let region = toRegion row col in
2171 Report.Report "EXPECTING RECORD ACCESSOR" region [] $
2172 Code.toSnippet source region Nothing
2174 D.reflow $
2175 "I was expecting to see a record accessor here:"
2177 D.fillSep
2178 ["Something","like",D.dullyellow".name","or",D.dullyellow".price"
2179 ,"that","accesses","a","value","from","a","record."
2183 Access row col ->
2184 let region = toRegion row col in
2185 Report.Report "EXPECTING RECORD ACCESSOR" region [] $
2186 Code.toSnippet source region Nothing
2188 D.reflow $
2189 "I am trying to parse a record accessor here:"
2191 D.stack
2193 D.fillSep
2194 ["Something","like",D.dullyellow".name","or",D.dullyellow".price"
2195 ,"that","accesses","a","value","from","a","record."
2198 D.toSimpleNote $
2199 "Record field names must start with a lower case letter!"
2203 OperatorRight op row col ->
2204 let region = toRegion row col in
2205 Report.Report "MISSING EXPRESSION" region [] $
2206 Code.toSnippet source region Nothing
2208 D.reflow $
2209 "I was expecting to see an expression after this " ++ Name.toChars op ++ " operator:"
2211 D.stack
2212 [ D.fillSep $
2213 ["You","can","just","put","anything","for","now,","like"
2214 ,D.dullyellow "42","or",D.dullyellow"\"hello\"" <> "."
2215 ,"Once","there","is","something","there,","I","can","probably"
2216 ,"give","a","more","specific","hint!"
2218 , D.toSimpleNote $
2219 "This can also happen if run into reserved words like `let` or `as` unexpectedly.\
2220 \ Or if I run into operators in unexpected spots. Point is, there are a\
2221 \ couple ways I can get confused and give sort of weird advice!"
2225 OperatorReserved operator row col ->
2226 toOperatorReport source context operator row col
2228 Start row col ->
2229 let
2230 (contextRow, contextCol, aThing) =
2231 case context of
2232 InDef name r c -> (r, c, "the `" ++ Name.toChars name ++ "` definition")
2233 InNode NRecord r c _ -> (r, c, "a record")
2234 InNode NParens r c _ -> (r, c, "some parentheses")
2235 InNode NList r c _ -> (r, c, "a list")
2236 InNode NFunc r c _ -> (r, c, "an anonymous function")
2237 InNode NCond r c _ -> (r, c, "an `if` expression")
2238 InNode NThen r c _ -> (r, c, "an `if` expression")
2239 InNode NElse r c _ -> (r, c, "an `if` expression")
2240 InNode NCase r c _ -> (r, c, "a `case` expression")
2241 InNode NBranch r c _ -> (r, c, "a `case` expression")
2242 -- TODO check if this is actually the best way to get error messages here
2244 surroundings = A.Region (A.Position contextRow contextCol) (A.Position row col)
2245 region = toRegion row col
2246 in
2247 Report.Report "MISSING EXPRESSION" region [] $
2248 Code.toSnippet source surroundings (Just region)
2250 D.reflow $
2251 "I am partway through parsing " ++ aThing ++ ", but I got stuck here:"
2253 D.stack
2254 [ D.fillSep $
2255 ["I","was","expecting","to","see","an","expression","like"
2256 ,D.dullyellow "42","or",D.dullyellow"\"hello\"" <> "."
2257 ,"Once","there","is","something","there,","I","can","probably"
2258 ,"give","a","more","specific","hint!"
2260 , D.toSimpleNote $
2261 "This can also happen if run into reserved words like `let` or `as` unexpectedly.\
2262 \ Or if I run into operators in unexpected spots. Point is, there are a\
2263 \ couple ways I can get confused and give sort of weird advice!"
2267 Char char row col ->
2268 toCharReport source char row col
2270 String string row col ->
2271 toStringReport source string row col
2273 Number number row col ->
2274 toNumberReport source number row col
2276 Space space row col ->
2277 toSpaceReport source space row col
2279 EndlessShader row col ->
2280 let
2281 region = toWiderRegion row col 6
2282 in
2283 Report.Report "ENDLESS SHADER" region [] $
2284 Code.toSnippet source region Nothing
2286 D.reflow "I cannot find the end of this shader:"
2288 D.reflow "Add a |] somewhere after this to end the shader."
2291 ShaderProblem problem row col ->
2292 let
2293 region = toRegion row col
2294 in
2295 Report.Report "SHADER PROBLEM" region [] $
2296 Code.toSnippet source region Nothing
2298 D.reflow $
2299 "I ran into a problem while parsing this GLSL block."
2301 D.stack
2302 [ D.reflow $
2303 "I use a 3rd party GLSL parser for now, and I did my best to extract their error message:"
2304 , D.indent 4 $ D.vcat $
2305 map D.fromChars (filter (/="") (lines problem))
2309 IndentOperatorRight op row col ->
2310 let
2311 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2312 region = toRegion row col
2313 in
2314 Report.Report "MISSING EXPRESSION" region [] $
2315 Code.toSnippet source surroundings (Just region)
2317 D.reflow $
2318 "I was expecting to see an expression after this " ++ Name.toChars op ++ " operator:"
2320 D.stack
2322 D.fillSep $
2323 ["You","can","just","put","anything","for","now,","like"
2324 ,D.dullyellow "42","or",D.dullyellow"\"hello\"" <> "."
2325 ,"Once","there","is","something","there,","I","can","probably"
2326 ,"give","a","more","specific","hint!"
2329 D.toSimpleNote $
2330 "I may be getting confused by your indentation? The easiest way to make sure\
2331 \ this is not an indentation problem is to put the expression on the right of\
2332 \ the " ++ Name.toChars op ++ " operator on the same line."
2336 IndentMoreExpr _ _ ->
2337 error "TODO IndentMoreExpr"
2341-- CHAR
2344toCharReport :: Code.Source -> Char -> Row -> Col -> Report.Report
2345toCharReport source char row col =
2346 case char of
2347 CharEndless ->
2348 let
2349 region = toRegion row col
2350 in
2351 Report.Report "MISSING SINGLE QUOTE" region [] $
2352 Code.toSnippet source region Nothing
2354 D.reflow $
2355 "I thought I was parsing a character, but I got to the end of\
2356 \ the line without seeing the closing single quote:"
2358 D.reflow $
2359 "Add a closing single quote here!"
2362 CharEscape escape ->
2363 toEscapeReport source escape row col
2365 CharNotString width ->
2366 let
2367 region = toWiderRegion row col width
2368 in
2369 Report.Report "NEEDS DOUBLE QUOTES" region [] $
2370 Code.toSnippet source region Nothing
2372 "The following string uses single quotes:"
2374 D.stack
2375 [ "Please switch to double quotes instead:"
2376 , D.indent 4 $
2377 D.dullyellow "'this'" <> " => " <> D.green "\"this\""
2378 , D.toSimpleNote $
2379 "Elm uses double quotes for strings like \"hello\", whereas it uses single\
2380 \ quotes for individual characters like 'a' and 'ø'. This distinction helps with\
2381 \ code like (String.any (\\c -> c == 'X') \"90210\") where you are inspecting\
2382 \ individual characters."
2388-- STRING
2391toStringReport :: Code.Source -> String -> Row -> Col -> Report.Report
2392toStringReport source string row col =
2393 case string of
2394 StringEndless_Single ->
2395 let
2396 region = toRegion row col
2397 in
2398 Report.Report "ENDLESS STRING" region [] $
2399 Code.toSnippet source region Nothing
2401 D.reflow $
2402 "I got to the end of the line without seeing the closing double quote:"
2404 D.stack
2405 [ D.fillSep $
2406 ["Strings","look","like",D.green "\"this\"","with","double"
2407 ,"quotes","on","each","end.","Is","the","closing","double"
2408 ,"quote","missing","in","your","code?"
2410 , D.link "Note" "Read" "TODO" "if you want a string that spans multiple lines."
2414 StringEndless_Multi ->
2415 let
2416 region = toWiderRegion row col 3
2417 in
2418 Report.Report "ENDLESS STRING" region [] $
2419 Code.toSnippet source region Nothing
2421 D.reflow $
2422 "I cannot find the end of this multi-line string:"
2424 D.stack
2425 [ D.reflow "Add a \"\"\" somewhere after this to end the string."
2426 , D.link "Hint" "Read" "TODO" "for more information on strings and multi-line strings."
2430 StringEscape escape ->
2431 toEscapeReport source escape row col
2435-- ESCAPES
2438toEscapeReport :: Code.Source -> Escape -> Row -> Col -> Report.Report
2439toEscapeReport source escape row col =
2440 case escape of
2441 EscapeUnknown ->
2442 let
2443 region = toWiderRegion row col 2
2444 in
2445 Report.Report "UNKNOWN ESCAPE" region [] $
2446 Code.toSnippet source region Nothing
2448 D.reflow $
2449 "Backslashes always start escaped characters, but I do not recognize this one:"
2451 D.stack
2452 [ D.reflow $
2453 "Valid escape characters include:"
2454 , D.dullyellow $ D.indent 4 $ D.vcat $
2455 [ "\\n"
2456 , "\\r"
2457 , "\\t"
2458 , "\\\""
2459 , "\\\'"
2460 , "\\\\"
2461 , "\\u{003D}"
2463 , D.reflow $
2464 "Do you want one of those instead? Maybe you need \\\\ to escape a backslash?"
2465 , D.toSimpleNote $
2466 "The last style lets encode ANY character by its Unicode code\
2467 \ point. That means \\u{0009} and \\t are the same. You can use\
2468 \ that style for anything not covered by the other six escapes!"
2472 BadUnicodeFormat width ->
2473 let
2474 region = toWiderRegion row col width
2475 in
2476 Report.Report "BAD UNICODE ESCAPE" region [] $
2477 Code.toSnippet source region Nothing
2479 D.reflow $
2480 "I ran into an invalid Unicode escape:"
2482 D.stack
2483 [ D.reflow $
2484 "Here are some examples of valid Unicode escapes:"
2485 , D.dullyellow $ D.indent 4 $ D.vcat $
2486 [ "\\u{0041}"
2487 , "\\u{03BB}"
2488 , "\\u{6728}"
2489 , "\\u{1F60A}"
2491 , D.reflow $
2492 "Notice that the code point is always surrounded by curly braces.\
2493 \ Maybe you are missing the opening or closing curly brace?"
2496 BadUnicodeCode width ->
2497 let
2498 region = toWiderRegion row col width
2499 in
2500 Report.Report "BAD UNICODE ESCAPE" region [] $
2501 Code.toSnippet source region Nothing
2503 D.reflow $
2504 "This is not a valid code point:"
2506 D.reflow $
2507 "The valid code points are between 0 and 10FFFF inclusive."
2510 BadUnicodeLength width numDigits badCode ->
2511 let
2512 region = toWiderRegion row col width
2513 in
2514 Report.Report "BAD UNICODE ESCAPE" region [] $
2515 Code.toSnippet source region Nothing $
2516 if numDigits < 4 then
2518 D.reflow $
2519 "Every code point needs at least four digits:"
2521 let
2522 goodCode = replicate (4 - numDigits) '0' ++ map Char.toUpper (showHex badCode "")
2523 suggestion = "\\u{" <> D.fromChars goodCode <> "}"
2524 in
2525 D.fillSep ["Try",D.green suggestion,"instead?"]
2528 else
2530 D.reflow $
2531 "This code point has too many digits:"
2533 D.fillSep $
2534 ["Valid","code","points","are","between"
2535 ,D.green "\\u{0000}","and",D.green "\\u{10FFFF}" <> ","
2536 ,"so","try","trimming","any","leading","zeros","until"
2537 ,"you","have","between","four","and","six","digits."
2543-- NUMBERS
2546toNumberReport :: Code.Source -> Number -> Row -> Col -> Report.Report
2547toNumberReport source number row col =
2548 let
2549 region = toRegion row col
2550 in
2551 case number of
2552 NumberEnd ->
2553 Report.Report "WEIRD NUMBER" region [] $
2554 Code.toSnippet source region Nothing
2556 D.reflow $
2557 "I thought I was reading a number, but I ran into some weird stuff here:"
2559 D.stack
2560 [ D.reflow $
2561 "I recognize numbers in the following formats:"
2562 , D.indent 4 $ D.vcat [ "42", "3.14", "6.022e23", "0x002B" ]
2563 , D.reflow $
2564 "So is there a way to write it like one of those?"
2568 NumberDot int ->
2569 Report.Report "WEIRD NUMBER" region [] $
2570 Code.toSnippet source region Nothing
2572 D.reflow $
2573 "Numbers cannot end with a dot like this:"
2575 D.fillSep
2576 ["Switching","to",D.green (D.fromChars (show int))
2577 ,"or",D.green (D.fromChars (show int ++ ".0"))
2578 ,"will","work","though!"
2582 NumberHexDigit ->
2583 Report.Report "WEIRD HEXIDECIMAL" region [] $
2584 Code.toSnippet source region Nothing
2586 D.reflow $
2587 "I thought I was reading a hexidecimal number until I got here:"
2589 D.stack
2590 [ D.reflow $
2591 "Valid hexidecimal digits include 0123456789abcdefABCDEF, so I can\
2592 \ only recognize things like this:"
2593 , D.indent 4 $ D.vcat [ "0x2B", "0x002B", "0x00ffb3" ]
2597 NumberNoLeadingZero ->
2598 Report.Report "LEADING ZEROS" region [] $
2599 Code.toSnippet source region Nothing
2601 D.reflow $
2602 "I do not accept numbers with leading zeros:"
2604 D.stack
2605 [ D.reflow $
2606 "Just delete the leading zeros and it should work!"
2607 , D.toSimpleNote $
2608 "Some languages let you to specify octal numbers by adding a leading zero.\
2609 \ So in C, writing 0111 is the same as writing 73. Some people are used to\
2610 \ that, but others probably want it to equal 111. Either path is going to\
2611 \ surprise people from certain backgrounds, so Elm tries to avoid this whole\
2612 \ situation."
2618-- OPERATORS
2621toOperatorReport :: Code.Source -> Context -> BadOperator -> Row -> Col -> Report.Report
2622toOperatorReport source context operator row col =
2623 case operator of
2624 BadDot ->
2625 let
2626 region = toRegion row col
2627 in
2628 Report.Report "UNEXPECTED SYMBOL" region [] $
2629 Code.toSnippet source region Nothing
2631 "I was not expecting this dot:"
2633 D.reflow $
2634 "Dots are for record access and decimal points, so\
2635 \ they cannot float around on their own. Maybe\
2636 \ there is some extra whitespace?"
2639 BadPipe ->
2640 let
2641 region = toRegion row col
2642 in
2643 Report.Report "UNEXPECTED SYMBOL" region [] $
2644 Code.toSnippet source region Nothing
2646 D.reflow $
2647 "I was not expecting this vertical bar:"
2649 D.reflow $
2650 "Vertical bars should only appear in custom type declarations. Maybe you want || instead?"
2653 BadArrow ->
2654 let
2655 region = toWiderRegion row col 2
2656 in
2657 Report.Report "UNEXPECTED ARROW" region [] $
2658 Code.toSnippet source region Nothing $
2659 if isWithin NBranch context then
2661 D.reflow $
2662 "I was not expecting to see an arrow here:"
2664 D.stack
2666 D.reflow $
2667 "I think I am parsing a `case` expression right now, so it makes sense to\
2668 \ see arrows around here. This one is confusing me though!"
2670 D.toSimpleHint $
2671 "I may be getting confused by the indentation. Every pattern in a `case` must be\
2672 \ exactly aligned (with exactly the same amount of indentation) so maybe this arrow\
2673 \ appears after the next `case` pattern (correctly!) but the pattern itself is\
2674 \ indented too far?"
2678 else
2680 D.reflow $
2681 "I was not expecting an arrow here:"
2683 D.reflow $
2684 "Arrows should only appear in `case` expressions and anonymous functions. Maybe\
2685 \ you want > or >= instead?"
2688 BadEquals ->
2689 let
2690 region = toRegion row col
2691 name = getDefName context
2692 in
2693 Report.Report "UNEXPECTED EQUALS" region [] $
2694 Code.toSnippet source region Nothing
2696 D.reflow $
2697 "I was not expecting to see this equals sign:"
2699 D.stack
2701 D.reflow "Maybe you want == instead? To check if two values are equal?"
2703 D.toSimpleNote $
2704 if isWithin NRecord context then
2705 "Records look like { x = 3, y = 4 } with the equals sign right\
2706 \ after the field name. So maybe you forgot a comma?"
2707 else
2708 "I may be getting confused by your indentation. Is this supposed to be part of\
2709 \ a definition AFTER the `" ++ Name.toChars name ++ "` definition? If so,\
2710 \ the problem may be a bit before the equals sign. I need all definitions to\
2711 \ be exactly aligned (with exactly the same indentation) so the problem may be that\
2712 \ this new definition is indented a bit too much."
2716 BadHasType ->
2717 let
2718 region = toRegion row col
2719 name = getDefName context
2720 in
2721 Report.Report "UNEXPECTED SYMBOL" region [] $
2722 Code.toSnippet source region Nothing $
2724 D.reflow $
2725 "I was not expecting to run into the \"has type\" symbol here:"
2727 D.stack
2729 D.fillSep
2730 ["Maybe","you","want",D.green "::","instead?"
2731 ,"To","put","something","on","the","front","of","a","list?"
2733 , D.toSimpleNote $
2734 "The single colon is reserved for type annotations and record types, but I think\
2735 \ I am parsing the definition of `" ++ Name.toChars name ++ "` right now."
2737 D.toSimpleNote $
2738 "I may be getting confused by your indentation. Is this supposed to be part of\
2739 \ a type annotation AFTER the `" ++ Name.toChars name ++ "` definition? If so,\
2740 \ the problem may be a bit before the \"has type\" symbol. I need all definitions to\
2741 \ be exactly aligned (with exactly the same indentation) so the problem may be that\
2742 \ this new definition is indented a bit too much."
2748-- CASE
2751toLetReport :: Code.Source -> Context -> Let -> Row -> Col -> Report.Report
2752toLetReport source context let_ startRow startCol =
2753 case let_ of
2754 LetSpace space row col ->
2755 toSpaceReport source space row col
2757 LetIn row col ->
2758 let
2759 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2760 region = toRegion row col
2761 in
2762 Report.Report "LET PROBLEM" region [] $
2763 Code.toSnippet source surroundings (Just region)
2765 D.reflow $
2766 "I was partway through parsing a `let` expression, but I got stuck here:"
2768 D.stack
2769 [ D.fillSep $
2770 ["Based","on","the","indentation,","I","was","expecting","to","see","the",D.cyan "in"
2771 ,"keyword","next.","Is","there","a","typo?"
2773 , D.toSimpleNote $
2774 "This can also happen if you are trying to define another value within the `let` but\
2775 \ it is not indented enough. Make sure each definition has exactly the same amount of\
2776 \ spaces before it. They should line up exactly!"
2780 LetDefAlignment _ 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 "LET PROBLEM" region [] $
2786 Code.toSnippet source surroundings (Just region)
2788 D.reflow $
2789 "I was partway through parsing a `let` expression, but I got stuck here:"
2791 D.stack
2792 [ D.fillSep $
2793 ["Based","on","the","indentation,","I","was","expecting","to","see","the",D.cyan "in"
2794 ,"keyword","next.","Is","there","a","typo?"
2796 , D.toSimpleNote $
2797 "This can also happen if you are trying to define another value within the `let` but\
2798 \ it is not indented enough. Make sure each definition has exactly the same amount of\
2799 \ spaces before it. The should line up exactly!"
2803 LetDefName row col ->
2804 case Code.whatIsNext source row col of
2805 Code.Keyword keyword ->
2806 let
2807 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2808 region = toKeywordRegion row col keyword
2809 in
2810 Report.Report "RESERVED WORD" region [] $
2811 Code.toSnippet source surroundings (Just region)
2813 D.reflow $
2814 "I was partway through parsing a `let` expression, but I got stuck here:"
2816 D.reflow $
2817 "It looks like you are trying to use `" ++ keyword ++ "` as a variable name, but\
2818 \ it is a reserved word! Try using a different name instead."
2821 _ ->
2822 toUnfinishLetReport source row col startRow startCol $
2823 D.reflow $
2824 "I was expecting the name of a definition next."
2826 LetDef name def row col ->
2827 error "TODO LetDef" name def row col
2829 LetDestruct destruct row col ->
2830 error "TODO LetDestruct" destruct row col
2832 LetBody expr row col ->
2833 toExprReport source context expr row col
2835 LetIndentDef row col ->
2836 toUnfinishLetReport source row col startRow startCol $
2837 D.reflow $
2838 "I was expecting a value to be defined here."
2840 LetIndentIn row col ->
2841 toUnfinishLetReport source row col startRow startCol $
2842 D.fillSep $
2843 ["I","was","expecting","to","see","the",D.cyan "in","keyword","next."
2844 ,"Or","maybe","more","of","that","expression?"
2847 LetIndentBody row col ->
2848 toUnfinishLetReport source row col startRow startCol $
2849 D.reflow $
2850 "I was expecting an expression next. Tell me what should happen with the value you just defined!"
2853toUnfinishLetReport :: Code.Source -> Row -> Col -> Row -> Col -> D.Doc -> Report.Report
2854toUnfinishLetReport source row col startRow startCol message =
2855 let
2856 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2857 region = toRegion row col
2858 in
2859 Report.Report "UNFINISHED LET" region [] $
2860 Code.toSnippet source surroundings (Just region)
2862 D.reflow $
2863 "I was partway through parsing a `let` expression, but I got stuck here:"
2865 D.stack
2866 [ message
2867 , D.toSimpleNote $
2868 "Here is an example with a valid `let` expression for reference:"
2869 , D.vcat $
2870 [ D.indent 0 $ D.fillSep [D.green "viewPerson","person","="]
2871 , D.indent 2 $ D.fillSep [D.cyan "let"]
2872 , D.indent 4 $ D.fillSep ["fullName","="]
2873 , D.indent 6 $ D.fillSep ["person.firstName","++",D.dullyellow "\" \"","++","person.lastName"]
2874 , D.indent 2 $ D.fillSep [D.cyan "in"]
2875 , D.indent 2 $ D.fillSep ["div","[]","[","text","fullName","]"]
2877 , D.reflow $
2878 "Here we defined a `viewPerson` function that turns a person into some HTML. We use\
2879 \ a `let` expression to define the `fullName` we want to show. Notice the indentation! The\
2880 \ `fullName` is indented more than the `let` keyword, and the actual value of `fullName` is\
2881 \ indented a bit more than that. That is important!"
2887-- CASE
2890toCaseReport :: Code.Source -> Context -> Case -> Row -> Col -> Report.Report
2891toCaseReport source context case_ startRow startCol =
2892 case case_ of
2893 CaseSpace space row col ->
2894 toSpaceReport source space row col
2896 CaseOf row col ->
2897 toUnfinishCaseReport source row col startRow startCol $
2898 D.fillSep ["I","was","expecting","to","see","the",D.dullyellow "of","keyword","next."]
2900 CasePattern pattern row col ->
2901 toPatternReport source PCase pattern row col
2903 CaseArrow row col ->
2904 case Code.whatIsNext source row col of
2905 Code.Keyword keyword ->
2906 let
2907 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2908 region = toKeywordRegion row col keyword
2909 in
2910 Report.Report "RESERVED WORD" region [] $
2911 Code.toSnippet source surroundings (Just region)
2913 D.reflow $
2914 "I am partway through parsing a `case` expression, but I got stuck here:"
2916 D.reflow $
2917 "It looks like you are trying to use `" ++ keyword ++ "` in one of your\
2918 \ patterns, but it is a reserved word. Try using a different name?"
2921 Code.Operator ":" ->
2922 let
2923 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2924 region = toRegion row col
2925 in
2926 Report.Report "UNEXPECTED OPERATOR" region [] $
2927 Code.toSnippet source surroundings (Just region)
2929 D.reflow $
2930 "I am partway through parsing a `case` expression, but I got stuck here:"
2932 D.fillSep $
2933 ["I","am","seeing",D.dullyellow ":","but","maybe","you","want",D.green "::","instead?"
2934 ,"For","pattern","matching","on","lists?"
2938 Code.Operator "=" ->
2939 let
2940 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2941 region = toRegion row col
2942 in
2943 Report.Report "UNEXPECTED OPERATOR" region [] $
2944 Code.toSnippet source surroundings (Just region)
2946 D.reflow $
2947 "I am partway through parsing a `case` expression, but I got stuck here:"
2949 D.fillSep $
2950 ["I","am","seeing",D.dullyellow "=","but","maybe","you","want",D.green "->","instead?"
2954 _ ->
2955 let
2956 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2957 region = toRegion row col
2958 in
2959 Report.Report "MISSING ARROW" region [] $
2960 Code.toSnippet source surroundings (Just region)
2962 D.reflow $
2963 "I am partway through parsing a `case` expression, but I got stuck here:"
2965 addNoteForCaseIndentError $
2966 D.reflow $
2967 "I was expecting to see an arrow next."
2970 CaseExpr expr row col ->
2971 toExprReport source (InNode NCase startRow startCol context) expr row col
2973 CaseBranch expr row col ->
2974 toExprReport source (InNode NBranch startRow startCol context) expr row col
2976 CaseIndentOf row col ->
2977 toUnfinishCaseReport source row col startRow startCol $
2978 D.fillSep ["I","was","expecting","to","see","the",D.dullyellow "of","keyword","next."]
2980 CaseIndentExpr row col ->
2981 toUnfinishCaseReport source row col startRow startCol $
2982 D.reflow "I was expecting to see a expression next."
2984 CaseIndentPattern row col ->
2985 toUnfinishCaseReport source row col startRow startCol $
2986 D.reflow "I was expecting to see a pattern next."
2988 CaseIndentArrow row col ->
2989 toUnfinishCaseReport source row col startRow startCol $
2990 D.fillSep
2991 ["I","just","saw","a","pattern,","so","I","was","expecting"
2992 ,"to","see","a",D.dullyellow "->","next."
2995 CaseIndentBranch row col ->
2996 toUnfinishCaseReport source row col startRow startCol $
2997 D.reflow $
2998 "I was expecting to see an expression next. What should I do when\
2999 \ I run into this particular pattern?"
3001 CasePatternAlignment indent row col ->
3002 toUnfinishCaseReport source row col startRow startCol $
3003 D.reflow $
3004 "I suspect this is a pattern that is not indented far enough? (" ++ show indent ++ " spaces)"
3007toUnfinishCaseReport :: Code.Source -> Row -> Col -> Row -> Col -> D.Doc -> Report.Report
3008toUnfinishCaseReport source row col startRow startCol message =
3009 let
3010 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3011 region = toRegion row col
3012 in
3013 Report.Report "UNFINISHED CASE" region [] $
3014 Code.toSnippet source surroundings (Just region)
3016 D.reflow $
3017 "I was partway through parsing a `case` expression, but I got stuck here:"
3019 D.stack
3020 [ message
3021 , D.toSimpleNote $
3022 "Here is an example of a valid `case` expression for reference."
3023 , D.vcat $
3024 [ D.indent 4 $ D.fillSep [D.cyan "case","maybeWidth",D.cyan "of"]
3025 , D.indent 6 $ D.fillSep [D.blue "Just","width","->"]
3026 , D.indent 8 $ D.fillSep ["width","+",D.dullyellow "200"]
3027 , ""
3028 , D.indent 6 $ D.fillSep [D.blue "Nothing","->"]
3029 , D.indent 8 $ D.fillSep [D.dullyellow "400"]
3031 , D.reflow $
3032 "Notice the indentation. Each pattern is aligned, and each branch is indented\
3033 \ a bit more than the corresponding pattern. That is important!"
3038addNoteForCaseIndentError :: D.Doc -> D.Doc
3039addNoteForCaseIndentError message =
3040 D.stack $
3041 message
3043 [ D.toSimpleNote $
3044 "Sometimes I get confused by indentation, so try to make your `case` look\
3045 \ something like this:"
3046 , D.vcat $
3047 [ D.indent 4 $ D.fillSep [D.cyan "case","maybeWidth",D.cyan "of"]
3048 , D.indent 6 $ D.fillSep [D.blue "Just","width","->"]
3049 , D.indent 8 $ D.fillSep ["width","+",D.dullyellow "200"]
3050 , ""
3051 , D.indent 6 $ D.fillSep [D.blue "Nothing","->"]
3052 , D.indent 8 $ D.fillSep [D.dullyellow "400"]
3054 , D.reflow $
3055 "Notice the indentation! Each pattern is aligned, and each branch is indented\
3056 \ a bit more than the corresponding pattern. That is important!"
3061-- IF
3064toIfReport :: Code.Source -> Context -> If -> Row -> Col -> Report.Report
3065toIfReport source context if_ startRow startCol =
3066 case if_ of
3067 IfSpace space row col ->
3068 toSpaceReport source space row col
3070 IfThen row col ->
3071 let
3072 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3073 region = toRegion row col
3074 in
3075 Report.Report "UNFINISHED IF" region [] $
3076 Code.toSnippet source surroundings (Just region)
3078 D.reflow $
3079 "I was expecting to see more of this `if` expression, but I got stuck here:"
3081 D.fillSep $
3082 ["I","was","expecting","to","see","the",D.cyan "then","keyword","next."
3086 IfElse row col ->
3087 let
3088 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3089 region = toRegion row col
3090 in
3091 Report.Report "UNFINISHED IF" region [] $
3092 Code.toSnippet source surroundings (Just region)
3094 D.reflow $
3095 "I was expecting to see more of this `if` expression, but I got stuck here:"
3097 D.fillSep $
3098 ["I","was","expecting","to","see","the",D.cyan "else","keyword","next."
3102 IfElseBranchStart row col ->
3103 let
3104 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3105 region = toRegion row col
3106 in
3107 Report.Report "UNFINISHED IF" region [] $
3108 Code.toSnippet source surroundings (Just region)
3110 D.reflow $
3111 "I just saw the start of an `else` branch, but then I got stuck here:"
3113 D.reflow $
3114 "I was expecting to see an expression next. Maybe it is not filled in yet?"
3117 IfCondition expr row col ->
3118 toExprReport source (InNode NCond startRow startCol context) expr row col
3120 IfThenBranch expr row col ->
3121 toExprReport source (InNode NThen startRow startCol context) expr row col
3123 IfElseBranch expr row col ->
3124 toExprReport source (InNode NElse startRow startCol context) expr row col
3126 IfIndentCondition row col ->
3127 let
3128 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3129 region = toRegion row col
3130 in
3131 Report.Report "UNFINISHED IF" region [] $
3132 Code.toSnippet source surroundings (Just region)
3134 D.reflow $
3135 "I was expecting to see more of this `if` expression, but I got stuck here:"
3137 D.stack
3138 [ D.fillSep $
3139 ["I","was","expecting","to","see","an","expression","like",D.dullyellow "x < 0"
3140 ,"that","evaluates","to","True","or","False."
3142 , D.toSimpleNote $
3143 "I can be confused by indentation. Maybe something is not indented enough?"
3147 IfIndentThen row col ->
3148 let
3149 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3150 region = toRegion row col
3151 in
3152 Report.Report "UNFINISHED IF" region [] $
3153 Code.toSnippet source surroundings (Just region)
3155 D.reflow $
3156 "I was expecting to see more of this `if` expression, but I got stuck here:"
3158 D.stack
3159 [ D.fillSep $
3160 ["I","was","expecting","to","see","the",D.cyan "then","keyword","next."
3162 , D.toSimpleNote $
3163 "I can be confused by indentation. Maybe something is not indented enough?"
3167 IfIndentThenBranch row col ->
3168 let
3169 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3170 region = toRegion row col
3171 in
3172 Report.Report "UNFINISHED IF" region [] $
3173 Code.toSnippet source surroundings (Just region)
3175 D.reflow $
3176 "I got stuck after the start of this `then` branch:"
3178 D.stack
3179 [ D.reflow $
3180 "I was expecting to see an expression next. Maybe it is not filled in yet?"
3181 , D.toSimpleNote $
3182 "I can be confused by indentation, so if the `then` branch is already\
3183 \ present, it may not be indented enough for me to recognize it."
3187 IfIndentElseBranch row col ->
3188 let
3189 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3190 region = toRegion row col
3191 in
3192 Report.Report "UNFINISHED IF" region [] $
3193 Code.toSnippet source surroundings (Just region)
3195 D.reflow $
3196 "I got stuck after the start of this `else` branch:"
3198 D.stack
3199 [ D.reflow $
3200 "I was expecting to see an expression next. Maybe it is not filled in yet?"
3201 , D.toSimpleNote $
3202 "I can be confused by indentation, so if the `else` branch is already\
3203 \ present, it may not be indented enough for me to recognize it."
3207 IfIndentElse row col ->
3208 let
3209 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3210 region = toRegion row col
3211 in
3212 Report.Report "UNFINISHED IF" region [] $
3213 Code.toSnippet source surroundings (Just region)
3215 D.reflow $
3216 "I was expecting to see an `else` branch after this:"
3218 D.stack
3219 [ D.reflow $
3220 "I know what to do when the condition is `True`, but not when it is `False`."
3221 , D.fillSep
3222 ["Add","an",D.cyan "else","branch","to","handle","that","scenario!"]
3228-- RECORD
3231toRecordReport :: Code.Source -> Context -> Record -> Row -> Col -> Report.Report
3232toRecordReport source context record startRow startCol =
3233 case record of
3234 RecordOpen row col ->
3235 case Code.whatIsNext source row col of
3236 Code.Keyword keyword ->
3237 let
3238 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3239 region = toKeywordRegion row col keyword
3240 in
3241 Report.Report "RESERVED WORD" region [] $
3242 Code.toSnippet source surroundings (Just region)
3244 D.reflow $
3245 "I just started parsing a record, but I got stuck on this field name:"
3247 D.reflow $
3248 "It looks like you are trying to use `" ++ keyword ++ "` as a field name, but \
3249 \ that is a reserved word. Try using a different name!"
3252 _ ->
3253 let
3254 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3255 region = toRegion row col
3256 in
3257 Report.Report "UNFINISHED RECORD" region [] $
3258 Code.toSnippet source surroundings (Just region)
3260 D.reflow $
3261 "I just started parsing a record, but I got stuck here:"
3263 D.fillSep
3264 ["Records","look","like",D.dullyellow "{ x = 3, y = 4 },"
3265 ,"so","I","was","expecting","to","see","a","field","name","next."
3269 RecordEnd row col ->
3270 let
3271 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3272 region = toRegion row col
3273 in
3274 Report.Report "UNFINISHED RECORD" region [] $
3275 Code.toSnippet source surroundings (Just region)
3277 D.reflow $
3278 "I am partway through parsing a record, but I got stuck here:"
3280 D.stack
3281 [ D.fillSep
3282 ["I","was","expecting","to","see","a","closing","curly","brace","before","this,"
3283 ,"so","try","adding","a",D.dullyellow "}","and","see","if","that","helps?"
3285 , D.toSimpleNote $
3286 "When I get stuck like this, it usually means that there is a missing parenthesis\
3287 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
3291 RecordField row col ->
3292 case Code.whatIsNext source row col of
3293 Code.Keyword keyword ->
3294 let
3295 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3296 region = toKeywordRegion row col keyword
3297 in
3298 Report.Report "RESERVED WORD" region [] $
3299 Code.toSnippet source surroundings (Just region)
3301 D.reflow $
3302 "I am partway through parsing a record, but I got stuck on this field name:"
3304 D.reflow $
3305 "It looks like you are trying to use `" ++ keyword ++ "` as a field name, but \
3306 \ that is a reserved word. Try using a different name!"
3309 _ ->
3310 let
3311 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3312 region = toRegion row col
3313 in
3314 Report.Report "UNFINISHED RECORD" region [] $
3315 Code.toSnippet source surroundings (Just region)
3317 D.reflow $
3318 "I am partway through parsing a record, but I got stuck after that last comma:"
3320 addNoteForRecordError $
3321 D.reflow $
3322 "Trailing commas are not allowed in records, so I was expecting to see another\
3323 \ record field defined next. If you are done defining the record, the fix may\
3324 \ be to delete that last comma?"
3327 RecordEquals row col ->
3328 let
3329 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3330 region = toRegion row col
3331 in
3332 Report.Report "UNFINISHED RECORD" region [] $
3333 Code.toSnippet source surroundings (Just region)
3335 D.reflow $
3336 "I am partway through parsing a record, but I got stuck here:"
3338 addNoteForRecordError $
3339 D.fillSep $
3340 ["I","just","saw","a","field","name,","so","I","was","expecting","to","see"
3341 ,"an","equals","sign","next.","So","try","putting","an",D.green "=","sign","here?"
3345 RecordExpr expr row col ->
3346 toExprReport source (InNode NRecord startRow startCol context) expr row col
3348 RecordSpace space row col ->
3349 toSpaceReport source space row col
3351 RecordIndentOpen row col ->
3352 let
3353 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3354 region = toRegion row col
3355 in
3356 Report.Report "UNFINISHED RECORD" region [] $
3357 Code.toSnippet source surroundings (Just region)
3359 D.reflow $
3360 "I just saw the opening curly brace of a record, but then I got stuck here:"
3362 addNoteForRecordIndentError $
3363 D.fillSep $
3364 ["I","am","expecting","a","record","like",D.dullyellow "{ x = 3, y = 4 }","here."
3365 ,"Try","defining","some","fields","of","your","own?"
3369 RecordIndentEnd row col ->
3370 let
3371 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3372 region = toRegion row col
3373 in
3374 Report.Report "UNFINISHED RECORD" region [] $
3375 Code.toSnippet source surroundings (Just region)
3377 D.reflow $
3378 "I was expecting to see a closing curly brace next:"
3380 addNoteForRecordIndentError $
3381 D.fillSep $
3382 ["Try","putting","an",D.green "}","and","see","if","that","helps?"
3386 RecordIndentField row col ->
3387 let
3388 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3389 region = toRegion row col
3390 in
3391 Report.Report "UNFINISHED RECORD" region [] $
3392 Code.toSnippet source surroundings (Just region)
3394 D.reflow $
3395 "I am partway through parsing a record, but I got stuck after that last comma:"
3397 addNoteForRecordError $
3398 D.reflow $
3399 "Trailing commas are not allowed in records, so the fix may be to\
3400 \ delete that last comma? Or maybe you were in the middle of defining\
3401 \ an additional field?"
3404 RecordIndentEquals row col ->
3405 let
3406 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3407 region = toRegion row col
3408 in
3409 Report.Report "UNFINISHED RECORD" region [] $
3410 Code.toSnippet source surroundings (Just region)
3412 D.reflow $
3413 "I am partway through parsing a record. I just saw a record\
3414 \ field, so I was expecting to see an equals sign next:"
3416 addNoteForRecordIndentError $
3417 D.fillSep $
3418 ["Try","putting","an",D.green "=","followed","by","an","expression?"
3422 RecordIndentExpr row col ->
3423 let
3424 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3425 region = toRegion row col
3426 in
3427 Report.Report "UNFINISHED RECORD" region [] $
3428 Code.toSnippet source surroundings (Just region)
3430 D.reflow $
3431 "I am partway through parsing a record, and I was expecting to run into an expression next:"
3433 addNoteForRecordIndentError $
3434 D.fillSep $
3435 ["Try","putting","something","like"
3436 ,D.dullyellow "42","or",D.dullyellow"\"hello\"","for","now?"
3441addNoteForRecordError :: D.Doc -> D.Doc
3442addNoteForRecordError normalRecommendation =
3443 D.stack $
3444 normalRecommendation
3446 [ D.toSimpleNote
3447 "If you are trying to define a record across multiple lines, I recommend using this format:"
3448 , D.indent 4 $ D.vcat $
3449 [ "{ name = \"Alice\""
3450 , ", age = 42"
3451 , ", height = 1.75"
3452 , "}"
3454 , D.reflow $
3455 "Notice that each line starts with some indentation. Usually two or four spaces. I\
3456 \ know this style can be jarring for people coming from C-like syntax, but folks generally\
3457 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
3461addNoteForRecordIndentError :: D.Doc -> D.Doc
3462addNoteForRecordIndentError normalRecommendation =
3463 D.stack $
3464 normalRecommendation
3466 [ D.toSimpleNote
3467 "I may be confused by indentation. For example, if you are trying to define\
3468 \ a record across multiple lines, I recommend using this format:"
3469 , D.indent 4 $ D.vcat $
3470 [ "{ name = \"Alice\""
3471 , ", age = 42"
3472 , ", height = 1.75"
3473 , "}"
3475 , D.reflow $
3476 "Notice that each line starts with some indentation. Usually two or four spaces. I\
3477 \ know this style can be jarring for people coming from C-like syntax, but folks generally\
3478 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
3483-- TUPLE
3486toTupleReport :: Code.Source -> Context -> Tuple -> Row -> Col -> Report.Report
3487toTupleReport source context tuple startRow startCol =
3488 case tuple of
3489 TupleExpr expr row col ->
3490 toExprReport source (InNode NParens startRow startCol context) expr row col
3492 TupleSpace space row col ->
3493 toSpaceReport source space row col
3495 TupleEnd row col ->
3496 let
3497 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3498 region = toRegion row col
3499 in
3500 Report.Report "UNFINISHED PARENTHESES" region [] $
3501 Code.toSnippet source surroundings (Just region)
3503 D.reflow $
3504 "I was expecting to see a closing parentheses next, but I got stuck here:"
3506 D.stack
3507 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps?"]
3508 , D.toSimpleNote $
3509 "I can get stuck when I run into keywords, operators, parentheses, or brackets\
3510 \ unexpectedly. So there may be some earlier syntax trouble (like extra parenthesis\
3511 \ or missing brackets) that is confusing me."
3515 TupleOperatorClose row col ->
3516 let
3517 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3518 region = toRegion row col
3519 in
3520 Report.Report "UNFINISHED OPERATOR FUNCTION" region [] $
3521 Code.toSnippet source surroundings (Just region)
3523 D.reflow "I was expecting a closing parenthesis here:"
3525 D.stack
3526 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps!"]
3527 , D.toSimpleNote $
3528 "I think I am parsing an operator function right now, so I am expecting to see\
3529 \ something like (+) or (&&) where an operator is surrounded by parentheses with\
3530 \ no extra spaces."
3534 TupleOperatorReserved operator row col ->
3535 let
3536 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3537 region = toRegion row col
3538 in
3539 Report.Report "UNEXPECTED SYMBOL" region [] $
3540 Code.toSnippet source surroundings (Just region)
3542 D.reflow $
3543 "I ran into an unexpected symbol here:"
3545 D.fillSep $
3546 case operator of
3547 BadDot -> ["Maybe","you","wanted","a","record","accessor","like",D.dullyellow ".x","or",D.dullyellow ".name","instead?"]
3548 BadPipe -> ["Try",D.dullyellow "(||)","instead?","To","turn","boolean","OR","into","a","function?"]
3549 BadArrow -> ["Maybe","you","wanted",D.dullyellow "(>)","or",D.dullyellow "(>=)","instead?"]
3550 BadEquals -> ["Try",D.dullyellow "(==)","instead?","To","make","a","function","that","checks","equality?"]
3551 BadHasType -> ["Try",D.dullyellow "(::)","instead?","To","add","values","to","the","front","of","lists?"]
3554 TupleIndentExpr1 row col ->
3555 let
3556 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3557 region = toRegion row col
3558 in
3559 Report.Report "UNFINISHED PARENTHESES" region [] $
3560 Code.toSnippet source surroundings (Just region)
3562 D.reflow $
3563 "I just saw an open parenthesis, so I was expecting to see an expression next."
3565 D.stack
3566 [ D.fillSep $
3567 ["Something","like",D.dullyellow "(4 + 5)","or"
3568 ,D.dullyellow "(String.reverse \"desserts\")" <> "."
3569 ,"Anything","where","you","are","putting","parentheses","around","normal","expressions."
3571 , D.toSimpleNote $
3572 "I can get confused by indentation in cases like this, so\
3573 \ maybe you have an expression but it is not indented enough?"
3577 TupleIndentExprN row col ->
3578 let
3579 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3580 region = toRegion row col
3581 in
3582 Report.Report "UNFINISHED TUPLE" region [] $
3583 Code.toSnippet source surroundings (Just region)
3585 D.reflow $
3586 "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."
3588 D.stack
3589 [ D.fillSep $
3590 ["A","tuple","looks","like",D.dullyellow "(3,4)","or"
3591 ,D.dullyellow "(\"Tom\",42)" <> ","
3592 ,"so","I","think","there","is","an","expression","missing","here?"
3594 , D.toSimpleNote $
3595 "I can get confused by indentation in cases like this, so\
3596 \ maybe you have an expression but it is not indented enough?"
3600 TupleIndentEnd row col ->
3601 let
3602 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3603 region = toRegion row col
3604 in
3605 Report.Report "UNFINISHED PARENTHESES" region [] $
3606 Code.toSnippet source surroundings (Just region)
3608 D.reflow $
3609 "I was expecting to see a closing parenthesis next:"
3611 D.stack
3612 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps!"]
3613 , D.toSimpleNote $
3614 "I can get confused by indentation in cases like this, so\
3615 \ maybe you have a closing parenthesis but it is not indented enough?"
3620toListReport :: Code.Source -> Context -> List -> Row -> Col -> Report.Report
3621toListReport source context list startRow startCol =
3622 case list of
3623 ListSpace space row col ->
3624 toSpaceReport source space row col
3626 ListOpen row col ->
3627 let
3628 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3629 region = toRegion row col
3630 in
3631 Report.Report "UNFINISHED LIST" region [] $
3632 Code.toSnippet source surroundings (Just region)
3634 D.reflow $
3635 "I am partway through parsing a list, but I got stuck here:"
3637 D.stack
3638 [ D.fillSep
3639 ["I","was","expecting","to","see","a","closing","square","bracket","before","this,"
3640 ,"so","try","adding","a",D.dullyellow "]","and","see","if","that","helps?"
3642 , D.toSimpleNote $
3643 "When I get stuck like this, it usually means that there is a missing parenthesis\
3644 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
3648 ListExpr expr row col ->
3649 case expr of
3650 Start r c ->
3651 let
3652 surroundings = A.Region (A.Position startRow startCol) (A.Position r c)
3653 region = toRegion r c
3654 in
3655 Report.Report "UNFINISHED LIST" region [] $
3656 Code.toSnippet source surroundings (Just region)
3658 D.reflow $
3659 "I was expecting to see another list entry after that last comma:"
3661 D.stack
3662 [ D.reflow $
3663 "Trailing commas are not allowed in lists, so the fix may be to delete the comma?"
3664 , D.toSimpleNote
3665 "I recommend using the following format for lists that span multiple lines:"
3666 , D.indent 4 $ D.vcat $
3667 [ "[ \"Alice\""
3668 , ", \"Bob\""
3669 , ", \"Chuck\""
3670 , "]"
3672 , D.reflow $
3673 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
3674 \ This style can be jarring for people coming from C-like syntax, but folks generally\
3675 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
3679 _ ->
3680 toExprReport source (InNode NList startRow startCol context) expr row col
3682 ListEnd row col ->
3683 let
3684 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3685 region = toRegion row col
3686 in
3687 Report.Report "UNFINISHED LIST" region [] $
3688 Code.toSnippet source surroundings (Just region)
3690 D.reflow $
3691 "I am partway through parsing a list, but I got stuck here:"
3693 D.stack
3694 [ D.fillSep
3695 ["I","was","expecting","to","see","a","closing","square","bracket","before","this,"
3696 ,"so","try","adding","a",D.dullyellow "]","and","see","if","that","helps?"
3698 , D.toSimpleNote $
3699 "When I get stuck like this, it usually means that there is a missing parenthesis\
3700 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
3704 ListIndentOpen row col ->
3705 let
3706 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3707 region = toRegion row col
3708 in
3709 Report.Report "UNFINISHED LIST" region [] $
3710 Code.toSnippet source surroundings (Just region)
3712 D.reflow $
3713 "I cannot find the end of this list:"
3715 D.stack
3716 [ D.fillSep $
3717 ["You","could","change","it","to","something","like"
3718 ,D.dullyellow "[3,4,5]"
3719 ,"or","even","just"
3720 ,D.dullyellow "[]" <> "."
3721 ,"Anything","where","there","is","an","open","and","close","square","brace,"
3722 ,"and","where","the","elements","of","the","list","are","separated","by","commas."
3724 , D.toSimpleNote
3725 "I may be confused by indentation. For example, if you are trying to define\
3726 \ a list across multiple lines, I recommend using this format:"
3727 , D.indent 4 $ D.vcat $
3728 [ "[ \"Alice\""
3729 , ", \"Bob\""
3730 , ", \"Chuck\""
3731 , "]"
3733 , D.reflow $
3734 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
3735 \ This style can be jarring for people coming from C-like syntax, but folks generally\
3736 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
3740 ListIndentEnd row col ->
3741 let
3742 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3743 region = toRegion row col
3744 in
3745 Report.Report "UNFINISHED LIST" region [] $
3746 Code.toSnippet source surroundings (Just region)
3748 D.reflow $
3749 "I cannot find the end of this list:"
3751 D.stack
3752 [ D.fillSep $
3753 ["You","can","just","add","a","closing",D.dullyellow "]"
3754 ,"right","here,","and","I","will","be","all","set!"
3756 , D.toSimpleNote
3757 "I may be confused by indentation. For example, if you are trying to define\
3758 \ a list across multiple lines, I recommend using this format:"
3759 , D.indent 4 $ D.vcat $
3760 [ "[ \"Alice\""
3761 , ", \"Bob\""
3762 , ", \"Chuck\""
3763 , "]"
3765 , D.reflow $
3766 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
3767 \ This style can be jarring for people coming from C-like syntax, but folks generally\
3768 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
3772 ListIndentExpr row col ->
3773 let
3774 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3775 region = toRegion row col
3776 in
3777 Report.Report "UNFINISHED LIST" region [] $
3778 Code.toSnippet source surroundings (Just region)
3780 D.reflow $
3781 "I was expecting to see another list entry after this comma:"
3783 D.stack
3784 [ D.reflow $
3785 "Trailing commas are not allowed in lists, so the fix may be to delete the comma?"
3786 , D.toSimpleNote
3787 "I recommend using the following format for lists that span multiple lines:"
3788 , D.indent 4 $ D.vcat $
3789 [ "[ \"Alice\""
3790 , ", \"Bob\""
3791 , ", \"Chuck\""
3792 , "]"
3794 , D.reflow $
3795 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
3796 \ This style can be jarring for people coming from C-like syntax, but folks generally\
3797 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
3802toFuncReport :: Code.Source -> Context -> Func -> Row -> Col -> Report.Report
3803toFuncReport source context func startRow startCol =
3804 case func of
3805 FuncSpace space row col ->
3806 toSpaceReport source space row col
3808 FuncArg pattern row col ->
3809 toPatternReport source PArg pattern row col
3811 FuncBody expr row col ->
3812 toExprReport source (InNode NFunc startRow startCol context) expr row col
3814 FuncArrow row col ->
3815 case Code.whatIsNext source row col of
3816 Code.Keyword keyword ->
3817 let
3818 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3819 region = toKeywordRegion row col keyword
3820 in
3821 Report.Report "RESERVED WORD" region [] $
3822 Code.toSnippet source surroundings (Just region)
3824 D.reflow $
3825 "I was parsing an anonymous function, but I got stuck here:"
3827 D.reflow $
3828 "It looks like you are trying to use `" ++ keyword ++ "` as an argument, but\
3829 \ it is a reserved word in this language. Try using a different argument name!"
3832 _ ->
3833 let
3834 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3835 region = toRegion row col
3836 in
3837 Report.Report "UNFINISHED ANONYMOUS FUNCTION" region [] $
3838 Code.toSnippet source surroundings (Just region)
3840 D.reflow $
3841 "I just saw the beginning of an anonymous function, so I was expecting to see an arrow next:"
3843 D.fillSep $
3844 ["The","syntax","for","anonymous","functions","is"
3845 ,D.dullyellow "(\\x -> x + 1)"
3846 ,"so","I","am","missing","the","arrow","and","the","body","of","the","function."
3850 FuncIndentArg row col ->
3851 let
3852 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3853 region = toRegion row col
3854 in
3855 Report.Report "MISSING ARGUMENT" region [] $
3856 Code.toSnippet source surroundings (Just region)
3858 D.reflow $
3859 "I just saw the beginning of an anonymous function, so I was expecting to see an argument next:"
3861 D.stack
3862 [ D.fillSep
3863 ["Something","like",D.dullyellow"x","or",D.dullyellow "name" <> "."
3864 ,"Anything","that","starts","with","a","lower","case","letter!"
3866 , D.toSimpleNote $
3867 "The syntax for anonymous functions is (\\x -> x + 1) where the backslash\
3868 \ is meant to look a bit like a lambda if you squint. This visual pun seemed\
3869 \ like a better idea at the time!"
3873 FuncIndentArrow row col ->
3874 let
3875 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3876 region = toRegion row col
3877 in
3878 Report.Report "UNFINISHED ANONYMOUS FUNCTION" region [] $
3879 Code.toSnippet source surroundings (Just region)
3881 D.reflow $
3882 "I just saw the beginning of an anonymous function, so I was expecting to see an arrow next:"
3884 D.stack
3885 [ D.fillSep $
3886 ["The","syntax","for","anonymous","functions","is"
3887 ,D.dullyellow "(\\x -> x + 1)"
3888 ,"so","I","am","missing","the","arrow","and","the","body","of","the","function."
3890 , D.toSimpleNote $
3891 "It is possible that I am confused about indetation! I generally recommend\
3892 \ switching to named functions if the definition cannot fit inline nicely, so\
3893 \ either (1) try to fit the whole anonymous function on one line or (2) break\
3894 \ the whole thing out into a named function. Things tend to be clearer that way!"
3898 FuncIndentBody row col ->
3899 let
3900 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3901 region = toRegion row col
3902 in
3903 Report.Report "UNFINISHED ANONYMOUS FUNCTION" region [] $
3904 Code.toSnippet source surroundings (Just region)
3906 D.reflow $
3907 "I was expecting to see the body of your anonymous function next:"
3909 D.stack
3910 [ D.fillSep $
3911 ["The","syntax","for","anonymous","functions","is"
3912 ,D.dullyellow "(\\x -> x + 1)"
3913 ,"so","I","am","missing","all","the","stuff","after","the","arrow!"
3915 , D.toSimpleNote $
3916 "It is possible that I am confused about indetation! I generally recommend\
3917 \ switching to named functions if the definition cannot fit inline nicely, so\
3918 \ either (1) try to fit the whole anonymous function on one line or (2) break\
3919 \ the whole thing out into a named function. Things tend to be clearer that way!"
3925-- PATTERN
3928data PContext
3929 = PCase
3930 | PArg
3933toPatternReport :: Code.Source -> PContext -> Pattern -> Row -> Col -> Report.Report
3934toPatternReport source context pattern startRow startCol =
3935 case pattern of
3936 PRecord record row col ->
3937 toPRecordReport source record row col
3939 PTuple tuple row col ->
3940 toPTupleReport source context tuple row col
3942 PList list row col ->
3943 toPListReport source context list row col
3945 PStart row col ->
3946 case Code.whatIsNext source row col of
3947 Code.Keyword keyword ->
3948 let
3949 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3950 region = toKeywordRegion row col keyword
3951 aThing =
3952 case context of
3953 PArg -> "an argument"
3954 PCase -> "a pattern"
3955 in
3956 Report.Report "RESERVED WORD" region [] $
3957 Code.toSnippet source surroundings (Just region)
3959 D.reflow $
3960 "It looks like you are trying to use `" ++ keyword ++ "` as " ++ aThing ++ ":"
3962 D.reflow $
3963 "This is a reserved word! Try using some other name?"
3966 _ ->
3967 error "TODO PStart"
3969 PChar char row col ->
3970 toCharReport source char row col
3972 PString string row col ->
3973 toStringReport source string row col
3975 PNumber number row col ->
3976 toNumberReport source number row col
3978 PFloat width row col ->
3979 let
3980 region = toWiderRegion row col width
3981 in
3982 Report.Report "UNEXPECTED PATTERN" region [] $
3983 Code.toSnippet source region Nothing
3985 D.reflow $
3986 "I cannot pattern match with floating point numbers:"
3988 D.fillSep $
3989 ["Equality","on","floats","can","be","unreliable,","so","you","usually","want"
3990 ,"to","check","that","they","are","nearby","with","some","sort","of"
3991 ,D.dullyellow "(abs (actual - expected) < 0.001)","check."
3995 PAlias row col ->
3996 let
3997 region = toRegion row col
3998 in
3999 Report.Report "UNFINISHED PATTERN" region [] $
4000 Code.toSnippet source region Nothing $
4002 D.reflow $
4003 "I was expecting to see a variable name after the `as` keyword:"
4005 D.stack
4006 [ D.fillSep $
4007 ["The","`as`","keyword","lets","you","write","patterns","like"
4008 ,"((" <> D.dullyellow "x" <> "," <> D.dullyellow "y" <> ") " <> D.cyan "as" <> D.dullyellow " point" <> ")"
4009 ,"so","you","can","refer","to","individual","parts","of","the","tuple","with"
4010 ,D.dullyellow "x","and",D.dullyellow "y","or","you","refer","to","the","whole"
4011 ,"thing","with",D.dullyellow "point."
4013 , D.reflow $
4014 "So I was expecting to see a variable name after the `as` keyword here. Sometimes\
4015 \ people just want to use `as` as a variable name though. Try using a different name\
4016 \ in that case!"
4020 PWildcardNotVar name width row col ->
4021 let
4022 region = toWiderRegion row col (fromIntegral width)
4023 examples =
4024 case dropWhile (=='_') (Name.toChars name) of
4025 [] -> [D.dullyellow "x","or",D.dullyellow "age"]
4026 c:cs -> [D.dullyellow (D.fromChars (Char.toLower c : cs))]
4027 in
4028 Report.Report "UNEXPECTED NAME" region [] $
4029 Code.toSnippet source region Nothing $
4031 D.reflow $
4032 "Variable names cannot start with underscores like this:"
4034 D.fillSep $
4035 ["You","can","either","have","an","underscore","like",D.dullyellow "_","to"
4036 ,"ignore","the","value,","or","you","can","have","a","name","like"
4037 ] ++ examples ++ ["to","use","the","matched","value." ]
4040 PSpace space row col ->
4041 toSpaceReport source space row col
4043 PIndentStart row col ->
4044 error "TODO PIndentStart" row col
4046 PIndentAlias row col ->
4047 let
4048 region = toRegion row col
4049 in
4050 Report.Report "UNFINISHED PATTERN" region [] $
4051 Code.toSnippet source region Nothing $
4053 D.reflow $
4054 "I was expecting to see a variable name after the `as` keyword:"
4056 D.stack
4057 [ D.fillSep $
4058 ["The","`as`","keyword","lets","you","write","patterns","like"
4059 ,"((" <> D.dullyellow "x" <> "," <> D.dullyellow "y" <> ") " <> D.cyan "as" <> D.dullyellow " point" <> ")"
4060 ,"so","you","can","refer","to","individual","parts","of","the","tuple","with"
4061 ,D.dullyellow "x","and",D.dullyellow "y","or","you","refer","to","the","whole"
4062 ,"thing","with",D.dullyellow "point."
4064 , D.reflow $
4065 "So I was expecting to see a variable name after the `as` keyword here. Sometimes\
4066 \ people just want to use `as` as a variable name though. Try using a different name\
4067 \ in that case!"
4072toPRecordReport :: Code.Source -> PRecord -> Row -> Col -> Report.Report
4073toPRecordReport source record startRow startCol =
4074 case record of
4075 PRecordOpen row col ->
4076 toUnfinishRecordPatternReport source row col startRow startCol $
4077 D.reflow "I was expecting to see a field name next."
4079 PRecordEnd row col ->
4080 toUnfinishRecordPatternReport source row col startRow startCol $
4081 D.fillSep
4082 ["I","was","expecting","to","see","a","closing","curly","brace","next."
4083 ,"Try","adding","a",D.dullyellow "}","here?"
4086 PRecordField row col ->
4087 case Code.whatIsNext source row col of
4088 Code.Keyword keyword ->
4089 let
4090 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4091 region = toKeywordRegion row col keyword
4092 in
4093 Report.Report "RESERVED WORD" region [] $
4094 Code.toSnippet source surroundings (Just region)
4096 D.reflow $
4097 "I was not expecting to see `" ++ keyword ++ "` as a record field name:"
4099 D.reflow $
4100 "This is a reserved word, not available for variable names. Try another name!"
4103 _ ->
4104 toUnfinishRecordPatternReport source row col startRow startCol $
4105 D.reflow "I was expecting to see a field name next."
4107 PRecordSpace space row col ->
4108 toSpaceReport source space row col
4110 PRecordIndentOpen row col ->
4111 toUnfinishRecordPatternReport source row col startRow startCol $
4112 D.reflow "I was expecting to see a field name next."
4114 PRecordIndentEnd row col ->
4115 toUnfinishRecordPatternReport source row col startRow startCol $
4116 D.fillSep
4117 ["I","was","expecting","to","see","a","closing","curly","brace","next."
4118 ,"Try","adding","a",D.dullyellow "}","here?"
4121 PRecordIndentField row col ->
4122 toUnfinishRecordPatternReport source row col startRow startCol $
4123 D.reflow "I was expecting to see a field name next."
4126toUnfinishRecordPatternReport :: Code.Source -> Row -> Col -> Row -> Col -> D.Doc -> Report.Report
4127toUnfinishRecordPatternReport source row col startRow startCol message =
4128 let
4129 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4130 region = toRegion row col
4131 in
4132 Report.Report "UNFINISHED RECORD PATTERN" region [] $
4133 Code.toSnippet source surroundings (Just region)
4135 D.reflow $
4136 "I was partway through parsing a record pattern, but I got stuck here:"
4138 D.stack
4139 [ message
4140 , D.toFancyHint $
4141 ["A","record","pattern","looks","like",D.dullyellow "{x,y}","or",D.dullyellow "{name,age}"
4142 ,"where","you","list","the","field","names","you","want","to","access."
4149toPTupleReport :: Code.Source -> PContext -> PTuple -> Row -> Col -> Report.Report
4150toPTupleReport source context tuple startRow startCol =
4151 case tuple of
4152 PTupleOpen row col ->
4153 case Code.whatIsNext source row col of
4154 Code.Keyword keyword ->
4155 let
4156 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4157 region = toKeywordRegion row col keyword
4158 in
4159 Report.Report "RESERVED WORD" region [] $
4160 Code.toSnippet source surroundings (Just region)
4162 D.reflow $
4163 "It looks like you are trying to use `" ++ keyword ++ "` as a variable name:"
4165 D.reflow $
4166 "This is a reserved word! Try using some other name?"
4169 _ ->
4170 let
4171 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4172 region = toRegion row col
4173 in
4174 Report.Report "UNFINISHED PARENTHESES" region [] $
4175 Code.toSnippet source surroundings (Just region)
4177 D.reflow $
4178 "I just saw an open parenthesis, but I got stuck here:"
4180 D.fillSep
4181 ["I","was","expecting","so","see","a","pattern","next."
4182 ,"Maybe","it","will","end","up","being","something"
4183 ,"like",D.dullyellow "(x,y)","or",D.dullyellow "(name, _)" <> "?"
4187 PTupleEnd row col ->
4188 let
4189 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4190 region = toRegion row col
4191 in
4192 Report.Report "UNFINISHED PARENTHESES" region [] $
4193 Code.toSnippet source surroundings (Just region) $
4195 D.reflow $
4196 "I was expecting a closing parenthesis next:"
4198 D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps?"]
4201 PTupleExpr pattern row col ->
4202 toPatternReport source context pattern row col
4204 PTupleSpace space row col ->
4205 toSpaceReport source space row col
4207 PTupleIndentEnd row col ->
4208 let
4209 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4210 region = toRegion row col
4211 in
4212 Report.Report "UNFINISHED PARENTHESES" region [] $
4213 Code.toSnippet source surroundings (Just region) $
4215 D.reflow $
4216 "I was expecting a closing parenthesis next:"
4218 D.stack
4219 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps?"]
4220 , D.toSimpleNote $
4221 "I can get confused by indentation in cases like this, so\
4222 \ maybe you have a closing parenthesis but it is not indented enough?"
4226 PTupleIndentExpr1 row col ->
4227 let
4228 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4229 region = toRegion row col
4230 in
4231 Report.Report "UNFINISHED PARENTHESES" region [] $
4232 Code.toSnippet source surroundings (Just region) $
4234 D.reflow $
4235 "I just saw an open parenthesis, but then I got stuck here:"
4237 D.fillSep
4238 ["I","was","expecting","so","see","a","pattern","next."
4239 ,"Maybe","it","will","end","up","being","something"
4240 ,"like",D.dullyellow "(x,y)","or",D.dullyellow "(name, _)" <> "?"
4244 PTupleIndentExprN row col ->
4245 let
4246 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4247 region = toRegion row col
4248 in
4249 Report.Report "UNFINISHED TUPLE PATTERN" region [] $
4250 Code.toSnippet source surroundings (Just region) $
4252 D.reflow $
4253 "I am partway through parsing a tuple pattern, but I got stuck here:"
4255 D.stack
4256 [ D.fillSep
4257 ["I","was","expecting","so","see","a","pattern","next."
4258 ,"I","am","expecting","the","final","result","to","be","something"
4259 ,"like",D.dullyellow "(x,y)","or",D.dullyellow "(name, _)" <> "."
4261 , D.toSimpleNote $
4262 "I can get confused by indentation in cases like this, so the problem\
4263 \ may be that the next part is not indented enough?"
4268toPListReport :: Code.Source -> PContext -> PList -> Row -> Col -> Report.Report
4269toPListReport source context list startRow startCol =
4270 case list of
4271 PListOpen row col ->
4272 case Code.whatIsNext source row col of
4273 Code.Keyword keyword ->
4274 let
4275 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4276 region = toKeywordRegion row col keyword
4277 in
4278 Report.Report "RESERVED WORD" region [] $
4279 Code.toSnippet source surroundings (Just region)
4281 D.reflow $
4282 "It looks like you are trying to use `" ++ keyword ++ "` to name an element of a list:"
4284 D.reflow $
4285 "This is a reserved word though! Try using some other name?"
4288 _ ->
4289 let
4290 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4291 region = toRegion row col
4292 in
4293 Report.Report "UNFINISHED LIST PATTERN" region [] $
4294 Code.toSnippet source surroundings (Just region) $
4296 D.reflow $
4297 "I just saw an open square bracket, but then I got stuck here:"
4299 D.fillSep ["Try","adding","a",D.dullyellow "]","to","see","if","that","helps?"]
4302 PListEnd row col ->
4303 let
4304 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4305 region = toRegion row col
4306 in
4307 Report.Report "UNFINISHED LIST PATTERN" region [] $
4308 Code.toSnippet source surroundings (Just region) $
4310 D.reflow $
4311 "I was expecting a closing square bracket to end this list pattern:"
4313 D.fillSep ["Try","adding","a",D.dullyellow "]","to","see","if","that","helps?"]
4316 PListExpr pattern row col ->
4317 toPatternReport source context pattern row col
4319 PListSpace space row col ->
4320 toSpaceReport source space row col
4322 PListIndentOpen row col ->
4323 let
4324 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4325 region = toRegion row col
4326 in
4327 Report.Report "UNFINISHED LIST PATTERN" region [] $
4328 Code.toSnippet source surroundings (Just region) $
4330 D.reflow $
4331 "I just saw an open square bracket, but then I got stuck here:"
4333 D.stack
4334 [ D.fillSep ["Try","adding","a",D.dullyellow "]","to","see","if","that","helps?"]
4335 , D.toSimpleNote $
4336 "I can get confused by indentation in cases like this, so\
4337 \ maybe there is something next, but it is not indented enough?"
4341 PListIndentEnd row col ->
4342 let
4343 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4344 region = toRegion row col
4345 in
4346 Report.Report "UNFINISHED LIST PATTERN" region [] $
4347 Code.toSnippet source surroundings (Just region) $
4349 D.reflow $
4350 "I was expecting a closing square bracket to end this list pattern:"
4352 D.stack
4353 [ D.fillSep ["Try","adding","a",D.dullyellow "]","to","see","if","that","helps?"]
4354 , D.toSimpleNote $
4355 "I can get confused by indentation in cases like this, so\
4356 \ maybe you have a closing square bracket but it is not indented enough?"
4360 PListIndentExpr row col ->
4361 let
4362 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4363 region = toRegion row col
4364 in
4365 Report.Report "UNFINISHED LIST PATTERN" region [] $
4366 Code.toSnippet source surroundings (Just region) $
4368 D.reflow $
4369 "I am partway through parsing a list pattern, but I got stuck here:"
4371 D.stack
4372 [ D.reflow $
4373 "I was expecting to see another pattern next. Maybe a variable name."
4374 , D.toSimpleNote $
4375 "I can get confused by indentation in cases like this, so\
4376 \ maybe there is more to this pattern but it is not indented enough?"
4382-- TYPES
4385data TContext
4386 = TC_Annotation Name.Name
4387 | TC_CustomType
4388 | TC_TypeAlias
4389 | TC_Port
4392toTypeReport :: Code.Source -> TContext -> Type -> Row -> Col -> Report.Report
4393toTypeReport source context tipe startRow startCol =
4394 case tipe of
4395 TRecord record row col ->
4396 toTRecordReport source context record row col
4398 TTuple tuple row col ->
4399 toTTupleReport source context tuple row col
4401 TStart row col ->
4402 case Code.whatIsNext source row col of
4403 Code.Keyword keyword ->
4404 let
4405 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4406 region = toKeywordRegion row col keyword
4407 in
4408 Report.Report "RESERVED WORD" region [] $
4409 Code.toSnippet source surroundings (Just region)
4411 D.reflow $
4412 "I was expecting to see a type next, but I got stuck on this reserved word:"
4414 D.reflow $
4415 "It looks like you are trying to use `" ++ keyword ++ "` as a type variable, but \
4416 \ it is a reserved word. Try using a different name!"
4419 _ ->
4420 let
4421 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4422 region = toRegion row col
4424 thing =
4425 case context of
4426 TC_Annotation _ -> "type annotation"
4427 TC_CustomType -> "custom type"
4428 TC_TypeAlias -> "type alias"
4429 TC_Port -> "port"
4431 something =
4432 case context of
4433 TC_Annotation name -> "the `" ++ Name.toChars name ++ "` type annotation"
4434 TC_CustomType -> "a custom type"
4435 TC_TypeAlias -> "a type alias"
4436 TC_Port -> "a port"
4437 in
4438 Report.Report ("PROBLEM IN " ++ map Char.toUpper thing) region [] $
4439 Code.toSnippet source surroundings (Just region)
4441 D.reflow $
4442 "I was partway through parsing " ++ something ++ ", but I got stuck here:"
4444 D.fillSep $
4445 ["I","was","expecting","to","see","a","type","next."
4446 ,"Try","putting",D.dullyellow "Int","or",D.dullyellow "String","for","now?"
4450 TSpace space row col ->
4451 toSpaceReport source space row col
4453 TIndentStart row col ->
4454 let
4455 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4456 region = toRegion row col
4458 thing =
4459 case context of
4460 TC_Annotation _ -> "type annotation"
4461 TC_CustomType -> "custom type"
4462 TC_TypeAlias -> "type alias"
4463 TC_Port -> "port"
4464 in
4465 Report.Report ("UNFINISHED " ++ map Char.toUpper thing) region [] $
4466 Code.toSnippet source surroundings (Just region)
4468 D.reflow $
4469 "I was partway through parsing a " ++ thing ++ ", but I got stuck here:"
4471 D.stack
4472 [ D.fillSep $
4473 ["I","was","expecting","to","see","a","type","next."
4474 ,"Try","putting",D.dullyellow "Int","or",D.dullyellow "String","for","now?"
4476 , D.toSimpleNote $
4477 "I can get confused by indentation. If you think there is already a type\
4478 \ next, maybe it is not indented enough?"
4483toTRecordReport :: Code.Source -> TContext -> TRecord -> Row -> Col -> Report.Report
4484toTRecordReport source context record startRow startCol =
4485 case record of
4486 TRecordOpen row col ->
4487 case Code.whatIsNext source row col of
4488 Code.Keyword keyword ->
4489 let
4490 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4491 region = toKeywordRegion row col keyword
4492 in
4493 Report.Report "RESERVED WORD" region [] $
4494 Code.toSnippet source surroundings (Just region)
4496 D.reflow $
4497 "I just started parsing a record type, but I got stuck on this field name:"
4499 D.reflow $
4500 "It looks like you are trying to use `" ++ keyword ++ "` as a field name, but \
4501 \ that is a reserved word. Try using a different name!"
4504 _ ->
4505 let
4506 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4507 region = toRegion row col
4508 in
4509 Report.Report "UNFINISHED RECORD TYPE" region [] $
4510 Code.toSnippet source surroundings (Just region)
4512 D.reflow $
4513 "I just started parsing a record type, but I got stuck here:"
4515 D.fillSep
4516 ["Record","types","look","like",D.dullyellow "{ name : String, age : Int },"
4517 ,"so","I","was","expecting","to","see","a","field","name","next."
4521 TRecordEnd row col ->
4522 let
4523 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4524 region = toRegion row col
4525 in
4526 Report.Report "UNFINISHED RECORD TYPE" region [] $
4527 Code.toSnippet source surroundings (Just region)
4529 D.reflow $
4530 "I am partway through parsing a record type, but I got stuck here:"
4532 D.stack
4533 [ D.fillSep
4534 ["I","was","expecting","to","see","a","closing","curly","brace","before","this,"
4535 ,"so","try","adding","a",D.dullyellow "}","and","see","if","that","helps?"
4537 , D.toSimpleNote $
4538 "When I get stuck like this, it usually means that there is a missing parenthesis\
4539 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
4543 TRecordField row col ->
4544 case Code.whatIsNext source row col of
4545 Code.Keyword keyword ->
4546 let
4547 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4548 region = toKeywordRegion row col keyword
4549 in
4550 Report.Report "RESERVED WORD" region [] $
4551 Code.toSnippet source surroundings (Just region)
4553 D.reflow $
4554 "I am partway through parsing a record type, but I got stuck on this field name:"
4556 D.reflow $
4557 "It looks like you are trying to use `" ++ keyword ++ "` as a field name, but \
4558 \ that is a reserved word. Try using a different name!"
4561 _ ->
4562 let
4563 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4564 region = toRegion row col
4565 in
4566 Report.Report "UNFINISHED RECORD TYPE" region [] $
4567 Code.toSnippet source surroundings (Just region)
4569 D.reflow $
4570 "I am partway through parsing a record type, but I got stuck after that last comma:"
4572 addNoteForRecordTypeError $
4573 D.reflow $
4574 "Trailing commas are not allowed in records, so I was expecting to see another\
4575 \ record field defined next. If you are done defining the record, the fix may\
4576 \ be to delete that last comma?"
4579 TRecordColon row col ->
4580 let
4581 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4582 region = toRegion row col
4583 in
4584 Report.Report "UNFINISHED RECORD TYPE" region [] $
4585 Code.toSnippet source surroundings (Just region)
4587 D.reflow $
4588 "I am partway through parsing a record type, but I got stuck here:"
4590 addNoteForRecordTypeError $
4591 D.fillSep $
4592 ["I","just","saw","a","field","name,","so","I","was","expecting","to","see"
4593 ,"a","colon","next.","So","try","putting","an",D.green ":","sign","here?"
4597 TRecordType tipe row col ->
4598 toTypeReport source context tipe row col
4600 TRecordSpace space row col ->
4601 toSpaceReport source space row col
4603 TRecordIndentOpen row col ->
4604 let
4605 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4606 region = toRegion row col
4607 in
4608 Report.Report "UNFINISHED RECORD TYPE" region [] $
4609 Code.toSnippet source surroundings (Just region)
4611 D.reflow $
4612 "I just saw the opening curly brace of a record type, but then I got stuck here:"
4614 addNoteForRecordTypeIndentError $
4615 D.fillSep $
4616 ["I","am","expecting","a","record","like",D.dullyellow "{ name : String, age : Int }","here."
4617 ,"Try","defining","some","fields","of","your","own?"
4621 TRecordIndentEnd row col ->
4622 let
4623 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4624 region = toRegion row col
4625 in
4626 Report.Report "UNFINISHED RECORD TYPE" region [] $
4627 Code.toSnippet source surroundings (Just region)
4629 D.reflow $
4630 "I was expecting to see a closing curly brace next:"
4632 addNoteForRecordTypeIndentError $
4633 D.fillSep $
4634 ["Try","putting","an",D.green "}","and","see","if","that","helps?"
4638 TRecordIndentField row col ->
4639 let
4640 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4641 region = toRegion row col
4642 in
4643 Report.Report "UNFINISHED RECORD TYPE" region [] $
4644 Code.toSnippet source surroundings (Just region)
4646 D.reflow $
4647 "I am partway through parsing a record type, but I got stuck after that last comma:"
4649 addNoteForRecordTypeIndentError $
4650 D.reflow $
4651 "Trailing commas are not allowed in record types, so the fix may be to\
4652 \ delete that last comma? Or maybe you were in the middle of defining\
4653 \ an additional field?"
4656 TRecordIndentColon row col ->
4657 let
4658 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4659 region = toRegion row col
4660 in
4661 Report.Report "UNFINISHED RECORD TYPE" region [] $
4662 Code.toSnippet source surroundings (Just region)
4664 D.reflow $
4665 "I am partway through parsing a record type. I just saw a record\
4666 \ field, so I was expecting to see a colon next:"
4668 addNoteForRecordTypeIndentError $
4669 D.fillSep $
4670 ["Try","putting","an",D.green ":","followed","by","a","type?"
4674 TRecordIndentType row col ->
4675 let
4676 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4677 region = toRegion row col
4678 in
4679 Report.Report "UNFINISHED RECORD TYPE" region [] $
4680 Code.toSnippet source surroundings (Just region)
4682 D.reflow $
4683 "I am partway through parsing a record type, and I was expecting to run into a type next:"
4685 addNoteForRecordTypeIndentError $
4686 D.fillSep $
4687 ["Try","putting","something","like"
4688 ,D.dullyellow "Int","or",D.dullyellow "String","for","now?"
4693addNoteForRecordTypeError :: D.Doc -> D.Doc
4694addNoteForRecordTypeError normalRecommendation =
4695 D.stack $
4696 normalRecommendation
4698 [ D.toSimpleNote
4699 "If you are trying to define a record type across multiple lines, I recommend using this format:"
4700 , D.indent 4 $ D.vcat $
4701 [ "{ name : String"
4702 , ", age : Int"
4703 , ", height : Float"
4704 , "}"
4706 , D.reflow $
4707 "Notice that each line starts with some indentation. Usually two or four spaces. I\
4708 \ know this style can be jarring for people coming from C-like syntax, but folks generally\
4709 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
4713addNoteForRecordTypeIndentError :: D.Doc -> D.Doc
4714addNoteForRecordTypeIndentError normalRecommendation =
4715 D.stack $
4716 normalRecommendation
4718 [ D.toSimpleNote
4719 "I may be confused by indentation. For example, if you are trying to define\
4720 \ a record type across multiple lines, I recommend using this format:"
4721 , D.indent 4 $ D.vcat $
4722 [ "{ name : String"
4723 , ", age : Int"
4724 , ", height : Float"
4725 , "}"
4727 , D.reflow $
4728 "Notice that each line starts with some indentation. Usually two or four spaces. I\
4729 \ know this style can be jarring for people coming from C-like syntax, but folks generally\
4730 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
4734toTTupleReport :: Code.Source -> TContext -> TTuple -> Row -> Col -> Report.Report
4735toTTupleReport source context tuple startRow startCol =
4736 case tuple of
4737 TTupleOpen row col ->
4738 case Code.whatIsNext source row col of
4739 Code.Keyword keyword ->
4740 let
4741 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4742 region = toKeywordRegion row col keyword
4743 in
4744 Report.Report "RESERVED WORD" region [] $
4745 Code.toSnippet source surroundings (Just region)
4747 D.reflow $
4748 "I ran into a reserved word unexpectedly:"
4750 D.reflow $
4751 "It looks like you are trying to use `" ++ keyword ++ "` as a variable name, but \
4752 \ it is a reserved word. Try using a different name!"
4755 _ ->
4756 let
4757 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4758 region = toRegion row col
4759 in
4760 Report.Report "UNFINISHED PARENTHESES" region [] $
4761 Code.toSnippet source surroundings (Just region)
4763 D.reflow $
4764 "I just saw an open parenthesis, so I was expecting to see a type next."
4766 D.fillSep $
4767 ["Something","like",D.dullyellow "(Maybe Int)","or"
4768 ,D.dullyellow "(List Person)" <> "."
4769 ,"Anything","where","you","are","putting","parentheses","around","normal","types."
4773 TTupleEnd row col ->
4774 let
4775 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4776 region = toRegion row col
4777 in
4778 Report.Report "UNFINISHED PARENTHESES" region [] $
4779 Code.toSnippet source surroundings (Just region)
4781 D.reflow $
4782 "I was expecting to see a closing parentheses next, but I got stuck here:"
4784 D.stack
4785 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps?"]
4786 , D.toSimpleNote $
4787 "I can get stuck when I run into keywords, operators, parentheses, or brackets\
4788 \ unexpectedly. So there may be some earlier syntax trouble (like extra parenthesis\
4789 \ or missing brackets) that is confusing me."
4793 TTupleType tipe row col ->
4794 toTypeReport source context tipe row col
4796 TTupleSpace space row col ->
4797 toSpaceReport source space row col
4799 TTupleIndentType1 row col ->
4800 let
4801 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4802 region = toRegion row col
4803 in
4804 Report.Report "UNFINISHED PARENTHESES" region [] $
4805 Code.toSnippet source surroundings (Just region)
4807 D.reflow $
4808 "I just saw an open parenthesis, so I was expecting to see a type next."
4810 D.stack
4811 [ D.fillSep $
4812 ["Something","like",D.dullyellow "(Maybe Int)","or"
4813 ,D.dullyellow "(List Person)" <> "."
4814 ,"Anything","where","you","are","putting","parentheses","around","normal","types."
4816 , D.toSimpleNote $
4817 "I can get confused by indentation in cases like this, so\
4818 \ maybe you have a type but it is not indented enough?"
4822 TTupleIndentTypeN row col ->
4823 let
4824 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4825 region = toRegion row col
4826 in
4827 Report.Report "UNFINISHED TUPLE TYPE" region [] $
4828 Code.toSnippet source surroundings (Just region)
4830 D.reflow $
4831 "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."
4833 D.stack
4834 [ D.fillSep $
4835 ["A","tuple","type","looks","like",D.dullyellow "(Float,Float)","or"
4836 ,D.dullyellow "(String,Int)" <> ","
4837 ,"so","I","think","there","is","a","type","missing","here?"
4839 , D.toSimpleNote $
4840 "I can get confused by indentation in cases like this, so\
4841 \ maybe you have an expression but it is not indented enough?"
4845 TTupleIndentEnd row col ->
4846 let
4847 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4848 region = toRegion row col
4849 in
4850 Report.Report "UNFINISHED PARENTHESES" region [] $
4851 Code.toSnippet source surroundings (Just region)
4853 D.reflow $
4854 "I was expecting to see a closing parenthesis next:"
4856 D.stack
4857 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps!"]
4858 , D.toSimpleNote $
4859 "I can get confused by indentation in cases like this, so\
4860 \ maybe you have a closing parenthesis but it is not indented enough?"