on e5abcf4 help sign in
2532 lines 82 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 | Module Row Col
82 | ModuleName Row Col
83 | ModuleExposing Row Col
84 | ModuleExposingList Exposing Row Col
85 --
86 | ModulePortModule Row Col
87 | ModuleEffect Row Col
88 --
89 | ModuleIndentStart Row Col
90 | ModuleIndentName Row Col
91 | ModuleIndentExposing Row Col
92 | ModuleIndentExposingList Row Col
93 | ModuleIndentPortModule Row Col
94 --
95 | FreshLineModuleStart Row Col
96 | FreshLineAfterModuleLine Row Col
97 | FreshLineAfterDocComment Row Col
98 --
99 | ImportStart Row Col
100 | ImportName Row Col
101 | ImportAs Row Col
102 | ImportAlias Row Col
103 | ImportExposing Row Col
104 | ImportExposingList Exposing Row Col
105 | ImportEnd Row Col -- different based on col=1 or if greater
106 --
107 | ImportIndentName Row Col
108 | ImportIndentAlias Row Col
109 | ImportIndentExposingList Row Col
110 --
111 | Infix Row Col
112 --
113 | Declarations Decl Row Col
116data Exposing
117 = ExposingSpace Space Row Col
118 | ExposingStart Row Col
119 | ExposingValue Row Col
120 | ExposingOperator Row Col
121 | ExposingOperatorReserved BadOperator Row Col
122 | ExposingOperatorRightParen Row Col
123 | ExposingEnd Row Col
124 --
125 | ExposingTypePrivacy Row Col
126 | ExposingTypePrivacyDots Row Col
127 | ExposingTypePrivacyEnd Row Col
128 --
129 | ExposingIndentEnd Row Col
130 | ExposingIndentValue Row Col
131 | ExposingIndentValueEnd Row Col
132 | ExposingIndentTypePrivacy Row Col
133 | ExposingIndentTypePrivacyDots Row Col
134 | ExposingIndentTypePrivacyEnd Row Col
138-- DECLARATIONS
141data Decl
142 = DeclStart Row Col
143 | DeclSpace Space Row Col
144 --
145 | Port Port Row Col
146 | DeclType DeclType Row Col
147 | DeclDef Name.Name DeclDef Row Col
148 --
149 | DeclFreshLineStart Row Col
150 | DeclFreshLineAfterDocComment Row Col
153data DeclDef
154 = DeclDefSpace Space Row Col
155 | DeclDefEquals Row Col
156 | DeclDefType Type Row Col
157 | DeclDefArg Pattern Row Col
158 | DeclDefBody Expr Row Col
159 | DeclDefNameRepeat Row Col
160 | DeclDefNameMatch Name.Name Row Col
161 --
162 | DeclDefIndentType Row Col
163 | DeclDefIndentEquals Row Col
164 | DeclDefIndentBody Row Col
165 --
166 | DeclDefFreshLineAfterType Row Col
169data Port
170 = PortSpace Space Row Col
171 | PortName Row Col
172 | PortColon Row Col
173 | PortType Type Row Col
174 | PortIndentName Row Col
175 | PortIndentColon Row Col
176 | PortIndentType Row Col
180-- TYPE DECLARATIONS
183data DeclType
184 = DT_Space Space Row Col
185 | DT_Name Row Col
186 | DT_Alias TypeAlias Row Col
187 | DT_Union CustomType Row Col
188 --
189 | DT_IndentName Row Col
192data TypeAlias
193 = AliasSpace Space Row Col
194 | AliasName Row Col
195 | AliasEquals Row Col
196 | AliasBody Type Row Col
197 --
198 | AliasIndentEquals Row Col
199 | AliasIndentBody Row Col
202data CustomType
203 = CT_Space Space Row Col
204 | CT_Name Row Col
205 | CT_Equals Row Col
206 | CT_Bar Row Col
207 | CT_Variant Row Col
208 | CT_VariantArg Type Row Col
209 --
210 | CT_IndentEquals Row Col
211 | CT_IndentBar Row Col
212 | CT_IndentAfterBar Row Col
213 | CT_IndentAfterEquals Row Col
217-- EXPRESSIONS
220data Expr
221 = Let Let Row Col
222 | Case Case Row Col
223 | If If Row Col
224 | List List Row Col
225 | Record Record Row Col
226 | Tuple Tuple Row Col
227 | Func Func Row Col
228 --
229 | Dot Row Col
230 | Access Row Col
231 | OperatorRight Name.Name Row Col
232 | OperatorReserved BadOperator Row Col
233 --
234 | Start Row Col
235 | Char Char Row Col
236 | String String Row Col
237 | Number Number Row Col
238 | Space Space Row Col
239 | EndlessShader Row Col
240 | ShaderProblem [Char.Char] Row Col
241 | IndentOperatorRight Name.Name Row Col
242 | IndentMoreExpr Row Col
245data Record
246 = RecordOpen Row Col
247 | RecordEnd Row Col
248 | RecordField Row Col
249 | RecordEquals Row Col
250 | RecordExpr Expr Row Col
251 | RecordSpace Space Row Col
252 --
253 | RecordIndentOpen Row Col
254 | RecordIndentEnd Row Col
255 | RecordIndentField Row Col
256 | RecordIndentEquals Row Col
257 | RecordIndentExpr Row Col
260data Tuple
261 = TupleExpr Expr Row Col
262 | TupleSpace Space Row Col
263 | TupleEnd Row Col
264 | TupleOperatorClose Row Col
265 | TupleOperatorReserved BadOperator Row Col
266 --
267 | TupleIndentExpr1 Row Col
268 | TupleIndentExprN Row Col
269 | TupleIndentEnd Row Col
272data List
273 = ListSpace Space Row Col
274 | ListOpen Row Col
275 | ListExpr Expr Row Col
276 | ListEnd Row Col
277 --
278 | ListIndentOpen Row Col
279 | ListIndentEnd Row Col
280 | ListIndentExpr Row Col
283data Func
284 = FuncSpace Space Row Col
285 | FuncArg Pattern Row Col
286 | FuncBody Expr Row Col
287 | FuncArrow Row Col
288 --
289 | FuncIndentArg Row Col
290 | FuncIndentArrow Row Col
291 | FuncIndentBody Row Col
294data Case
295 = CaseSpace Space Row Col
296 | CaseOf Row Col
297 | CasePattern Pattern Row Col
298 | CaseArrow Row Col
299 | CaseExpr Expr Row Col
300 | CaseBranch Expr Row Col
301 --
302 | CaseIndentOf Row Col
303 | CaseIndentExpr Row Col
304 | CaseIndentPattern Row Col
305 | CaseIndentArrow Row Col
306 | CaseIndentBranch Row Col
307 | CasePatternAlignment Word16 Row Col
310data If
311 = IfSpace Space Row Col
312 | IfThen Row Col
313 | IfElse Row Col
314 | IfElseBranchStart Row Col
315 --
316 | IfCondition Expr Row Col
317 | IfThenBranch Expr Row Col
318 | IfElseBranch Expr Row Col
319 --
320 | IfIndentCondition Row Col
321 | IfIndentThen Row Col
322 | IfIndentThenBranch Row Col
323 | IfIndentElseBranch Row Col
324 | IfIndentElse Row Col
327data Let
328 = LetSpace Space Row Col
329 | LetIn Row Col
330 | LetDefAlignment Word16 Row Col
331 | LetDefName Row Col
332 | LetDef Name.Name Def Row Col
333 | LetDestruct Destruct Row Col
334 | LetBody Expr Row Col
335 | LetIndentDef Row Col
336 | LetIndentIn Row Col
337 | LetIndentBody Row Col
340data Def
341 = DefSpace Space Row Col
342 | DefType Type Row Col
343 | DefNameRepeat Name.Name Row Col
344 | DefNameMatch Name.Name Name.Name Row Col
345 | DefArg Pattern Row Col
346 | DefEquals Row Col
347 | DefBody Expr Row Col
348 | DefIndentEquals Row Col
349 | DefIndentType Row Col
350 | DefIndentBody Row Col
351 | DefAlignment Word16 Row Col
354data Destruct
355 = DestructSpace Space Row Col
356 | DestructPattern Pattern Row Col
357 | DestructEquals Row Col
358 | DestructBody Expr Row Col
359 | DestructIndentEquals Row Col
360 | DestructIndentBody Row Col
364-- PATTERNS
367data Pattern
368 = PRecord PRecord Row Col
369 | PTuple PTuple Row Col
370 | PList PList Row Col
371 --
372 | PStart Row Col
373 | PChar Char Row Col
374 | PString String Row Col
375 | PNumber Number Row Col
376 | PFloat Int Row Col
377 | PAlias Row Col
378 | PWildcardNotVar Int Row Col
379 | PSpace Space Row Col
380 --
381 | PIndentStart Row Col
382 | PIndentAlias Row Col
385data PRecord
386 = PRecordOpen Row Col
387 | PRecordEnd Row Col
388 | PRecordField Row Col
389 | PRecordSpace Space Row Col
390 --
391 | PRecordIndentOpen Row Col
392 | PRecordIndentEnd Row Col
393 | PRecordIndentField Row Col
396data PTuple
397 = PTupleOpen Row Col
398 | PTupleEnd Row Col
399 | PTupleExpr Pattern Row Col
400 | PTupleSpace Space Row Col
401 --
402 | PTupleIndentOpen Row Col
403 | PTupleIndentEnd Row Col
404 | PTupleIndentExpr Row Col
407data PList
408 = PListOpen Row Col
409 | PListEnd Row Col
410 | PListExpr Pattern Row Col
411 | PListSpace Space Row Col
412 --
413 | PListIndentOpen Row Col
414 | PListIndentEnd Row Col
415 | PListIndentExpr Row Col
419-- TYPES
422data Type
423 = TRecord TRecord Row Col
424 | TTuple TTuple Row Col
425 | TVariant Row Col
426 | TArrow Row Col
427 --
428 | TStart Row Col
429 | TSpace Space Row Col
430 --
431 | TIndentStart Row Col
434data TRecord
435 = TRecordOpen Row Col
436 | TRecordEnd Row Col
437 --
438 | TRecordField Row Col
439 | TRecordColon Row Col
440 | TRecordType Type Row Col
441 --
442 | TRecordSpace Space Row Col
443 --
444 | TRecordIndentOpen Row Col
445 | TRecordIndentField Row Col
446 | TRecordIndentColon Row Col
447 | TRecordIndentType Row Col
448 | TRecordIndentEnd Row Col
451data TTuple
452 = TTupleOpen Row Col
453 | TTupleEnd Row Col
454 | TTupleType Type Row Col
455 | TTupleSpace Space Row Col
456 --
457 | TTupleIndentOpen Row Col
458 | TTupleIndentType Row Col
459 | TTupleIndentEnd Row Col
463-- LITERALS
466data Char
467 = CharEndless
468 | CharEscape Escape
469 | CharNotString Word16
472data String
473 = StringEndless_Single
474 | StringEndless_Multi
475 | StringEscape Escape
478data Escape
479 = EscapeUnknown
480 | BadUnicodeFormat Word16
481 | BadUnicodeCode Word16
482 | BadUnicodeLength Word16 Int Int
485data Number
486 = NumberEnd
487 | NumberDot Int
488 | NumberHexDigit
489 | NumberNoLeadingZero
493-- MISC
496data Space
497 = HasTab
498 | EndlessMultiComment
502-- TO REPORT
505toReport :: Code.Source -> Error -> Report.Report
506toReport source err =
507 case err of
508 ModuleNameUnspecified name ->
509 let
510 region = toRegion 1 1
511 in
512 Report.Report "MODULE NAME MISSING" region [] $
513 D.stack
514 [ D.reflow $
515 "I need the module name to be declared at the top of this file, like this:"
516 , D.indent 4 $ D.green $ D.fromChars $
517 "module " ++ ModuleName.toChars name ++ " exposing (..)"
518 , D.reflow $
519 "Try adding that as the first line of your file!"
520 , D.toSimpleNote $
521 "It is best to replace (..) with an explicit list of types and\
522 \ functions you want to expose. When you know a value is only used\
523 \ within this module, you can refactor without worrying about uses\
524 \ elsewhere. Limiting exposed values can also speed up compilation\
525 \ because I can skip a bunch of work if I see that the exposed API\
526 \ has not changed."
527 ]
529 ModuleNameMismatch expectedName (A.At region actualName) ->
530 Report.Report "MODULE NAME MISMATCH" region [ModuleName.toChars expectedName] $
531 Code.toSnippet source region Nothing
532 (
533 "It looks like this module name is out of sync:"
534 ,
535 D.stack
536 [ D.reflow $
537 "I need it to match the file path, so I was expecting it to see `"
538 ++ ModuleName.toChars expectedName
539 ++ "` here. Make the following change, and you should be all set!"
540 , D.indent 4 $
541 D.dullyellow (D.fromName actualName) <> " -> " <> D.green (D.fromName expectedName)
542 , D.toSimpleNote $
543 "I require that module names correspond to file paths. This makes it much\
544 \ easier to explore unfamiliar codebases! So if you want to keep the current\
545 \ module name, try renaming the file instead."
546 ]
547 )
549 UnexpectedPort region ->
550 error "TODO UnexpectedPort" region
552 NoPorts region ->
553 error "TODO NoPorts" region
555 ParseError modul ->
556 toParseErrorReport source modul
559toParseErrorReport :: Code.Source -> Module -> Report.Report
560toParseErrorReport source modul =
561 case modul of
562 ModuleSpace space row col ->
563 toSpaceReport source space row col
565 ModuleEndOfFile row col ->
566 let
567 region = toRegion row col
568 in
569 Report.Report "EXPECTING END OF FILE" region [] $
570 Code.toSnippet source region Nothing
571 (
572 D.reflow $
573 "I was not expecting to see anything more here:"
574 ,
575 D.reflow $
576 "I think I have read all the declarations in the file and that there is nothing\
577 \ left to see, so whatever I am running into is confusing me a lot!"
578 )
580 Module row col ->
581 error "TODO Module" row col
583 ModuleName row col ->
584 error "TODO ModuleName" row col
586 ModuleExposing row col ->
587 error "TODO ModuleExposing" row col
589 ModuleExposingList exposing row col ->
590 error "TODO ModuleExposingList" exposing row col
592 ModulePortModule row col ->
593 error "TODO ModulePortModule" row col
595 ModuleEffect row col ->
596 error "TODO ModuleEffect" row col
598 ModuleIndentStart row col ->
599 error "TODO ModuleIndentStart" row col
601 ModuleIndentName row col ->
602 error "TODO ModuleIndentName" row col
604 ModuleIndentExposing row col ->
605 error "TODO ModuleIndentExposing" row col
607 ModuleIndentExposingList row col ->
608 error "TODO ModuleIndentExposingList" row col
610 ModuleIndentPortModule row col ->
611 error "TODO ModuleIndentPortModule" row col
613 FreshLineModuleStart row col ->
614 error "TODO FreshLineModuleStart" row col
616 FreshLineAfterModuleLine row col ->
617 error "TODO FreshLineAfterModuleLine" row col
619 FreshLineAfterDocComment row col ->
620 error "TODO FreshLineAfterDocComment" row col
622 ImportStart row col ->
623 toImportReport source row col
625 ImportName row col ->
626 let
627 region = toRegion row col
628 in
629 Report.Report "EXPECTING IMPORT NAME" region [] $
630 Code.toSnippet source region Nothing
631 (
632 D.reflow $
633 "I was parsing an `import` until I got stuck here:"
634 ,
635 D.stack
636 [ D.reflow $
637 "I was expecting to see a module name next, like in these examples:"
638 , D.indent 4 $ D.vcat $
639 [ D.fillSep [D.blue "import","Dict"]
640 , D.fillSep [D.blue "import","Maybe"]
641 , D.fillSep [D.blue "import","Html.Attributes"]
642 , D.fillSep [D.blue "import","Json.Decode"]
643 ]
644 , D.reflow $
645 "Notice that the module names all start with capital letters. That is required!"
646 ]
647 )
649 ImportAs row col ->
650 toImportReport source row col
652 ImportAlias row col ->
653 let
654 region = toRegion row col
655 in
656 Report.Report "EXECTING IMPORT ALIAS" region [] $
657 Code.toSnippet source region Nothing
658 (
659 D.reflow $
660 "I was parsing an `import` until I got stuck here:"
661 ,
662 D.stack
663 [ D.reflow $
664 "I was expecting to see an alias next, like in these examples:"
665 , D.indent 4 $ D.vcat $
666 [ D.fillSep [D.blue "import","Html.Attributes",D.blue "as","Attr"]
667 , D.fillSep [D.blue "import","WebGL.Texture",D.blue "as","Texture"]
668 , D.fillSep [D.blue "import","Json.Decode",D.blue "as","D"]
669 ]
670 , D.reflow $
671 "Notice that the alias always starts with a capital letter. That is required!"
672 ]
673 )
675 ImportExposing row col ->
676 toImportReport source row col
678 ImportExposingList exposing row col ->
679 error "TODO ImportExposingList" exposing row col
681 ImportEnd row col ->
682 toImportReport source row col
684 ImportIndentName row col ->
685 toImportReport source row col
687 ImportIndentAlias row col ->
688 toImportReport source row col
690 ImportIndentExposingList row col ->
691 let
692 region = toRegion row col
693 in
694 Report.Report "UNFINISHED IMPORT" region [] $
695 Code.toSnippet source region Nothing
696 (
697 D.reflow $
698 "I was parsing an `import` until I got stuck here:"
699 ,
700 D.stack
701 [ D.reflow $
702 "I was expecting to see the list of exposed values next. For example, here\
703 \ are two ways to expose values from the `Html` module:"
704 , D.indent 4 $ D.vcat $
705 [ D.fillSep [D.blue "import","Html",D.blue "exposing","(..)"]
706 , D.fillSep [D.blue "import","Html",D.blue "exposing","(Html, div, text)"]
707 ]
708 , D.reflow $
709 "I generally recommend the second style. It is more explicit, making it\
710 \ much easier to figure out where values are coming from in large projects!"
711 ]
712 )
714 Infix row col ->
715 let
716 region = toRegion row col
717 in
718 Report.Report "BAD INFIX" region [] $
719 Code.toSnippet source region Nothing
720 (
721 D.reflow $
722 "Something went wrong in this infix operator declaration:"
723 ,
724 D.reflow $
725 "This feature is used by the @elm organization to define the\
726 \ languages built-in operators."
727 )
729 Declarations decl _ _ ->
730 toDeclarationsReport source decl
734-- IMPORTS
737toImportReport :: Code.Source -> Row -> Col -> Report.Report
738toImportReport source row col =
739 let
740 region = toRegion row col
741 in
742 Report.Report "UNFINISHED IMPORT" region [] $
743 Code.toSnippet source region Nothing
744 (
745 D.reflow $
746 "I am partway through parsing an import, but I got stuck here:"
747 ,
748 D.stack
749 [ D.reflow $
750 "Here are some examples of valid `import` declarations:"
751 , D.indent 4 $ D.vcat $
752 [ D.fillSep [D.blue "import","Html"]
753 , D.fillSep [D.blue "import","Html",D.blue "as","H"]
754 , D.fillSep [D.blue "import","Html",D.blue "exposing","(Html, div, text)"]
755 , D.fillSep [D.blue "import","Html",D.blue "as","H",D.blue "exposing","(..)"]
756 ]
757 , D.reflow $
758 "You are probably trying to import a different module, but try to make it look like one of these examples!"
759 ]
760 )
764-- SPACES
767toSpaceReport :: Code.Source -> Space -> Row -> Col -> Report.Report
768toSpaceReport source space row col =
769 case space of
770 HasTab ->
771 let
772 region = toRegion row col
773 in
774 Report.Report "NO TABS" region [] $
775 Code.toSnippet source region Nothing
776 (
777 D.reflow $
778 "I ran into a tab, but tabs are not allowed in Elm files."
779 ,
780 D.reflow $
781 "Replace the tab with spaces."
782 )
784 EndlessMultiComment ->
785 let
786 region = toWiderRegion row col 2
787 in
788 Report.Report "ENDLESS COMMENT" region [] $
789 Code.toSnippet source region Nothing
790 (
791 D.reflow $
792 "I cannot find the end of this multi-line comment:"
793 ,
794 D.stack -- "{-"
795 [ D.reflow "Add a -} somewhere after this to end the comment."
796 , D.toSimpleHint
797 "Multi-line comments can be nested in Elm, so {- {- -} -} is a comment\
798 \ that happens to contain another comment. Like parentheses and curly braces,\
799 \ the start and end markers must always be balanced. Maybe that is the problem?"
800 ]
801 )
805-- DECLARATIONS
808toRegion :: Row -> Col -> A.Region
809toRegion row col =
810 let
811 pos = A.Position row col
812 in
813 A.Region pos pos
816toWiderRegion :: Row -> Col -> Word16 -> A.Region
817toWiderRegion row col extra =
818 A.Region
819 (A.Position row col)
820 (A.Position row (col + extra))
823toDeclarationsReport :: Code.Source -> Decl -> Report.Report
824toDeclarationsReport source decl =
825 case decl of
826 DeclStart row col ->
827 error "TODO DeclStart" row col
829 DeclSpace space row col ->
830 toSpaceReport source space row col
832 Port port row col ->
833 error "TODO Port" port row col
835 DeclType declType row col ->
836 error "TODO DeclType" declType row col
838 DeclDef name declDef row col ->
839 toDeclDefReport source name declDef row col
841 DeclFreshLineStart row col ->
842 error "TODO DeclFreshLineStart" row col
844 DeclFreshLineAfterDocComment row col ->
845 error "TODO DeclFreshLineAfterDocComment" row col
848toDeclDefReport :: Code.Source -> Name.Name -> DeclDef -> Row -> Col -> Report.Report
849toDeclDefReport source name declDef startRow startCol =
850 case declDef of
851 DeclDefSpace space row col ->
852 toSpaceReport source space row col
854 DeclDefEquals row col ->
855 error "TODO DeclDefEquals" row col
857 DeclDefType tipe row col ->
858 error "TODO DeclDefType" tipe row col
860 DeclDefArg pattern row col ->
861 error "TODO DeclDefArg" pattern row col
863 DeclDefBody expr row col ->
864 toExprReport source (InDef name startRow startCol) expr row col
866 DeclDefNameRepeat row col ->
867 error "TODO DeclDefNameRepeat" name row col
869 DeclDefNameMatch defName row col ->
870 error "TODO DeclDefNameMatch" name defName row col
872 DeclDefIndentType row col ->
873 error "TODO DeclDefIndentType" row col
875 DeclDefIndentEquals row col ->
876 error "TODO DeclDefIndentEquals" row col
878 DeclDefIndentBody row col ->
879 error "TODO DeclDefIndentBody" row col
881 DeclDefFreshLineAfterType row col ->
882 error "TODO DeclDefFreshLineAfterType" row col
886-- CONTEXT
889data Context
890 = InNode Node Row Col Context
891 | InDef Name.Name Row Col
894data Node
895 = NRecord
896 | NParens
897 | NList
898 | NFunc
899 | NCond
900 | NThen
901 | NElse
902 deriving (Eq)
905getDefName :: Context -> Name.Name
906getDefName context =
907 case context of
908 InDef name _ _ -> name
909 InNode _ _ _ c -> getDefName c
912isWithin :: Node -> Context -> Bool
913isWithin desiredNode context =
914 case context of
915 InDef _ _ _ -> False
916 InNode actualNode _ _ _ -> desiredNode == actualNode
920-- EXPR REPORTS
923toExprReport :: Code.Source -> Context -> Expr -> Row -> Col -> Report.Report
924toExprReport source context expr startRow startCol =
925 case expr of
926 Let _ _ _ ->
927 error "TODO Let"
929 Case _ _ _ ->
930 error "TODO Case"
932 If if_ row col ->
933 toIfReport source context if_ row col
935 List list row col ->
936 toListReport source context list row col
938 Record record row col ->
939 toRecordReport source context record row col
941 Tuple tuple row col ->
942 toTupleReport source context tuple row col
944 Func func row col ->
945 toFuncReport source context func row col
947 Dot row col ->
948 let region = toRegion row col in
949 Report.Report "EXPECTING RECORD ACCESSOR" region [] $
950 Code.toSnippet source region Nothing
951 (
952 D.reflow $
953 "I was expecting to see a record accessor here:"
954 ,
955 D.fillSep
956 ["Something","like",D.dullyellow".name","or",D.dullyellow".price"
957 ,"that","accesses","a","value","from","a","record."
958 ]
959 )
961 Access row col ->
962 let region = toRegion row col in
963 Report.Report "EXPECTING RECORD ACCESSOR" region [] $
964 Code.toSnippet source region Nothing
965 (
966 D.reflow $
967 "I am trying to parse a record accessor here:"
968 ,
969 D.stack
970 [
971 D.fillSep
972 ["Something","like",D.dullyellow".name","or",D.dullyellow".price"
973 ,"that","accesses","a","value","from","a","record."
974 ]
975 ,
976 D.toSimpleNote $
977 "Record field names must start with a lower case letter!"
978 ]
979 )
981 OperatorRight op row col ->
982 let region = toRegion row col in
983 Report.Report "MISSING EXPRESSION" region [] $
984 Code.toSnippet source region Nothing
985 (
986 D.reflow $
987 "I was expecting to see an expression after this " ++ Name.toChars op ++ " operator:"
988 ,
989 D.stack
990 [ D.fillSep $
991 ["You","can","just","put","anything","for","now,","like"
992 ,D.dullyellow "42","or",D.dullyellow"\"hello\"" <> "."
993 ,"Once","there","is","something","there,","I","can","probably"
994 ,"give","a","more","specific","hint!"
995 ]
996 , D.toSimpleNote $
997 "This can also happen if run into reserved words like `let` or `as` unexpectedly.\
998 \ Or if I run into operators in unexpected spots. Point is, there are a\
999 \ couple ways I can get confused and give sort of weird advice!"
1003 OperatorReserved operator row col ->
1004 toOperatorReport source context operator row col
1006 Start row col ->
1007 let
1008 (contextRow, contextCol, aThing) =
1009 case context of
1010 InDef name r c -> (r, c, "the `" ++ Name.toChars name ++ "` definition")
1011 InNode NRecord r c _ -> (r, c, "a record")
1012 InNode NParens r c _ -> (r, c, "some parentheses")
1013 InNode NList r c _ -> (r, c, "a list")
1014 InNode NFunc r c _ -> (r, c, "an anonymous function")
1015 InNode NCond r c _ -> (r, c, "an `if` expression")
1016 InNode NThen r c _ -> (r, c, "an `if` expression")
1017 InNode NElse r c _ -> (r, c, "an `if` expression")
1018 -- TODO check if this is actually the best way to get error messages here
1020 surroundings = A.Region (A.Position contextRow contextCol) (A.Position row col)
1021 region = toRegion row col
1022 in
1023 Report.Report "MISSING EXPRESSION" region [] $
1024 Code.toSnippet source surroundings (Just region)
1026 D.reflow $
1027 "I am partway through parsing " ++ aThing ++ ", but I got stuck here:"
1029 D.stack
1030 [ D.fillSep $
1031 ["I","was","expecting","to","see","an","expression","like"
1032 ,D.dullyellow "42","or",D.dullyellow"\"hello\"" <> "."
1033 ,"Once","there","is","something","there,","I","can","probably"
1034 ,"give","a","more","specific","hint!"
1036 , D.toSimpleNote $
1037 "This can also happen if run into reserved words like `let` or `as` unexpectedly.\
1038 \ Or if I run into operators in unexpected spots. Point is, there are a\
1039 \ couple ways I can get confused and give sort of weird advice!"
1043 Char char row col ->
1044 toCharReport source char row col
1046 String string row col ->
1047 toStringReport source string row col
1049 Number number row col ->
1050 toNumberReport source number row col
1052 Space space row col ->
1053 toSpaceReport source space row col
1055 EndlessShader row col ->
1056 let
1057 region = toWiderRegion row col 6
1058 in
1059 Report.Report "ENDLESS SHADER" region [] $
1060 Code.toSnippet source region Nothing
1062 D.reflow "I cannot find the end of this shader:"
1064 D.reflow "Add a |] somewhere after this to end the shader."
1067 ShaderProblem problem row col ->
1068 let
1069 region = toRegion row col
1070 in
1071 Report.Report "SHADER PROBLEM" region [] $
1072 Code.toSnippet source region Nothing
1074 D.reflow $
1075 "I ran into a problem while parsing this GLSL block."
1077 D.stack
1078 [ D.reflow $
1079 "I use a 3rd party GLSL parser for now, and I did my best to extract their error message:"
1080 , D.indent 4 $ D.vcat $
1081 map D.fromChars (filter (/="") (lines problem))
1085 IndentOperatorRight op row col ->
1086 let
1087 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1088 region = toRegion row col
1089 in
1090 Report.Report "MISSING EXPRESSION" region [] $
1091 Code.toSnippet source surroundings (Just region)
1093 D.reflow $
1094 "I was expecting to see an expression after this " ++ Name.toChars op ++ " operator:"
1096 D.stack
1098 D.fillSep $
1099 ["You","can","just","put","anything","for","now,","like"
1100 ,D.dullyellow "42","or",D.dullyellow"\"hello\"" <> "."
1101 ,"Once","there","is","something","there,","I","can","probably"
1102 ,"give","a","more","specific","hint!"
1105 D.toSimpleNote $
1106 "I may be getting confused by your indentation? The easiest way to make sure\
1107 \ this is not an indentation problem is to put the expression on the right of\
1108 \ the " ++ Name.toChars op ++ " operator on the same line."
1112 IndentMoreExpr _ _ ->
1113 error "TODO IndentMoreExpr"
1117-- CHAR
1120toCharReport :: Code.Source -> Char -> Row -> Col -> Report.Report
1121toCharReport source char row col =
1122 case char of
1123 CharEndless ->
1124 let
1125 region = toRegion row col
1126 in
1127 Report.Report "MISSING SINGLE QUOTE" region [] $
1128 Code.toSnippet source region Nothing
1130 D.reflow $
1131 "I thought I was parsing a character, but I got to the end of\
1132 \ the line without seeing the closing single quote:"
1134 D.reflow $
1135 "Add a closing single quote here!"
1138 CharEscape escape ->
1139 toEscapeReport source escape row col
1141 CharNotString width ->
1142 let
1143 region = toWiderRegion row col width
1144 in
1145 Report.Report "NEEDS DOUBLE QUOTES" region [] $
1146 Code.toSnippet source region Nothing
1148 "The following string uses single quotes:"
1150 D.stack
1151 [ "Please switch to double quotes instead:"
1152 , D.indent 4 $
1153 D.dullyellow "'this'" <> " => " <> D.green "\"this\""
1154 , D.toSimpleNote $
1155 "Elm uses double quotes for strings like \"hello\", whereas it uses single\
1156 \ quotes for individual characters like 'a' and 'ø'. This distinction helps with\
1157 \ code like (String.any (\\c -> c == 'X') \"90210\") where you are inspecting\
1158 \ individual characters."
1164-- STRING
1167toStringReport :: Code.Source -> String -> Row -> Col -> Report.Report
1168toStringReport source string row col =
1169 case string of
1170 StringEndless_Single ->
1171 let
1172 region = toRegion row col
1173 in
1174 Report.Report "ENDLESS STRING" region [] $
1175 Code.toSnippet source region Nothing
1177 D.reflow $
1178 "I got to the end of the line without seeing the closing double quote:"
1180 D.stack
1181 [ D.fillSep $
1182 ["Strings","look","like",D.green "\"this\"","with","double"
1183 ,"quotes","on","each","end.","Is","the","closing","double"
1184 ,"quote","missing","in","your","code?"
1186 , D.link "Note" "Read" "TODO" "if you want a string that spans multiple lines."
1190 StringEndless_Multi ->
1191 let
1192 region = toWiderRegion row col 3
1193 in
1194 Report.Report "ENDLESS STRING" region [] $
1195 Code.toSnippet source region Nothing
1197 D.reflow $
1198 "I cannot find the end of this multi-line string:"
1200 D.stack
1201 [ D.reflow "Add a \"\"\" somewhere after this to end the string."
1202 , D.link "Hint" "Read" "TODO" "for more information on strings and multi-line strings."
1206 StringEscape escape ->
1207 toEscapeReport source escape row col
1211-- ESCAPES
1214toEscapeReport :: Code.Source -> Escape -> Row -> Col -> Report.Report
1215toEscapeReport source escape row col =
1216 case escape of
1217 EscapeUnknown ->
1218 let
1219 region = toWiderRegion row col 2
1220 in
1221 Report.Report "UNKNOWN ESCAPE" region [] $
1222 Code.toSnippet source region Nothing
1224 D.reflow $
1225 "Backslashes always start escaped characters, but I do not recognize this one:"
1227 D.stack
1228 [ D.reflow $
1229 "Valid escape characters include:"
1230 , D.dullyellow $ D.indent 4 $ D.vcat $
1231 [ "\\n"
1232 , "\\r"
1233 , "\\t"
1234 , "\\\""
1235 , "\\\'"
1236 , "\\\\"
1237 , "\\u{003D}"
1239 , D.reflow $
1240 "Do you want one of those instead? Maybe you need \\\\ to escape a backslash?"
1241 , D.toSimpleNote $
1242 "The last style lets encode ANY character by its Unicode code\
1243 \ point. That means \\u{0009} and \\t are the same. You can use\
1244 \ that style for anything not covered by the other six escapes!"
1248 BadUnicodeFormat width ->
1249 let
1250 region = toWiderRegion row col width
1251 in
1252 Report.Report "BAD UNICODE ESCAPE" region [] $
1253 Code.toSnippet source region Nothing
1255 D.reflow $
1256 "I ran into an invalid Unicode escape:"
1258 D.stack
1259 [ D.reflow $
1260 "Here are some examples of valid Unicode escapes:"
1261 , D.dullyellow $ D.indent 4 $ D.vcat $
1262 [ "\\u{0041}"
1263 , "\\u{03BB}"
1264 , "\\u{6728}"
1265 , "\\u{1F60A}"
1267 , D.reflow $
1268 "Notice that the code point is always surrounded by curly braces.\
1269 \ Maybe you are missing the opening or closing curly brace?"
1272 BadUnicodeCode width ->
1273 let
1274 region = toWiderRegion row col width
1275 in
1276 Report.Report "BAD UNICODE ESCAPE" region [] $
1277 Code.toSnippet source region Nothing
1279 D.reflow $
1280 "This is not a valid code point:"
1282 D.reflow $
1283 "The valid code points are between 0 and 10FFFF inclusive."
1286 BadUnicodeLength width numDigits badCode ->
1287 let
1288 region = toWiderRegion row col width
1289 in
1290 Report.Report "BAD UNICODE ESCAPE" region [] $
1291 Code.toSnippet source region Nothing $
1292 if numDigits < 4 then
1294 D.reflow $
1295 "Every code point needs at least four digits:"
1297 let
1298 goodCode = replicate (4 - numDigits) '0' ++ map Char.toUpper (showHex badCode "")
1299 suggestion = "\\u{" <> D.fromChars goodCode <> "}"
1300 in
1301 D.fillSep ["Try",D.green suggestion,"instead?"]
1304 else
1306 D.reflow $
1307 "This code point has too many digits:"
1309 D.fillSep $
1310 ["Valid","code","points","are","between"
1311 ,D.green "\\u{0000}","and",D.green "\\u{10FFFF}" <> ","
1312 ,"so","try","trimming","any","leading","zeros","until"
1313 ,"you","have","between","four","and","six","digits."
1319-- NUMBERS
1322toNumberReport :: Code.Source -> Number -> Row -> Col -> Report.Report
1323toNumberReport source number row col =
1324 let
1325 region = toRegion row col
1326 in
1327 case number of
1328 NumberEnd ->
1329 Report.Report "WEIRD NUMBER" region [] $
1330 Code.toSnippet source region Nothing
1332 D.reflow $
1333 "I thought I was reading a number, but I ran into some weird stuff here:"
1335 D.stack
1336 [ D.reflow $
1337 "I recognize numbers in the following formats:"
1338 , D.indent 4 $ D.vcat [ "42", "3.14", "6.022e23", "0x002B" ]
1339 , D.reflow $
1340 "So is there a way to write it like one of those?"
1344 NumberDot int ->
1345 Report.Report "WEIRD NUMBER" region [] $
1346 Code.toSnippet source region Nothing
1348 D.reflow $
1349 "Numbers cannot end with a dot like this:"
1351 D.fillSep
1352 ["Switching","to",D.green (D.fromChars (show int))
1353 ,"or",D.green (D.fromChars (show int ++ ".0"))
1354 ,"will","work","though!"
1358 NumberHexDigit ->
1359 Report.Report "WEIRD HEXIDECIMAL" region [] $
1360 Code.toSnippet source region Nothing
1362 D.reflow $
1363 "I thought I was reading a hexidecimal number until I got here:"
1365 D.stack
1366 [ D.reflow $
1367 "Valid hexidecimal digits include 0123456789abcdefABCDEF, so I can\
1368 \ only recognize things like this:"
1369 , D.indent 4 $ D.vcat [ "0x2B", "0x002B", "0x00ffb3" ]
1373 NumberNoLeadingZero ->
1374 Report.Report "LEADING ZEROS" region [] $
1375 Code.toSnippet source region Nothing
1377 D.reflow $
1378 "I do not accept numbers with leading zeros:"
1380 D.stack
1381 [ D.reflow $
1382 "Just delete the leading zeros and it should work!"
1383 , D.toSimpleNote $
1384 "Some languages let you to specify octal numbers by adding a leading zero.\
1385 \ So in C, writing 0111 is the same as writing 73. Some people are used to\
1386 \ that, but others probably want it to equal 111. Either path is going to\
1387 \ surprise people from certain backgrounds, so Elm tries to avoid this whole\
1388 \ situation."
1394-- OPERATORS
1397toOperatorReport :: Code.Source -> Context -> BadOperator -> Row -> Col -> Report.Report
1398toOperatorReport source context operator row col =
1399 case operator of
1400 BadDot ->
1401 let
1402 region = toRegion row col
1403 in
1404 Report.Report "UNEXPECTED SYMBOL" region [] $
1405 Code.toSnippet source region Nothing
1407 "I was not expecting this dot:"
1409 D.reflow $
1410 "Dots are for record access and decimal points, so\
1411 \ they cannot float around on their own. Maybe\
1412 \ there is some extra whitespace?"
1415 BadPipe ->
1416 let
1417 region = toRegion row col
1418 in
1419 Report.Report "UNEXPECTED SYMBOL" region [] $
1420 Code.toSnippet source region Nothing
1422 D.reflow $
1423 "I was not expecting this vertical bar:"
1425 D.reflow $
1426 "Vertical bars should only appear in custom type declarations. Maybe you want || instead?"
1429 BadArrow ->
1430 let
1431 region = toWiderRegion row col 2
1432 in
1433 Report.Report "UNEXPECTED ARROW" region [] $
1434 Code.toSnippet source region Nothing $
1435 if error "TODO inCase" then
1437 D.reflow $
1438 "I was not expecting to see an arrow here:"
1440 D.stack
1442 D.reflow $
1443 "I think I am parsing a `case` expression right now, so it makes sense to\
1444 \ see arrows around here. This one is confusing me though!"
1446 D.toSimpleHint $
1447 "I may be getting confused by the indentation. Every pattern in a `case` must be\
1448 \ exactly aligned (with exactly the same amount of indentation) so maybe this arrow\
1449 \ appears after the next `case` pattern (correctly!) but the pattern itself is\
1450 \ indented too far?"
1454 else
1456 D.reflow $
1457 "I was not expecting an arrow here:"
1459 D.reflow $
1460 "Arrows should only appear in `case` expressions and anonymous functions. Maybe\
1461 \ you want > or >= instead?"
1464 BadEquals ->
1465 let
1466 region = toRegion row col
1467 name = getDefName context
1468 in
1469 Report.Report "UNEXPECTED EQUALS" region [] $
1470 Code.toSnippet source region Nothing
1472 D.reflow $
1473 "I was not expecting to see this equals sign:"
1475 D.stack
1477 D.reflow "Maybe you want == instead? To check if two values are equal?"
1479 D.toSimpleNote $
1480 if isWithin NRecord context then
1481 "Records look like { x = 3, y = 4 } with the equals sign right\
1482 \ after the field name. So maybe you forgot a comma?"
1483 else
1484 "I may be getting confused by your indentation. Is this supposed to be part of\
1485 \ a definition AFTER the `" ++ Name.toChars name ++ "` definition? If so,\
1486 \ the problem may be a bit before the equals sign. I need all definitions to\
1487 \ be exactly aligned (with exactly the same indentation) so the problem may be that\
1488 \ this new definition is indented a bit too much."
1492 BadHasType ->
1493 let
1494 region = toRegion row col
1495 name = getDefName context
1496 in
1497 Report.Report "UNEXPECTED SYMBOL" region [] $
1498 Code.toSnippet source region Nothing $
1500 D.reflow $
1501 "I was not expecting to run into the \"has type\" symbol here:"
1503 D.stack
1505 D.fillSep
1506 ["Maybe","you","want",D.green "::","instead?"
1507 ,"To","put","something","on","the","front","of","a","list?"
1509 , D.toSimpleNote $
1510 "The single colon is reserved for type annotations and record types, but I think\
1511 \ I am parsing the definition of `" ++ Name.toChars name ++ "` right now."
1513 D.toSimpleNote $
1514 "I may be getting confused by your indentation. Is this supposed to be part of\
1515 \ a type annotation AFTER the `" ++ Name.toChars name ++ "` definition? If so,\
1516 \ the problem may be a bit before the \"has type\" symbol. I need all definitions to\
1517 \ be exactly aligned (with exactly the same indentation) so the problem may be that\
1518 \ this new definition is indented a bit too much."
1524-- IF
1527toIfReport :: Code.Source -> Context -> If -> Row -> Col -> Report.Report
1528toIfReport source context if_ startRow startCol =
1529 case if_ of
1530 IfSpace space row col ->
1531 toSpaceReport source space row col
1533 IfThen row col ->
1534 let
1535 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1536 region = toRegion row col
1537 in
1538 Report.Report "UNFINISHED IF" region [] $
1539 Code.toSnippet source surroundings (Just region)
1541 D.reflow $
1542 "I was expecting to see more of this `if` expression, but I got stuck here:"
1544 D.fillSep $
1545 ["I","was","expecting","to","see","the",D.green "then","keyword","next."
1549 IfElse row col ->
1550 let
1551 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1552 region = toRegion row col
1553 in
1554 Report.Report "UNFINISHED IF" region [] $
1555 Code.toSnippet source surroundings (Just region)
1557 D.reflow $
1558 "I was expecting to see more of this `if` expression, but I got stuck here:"
1560 D.fillSep $
1561 ["I","was","expecting","to","see","the",D.green "else","keyword","next."
1565 IfElseBranchStart row col ->
1566 let
1567 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1568 region = toRegion row col
1569 in
1570 Report.Report "UNFINISHED IF" region [] $
1571 Code.toSnippet source surroundings (Just region)
1573 D.reflow $
1574 "I just saw the start of an `else` branch, but then I got stuck here:"
1576 D.reflow $
1577 "I was expecting to see an expression next. Maybe it is not filled in yet?"
1580 IfCondition expr row col ->
1581 toExprReport source (InNode NCond startRow startCol context) expr row col
1583 IfThenBranch expr row col ->
1584 toExprReport source (InNode NThen startRow startCol context) expr row col
1586 IfElseBranch expr row col ->
1587 toExprReport source (InNode NElse startRow startCol context) expr row col
1589 IfIndentCondition row col ->
1590 let
1591 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1592 region = toRegion row col
1593 in
1594 Report.Report "UNFINISHED IF" region [] $
1595 Code.toSnippet source surroundings (Just region)
1597 D.reflow $
1598 "I was expecting to see more of this `if` expression, but I got stuck here:"
1600 D.stack
1601 [ D.fillSep $
1602 ["I","was","expecting","to","see","an","expression","like",D.dullyellow "x < 0"
1603 ,"that","evaluates","to","True","or","False."
1605 , D.toSimpleNote $
1606 "I can be confused by indentation. Maybe something is not indented enough?"
1610 IfIndentThen row col ->
1611 let
1612 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1613 region = toRegion row col
1614 in
1615 Report.Report "UNFINISHED IF" region [] $
1616 Code.toSnippet source surroundings (Just region)
1618 D.reflow $
1619 "I was expecting to see more of this `if` expression, but I got stuck here:"
1621 D.stack
1622 [ D.fillSep $
1623 ["I","was","expecting","to","see","the",D.green "then","keyword","next."
1625 , D.toSimpleNote $
1626 "I can be confused by indentation. Maybe something is not indented enough?"
1630 IfIndentThenBranch row col ->
1631 let
1632 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1633 region = toRegion row col
1634 in
1635 Report.Report "UNFINISHED IF" region [] $
1636 Code.toSnippet source surroundings (Just region)
1638 D.reflow $
1639 "I got stuck after the start of this `then` branch:"
1641 D.stack
1642 [ D.reflow $
1643 "I was expecting to see an expression next. Maybe it is not filled in yet?"
1644 , D.toSimpleNote $
1645 "I can be confused by indentation, so if the `then` branch is already\
1646 \ present, it may not be indented enough for me to recognize it."
1650 IfIndentElseBranch row col ->
1651 let
1652 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1653 region = toRegion row col
1654 in
1655 Report.Report "UNFINISHED IF" region [] $
1656 Code.toSnippet source surroundings (Just region)
1658 D.reflow $
1659 "I got stuck after the start of this `else` branch:"
1661 D.stack
1662 [ D.reflow $
1663 "I was expecting to see an expression next. Maybe it is not filled in yet?"
1664 , D.toSimpleNote $
1665 "I can be confused by indentation, so if the `else` branch is already\
1666 \ present, it may not be indented enough for me to recognize it."
1670 IfIndentElse row col ->
1671 let
1672 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1673 region = toRegion row col
1674 in
1675 Report.Report "UNFINISHED IF" region [] $
1676 Code.toSnippet source surroundings (Just region)
1678 D.reflow $
1679 "I was expecting to see an `else` branch after this:"
1681 D.stack
1682 [ D.reflow $
1683 "I know what to do when the condition is `True`, but not when it is `False`."
1684 , D.fillSep
1685 ["Add","an",D.green "else","branch","to","handle","that","scenario!"]
1691-- RECORD
1694toRecordReport :: Code.Source -> Context -> Record -> Row -> Col -> Report.Report
1695toRecordReport source context record startRow startCol =
1696 case record of
1697 RecordOpen row col ->
1698 let
1699 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1700 region = toRegion row col
1701 in
1702 case Code.whatIsNext source row col of
1703 Code.Keyword keyword ->
1704 Report.Report "RESERVED WORD" region [] $
1705 Code.toSnippet source surroundings (Just region)
1707 D.reflow $
1708 "I just started parsing a record, but I got stuck on this field name:"
1710 D.reflow $
1711 "It looks like you are trying to use `" ++ keyword ++ "` as a field name, but \
1712 \ that is a reserved word. Try using a different name!"
1715 _ ->
1716 Report.Report "UNFINISHED RECORD" region [] $
1717 Code.toSnippet source surroundings (Just region)
1719 D.reflow $
1720 "I just started parsing a record, but I got stuck here:"
1722 D.fillSep
1723 ["Records","look","like",D.dullyellow "{ x = 3, y = 4 },"
1724 ,"so","I","was","expecting","to","see","a","field","name","next."
1728 RecordEnd row col ->
1729 let
1730 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1731 region = toRegion row col
1732 in
1733 Report.Report "UNFINISHED RECORD" region [] $
1734 Code.toSnippet source surroundings (Just region)
1736 D.reflow $
1737 "I am partway through parsing a record, but I got stuck here:"
1739 D.stack
1740 [ D.fillSep
1741 ["I","was","expecting","to","see","a","closing","curly","brace","before","this,"
1742 ,"so","try","adding","a",D.dullyellow "}","and","see","if","that","helps?"
1744 , D.toSimpleNote $
1745 "When I get stuck like this, it usually means that there is a missing parenthesis\
1746 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
1750 RecordField row col ->
1751 let
1752 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1753 region = toRegion row col
1754 in
1755 case Code.whatIsNext source row col of
1756 Code.Keyword keyword ->
1757 Report.Report "RESERVED WORD" region [] $
1758 Code.toSnippet source surroundings (Just region)
1760 D.reflow $
1761 "I am partway through parsing a record, but I got stuck on this field name:"
1763 D.reflow $
1764 "It looks like you are trying to use `" ++ keyword ++ "` as a field name, but \
1765 \ that is a reserved word. Try using a different name!"
1768 _ ->
1769 Report.Report "UNFINISHED RECORD" region [] $
1770 Code.toSnippet source surroundings (Just region)
1772 D.reflow $
1773 "I am partway through parsing a record, but I got stuck after that last comma:"
1775 addNoteForRecordError $
1776 D.reflow $
1777 "Trailing commas are not allowed in records, so I was expecting to see another\
1778 \ record field defined next. If you are done defining the record, the fix may\
1779 \ be to delete that last comma?"
1782 RecordEquals row col ->
1783 let
1784 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1785 region = toRegion row col
1786 in
1787 Report.Report "UNFINISHED RECORD" region [] $
1788 Code.toSnippet source surroundings (Just region)
1790 D.reflow $
1791 "I am partway through parsing a record, but I got stuck here:"
1793 addNoteForRecordError $
1794 D.fillSep $
1795 ["I","just","saw","a","field","name,","so","I","was","expecting","to","see"
1796 ,"an","equals","sign","next.","So","try","putting","an",D.green "=","sign","here?"
1800 RecordExpr expr row col ->
1801 toExprReport source (InNode NRecord startRow startCol context) expr row col
1803 RecordSpace space row col ->
1804 toSpaceReport source space row col
1806 RecordIndentOpen row col ->
1807 let
1808 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1809 region = toRegion row col
1810 in
1811 Report.Report "UNFINISHED RECORD" region [] $
1812 Code.toSnippet source surroundings (Just region)
1814 D.reflow $
1815 "I just saw the opening curly brace of a record, but then I got stuck here:"
1817 addNoteForRecordIndentError $
1818 D.fillSep $
1819 ["I","am","expecting","a","record","like",D.dullyellow "{ x = 3, y = 4 }","here."
1820 ,"Try","defining","some","fields","of","your","own?"
1824 RecordIndentEnd row col ->
1825 let
1826 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1827 region = toRegion row col
1828 in
1829 Report.Report "UNFINISHED RECORD" region [] $
1830 Code.toSnippet source surroundings (Just region)
1832 D.reflow $
1833 "I was expecting to see a closing curly brace next:"
1835 addNoteForRecordIndentError $
1836 D.fillSep $
1837 ["Try","putting","an",D.green "}","and","see","if","that","helps?"
1841 RecordIndentField row col ->
1842 let
1843 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1844 region = toRegion row col
1845 in
1846 Report.Report "UNFINISHED RECORD" region [] $
1847 Code.toSnippet source surroundings (Just region)
1849 D.reflow $
1850 "I am partway through parsing a record, but I got stuck after that last comma:"
1852 addNoteForRecordError $
1853 D.reflow $
1854 "Trailing commas are not allowed in records, so the fix may be to\
1855 \ delete that last comma? Or maybe you were in the middle of defining\
1856 \ an additional field?"
1859 RecordIndentEquals row col ->
1860 let
1861 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1862 region = toRegion row col
1863 in
1864 Report.Report "UNFINISHED RECORD" region [] $
1865 Code.toSnippet source surroundings (Just region)
1867 D.reflow $
1868 "I am partway through parsing a record. I just saw a record\
1869 \ field, so I was expecting to see an equals sign next:"
1871 addNoteForRecordIndentError $
1872 D.fillSep $
1873 ["Try","putting","an",D.green "=","followed","by","an","expression?"
1877 RecordIndentExpr row col ->
1878 let
1879 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1880 region = toRegion row col
1881 in
1882 Report.Report "UNFINISHED RECORD" region [] $
1883 Code.toSnippet source surroundings (Just region)
1885 D.reflow $
1886 "I am partway through parsing a record, and I was expecting to run into an expression next:"
1888 addNoteForRecordIndentError $
1889 D.fillSep $
1890 ["Try","putting","something,","like"
1891 ,D.dullyellow "42","or",D.dullyellow"\"hello\"","for","now?"
1896addNoteForRecordError :: D.Doc -> D.Doc
1897addNoteForRecordError normalRecommendation =
1898 D.stack $
1899 normalRecommendation
1901 [ D.toSimpleNote
1902 "If you are trying to define a record across multiple lines, I recommend using this format:"
1903 , D.indent 4 $ D.vcat $
1904 [ "{ name = \"Alice\""
1905 , ", age = 42"
1906 , ", height = 1.75"
1907 , "}"
1909 , D.reflow $
1910 "Notice that nothing comes directly after a newline. Each line starts with some spaces. I\
1911 \ know this style can be jarring for people coming from C-like syntax, but folks generally\
1912 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
1916addNoteForRecordIndentError :: D.Doc -> D.Doc
1917addNoteForRecordIndentError normalRecommendation =
1918 D.stack $
1919 normalRecommendation
1921 [ D.toSimpleNote
1922 "I may be confused by indentation. For example, if you are trying to define\
1923 \ a record across multiple lines, I recommend using this format:"
1924 , D.indent 4 $ D.vcat $
1925 [ "[ \"Alice\""
1926 , ", \"Bob\""
1927 , ", \"Chuck\""
1928 , "]"
1930 , D.reflow $
1931 "Notice that nothing comes directly after a newline. Each line starts with some spaces. I\
1932 \ know this style can be jarring for people coming from C-like syntax, but folks generally\
1933 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
1938-- TUPLE
1941toTupleReport :: Code.Source -> Context -> Tuple -> Row -> Col -> Report.Report
1942toTupleReport source context tuple startRow startCol =
1943 case tuple of
1944 TupleExpr expr row col ->
1945 toExprReport source (InNode NParens startRow startCol context) expr row col
1947 TupleSpace space row col ->
1948 toSpaceReport source space row col
1950 TupleEnd row col ->
1951 let
1952 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1953 region = toRegion row col
1954 in
1955 Report.Report "UNFINISHED PARENTHESES" region [] $
1956 Code.toSnippet source surroundings (Just region)
1958 D.reflow $
1959 "I was expecting to see a closing parentheses next, but I got stuck here:"
1961 D.stack
1962 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps?"]
1963 , D.toSimpleNote $
1964 "I can get stuck when I run into keywords, operators, parentheses, or brackets\
1965 \ unexpectedly. So there may be some earlier syntax trouble (like extra parenthesis\
1966 \ or missing brackets) that is confusing me."
1970 TupleOperatorClose row col ->
1971 let
1972 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1973 region = toRegion row col
1974 in
1975 Report.Report "UNFINISHED OPERATOR FUNCTION" region [] $
1976 Code.toSnippet source surroundings (Just region)
1978 D.reflow "I was expecting a closing parenthesis here:"
1980 D.stack
1981 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps!"]
1982 , D.toSimpleNote $
1983 "I think I am parsing an operator function right now, so I am expecting to see\
1984 \ something like (+) or (&&) where an operator is surrounded by parentheses with\
1985 \ no extra spaces."
1989 TupleOperatorReserved operator row col ->
1990 let
1991 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1992 region = toRegion row col
1993 in
1994 Report.Report "UNEXPECTED SYMBOL" region [] $
1995 Code.toSnippet source surroundings (Just region)
1997 D.reflow $
1998 "I ran into an unexpected symbol here:"
2000 D.fillSep $
2001 case operator of
2002 BadDot -> ["Maybe","you","wanted","a","record","accessor","like",D.dullyellow ".x","or",D.dullyellow ".name","instead?"]
2003 BadPipe -> ["Try",D.dullyellow "(||)","instead?","To","turn","boolean","OR","into","a","function?"]
2004 BadArrow -> ["Maybe","you","wanted",D.dullyellow "(>)","or",D.dullyellow "(>=)","instead?"]
2005 BadEquals -> ["Try",D.dullyellow "(==)","instead?","To","make","a","function","that","checks","equality?"]
2006 BadHasType -> ["Try",D.dullyellow "(::)","instead?","To","add","values","to","the","front","of","lists?"]
2009 TupleIndentExpr1 row col ->
2010 let
2011 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2012 region = toRegion row col
2013 in
2014 Report.Report "UNFINISHED PARENTHESES" region [] $
2015 Code.toSnippet source surroundings (Just region)
2017 D.reflow $
2018 "I just saw an open parenthesis, so I was expecting to see an expression next."
2020 D.stack
2021 [ D.fillSep $
2022 ["Something","like",D.dullyellow "(4 + 5)","or"
2023 ,D.dullyellow "(String.reverse \"desserts\")" <> "."
2024 ,"Anything","where","you","are","putting","parentheses","around","normal","expressions."
2026 , D.toSimpleNote $
2027 "I can get confused by indentation in cases like this, so\
2028 \ maybe you have an expression but it is not indented enough?"
2032 TupleIndentExprN 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 TUPLE" region [] $
2038 Code.toSnippet source surroundings (Just region)
2040 D.reflow $
2041 "I think I am in the middle of parsing a tuple. I just saw a comma, so I was expecting to see expression next."
2043 D.stack
2044 [ D.fillSep $
2045 ["A","tuple","looks","like",D.dullyellow "(3,4)","or"
2046 ,D.dullyellow "(\"Tom\",42)" <> ","
2047 ,"so","I","think","there","is","an","expression","missing","here?"
2049 , D.toSimpleNote $
2050 "I can get confused by indentation in cases like this, so\
2051 \ maybe you have an expression but it is not indented enough?"
2055 TupleIndentEnd row col ->
2056 let
2057 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2058 region = toRegion row col
2059 in
2060 Report.Report "UNFINISHED PARENTHESES" region [] $
2061 Code.toSnippet source surroundings (Just region)
2063 D.reflow $
2064 "I was expecting to see a closing parenthesis next:"
2066 D.stack
2067 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps!"]
2068 , D.toSimpleNote $
2069 "I can get confused by indentation in cases like this, so\
2070 \ maybe you have a closing parenthesis but it is not indented enough?"
2075toListReport :: Code.Source -> Context -> List -> Row -> Col -> Report.Report
2076toListReport source context list startRow startCol =
2077 case list of
2078 ListSpace space row col ->
2079 toSpaceReport source space row col
2081 ListOpen row col ->
2082 let
2083 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2084 region = toRegion row col
2085 in
2086 Report.Report "UNFINISHED LIST" region [] $
2087 Code.toSnippet source surroundings (Just region)
2089 D.reflow $
2090 "I am partway through parsing a list, but I got stuck here:"
2092 D.stack
2093 [ D.fillSep
2094 ["I","was","expecting","to","see","a","closing","square","bracket","before","this,"
2095 ,"so","try","adding","a",D.dullyellow "]","and","see","if","that","helps?"
2097 , D.toSimpleNote $
2098 "When I get stuck like this, it usually means that there is a missing parenthesis\
2099 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
2103 ListExpr expr row col ->
2104 case expr of
2105 Start r c ->
2106 let
2107 surroundings = A.Region (A.Position startRow startCol) (A.Position r c)
2108 region = toRegion r c
2109 in
2110 Report.Report "UNFINISHED LIST" region [] $
2111 Code.toSnippet source surroundings (Just region)
2113 D.reflow $
2114 "I was expecting to see another list entry after that last comma:"
2116 D.stack
2117 [ D.reflow $
2118 "Trailing commas are not allowed in lists, so the fix may be to delete the comma?"
2119 , D.toSimpleNote
2120 "I recommend using the following format for lists that span multiple lines:"
2121 , D.indent 4 $ D.vcat $
2122 [ "[ \"Alice\""
2123 , ", \"Bob\""
2124 , ", \"Chuck\""
2125 , "]"
2127 , D.reflow $
2128 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
2129 \ This style can be jarring for people coming from C-like syntax, but folks generally\
2130 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
2134 _ ->
2135 toExprReport source (InNode NList startRow startCol context) expr row col
2137 ListEnd row col ->
2138 let
2139 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2140 region = toRegion row col
2141 in
2142 Report.Report "UNFINISHED LIST" region [] $
2143 Code.toSnippet source surroundings (Just region)
2145 D.reflow $
2146 "I am partway through parsing a list, but I got stuck here:"
2148 D.stack
2149 [ D.fillSep
2150 ["I","was","expecting","to","see","a","closing","square","bracket","before","this,"
2151 ,"so","try","adding","a",D.dullyellow "]","and","see","if","that","helps?"
2153 , D.toSimpleNote $
2154 "When I get stuck like this, it usually means that there is a missing parenthesis\
2155 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
2159 ListIndentOpen row col ->
2160 let
2161 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2162 region = toRegion row col
2163 in
2164 Report.Report "UNFINISHED LIST" region [] $
2165 Code.toSnippet source surroundings (Just region)
2167 D.reflow $
2168 "I cannot find the end of this list:"
2170 D.stack
2171 [ D.fillSep $
2172 ["You","could","change","it","to","something","like"
2173 ,D.dullyellow "[3,4,5]"
2174 ,"or","even","just"
2175 ,D.dullyellow "[]" <> "."
2176 ,"Anything","where","there","is","an","open","and","close","square","brace,"
2177 ,"and","where","the","elements","of","the","list","are","separated","by","commas."
2179 , D.toSimpleNote
2180 "I may be confused by indentation. For example, if you are trying to define\
2181 \ a list across multiple lines, I recommend using this format:"
2182 , D.indent 4 $ D.vcat $
2183 [ "[ \"Alice\""
2184 , ", \"Bob\""
2185 , ", \"Chuck\""
2186 , "]"
2188 , D.reflow $
2189 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
2190 \ This style can be jarring for people coming from C-like syntax, but folks generally\
2191 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
2195 ListIndentEnd row col ->
2196 let
2197 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2198 region = toRegion row col
2199 in
2200 Report.Report "UNFINISHED LIST" region [] $
2201 Code.toSnippet source surroundings (Just region)
2203 D.reflow $
2204 "I cannot find the end of this list:"
2206 D.stack
2207 [ D.fillSep $
2208 ["You","can","just","add","a","closing",D.dullyellow "]"
2209 ,"right","here,","and","I","will","be","all","set!"
2211 , D.toSimpleNote
2212 "I may be confused by indentation. For example, if you are trying to define\
2213 \ a list across multiple lines, I recommend using this format:"
2214 , D.indent 4 $ D.vcat $
2215 [ "[ \"Alice\""
2216 , ", \"Bob\""
2217 , ", \"Chuck\""
2218 , "]"
2220 , D.reflow $
2221 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
2222 \ This style can be jarring for people coming from C-like syntax, but folks generally\
2223 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
2227 ListIndentExpr row col ->
2228 let
2229 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2230 region = toRegion row col
2231 in
2232 Report.Report "UNFINISHED LIST" region [] $
2233 Code.toSnippet source surroundings (Just region)
2235 D.reflow $
2236 "I was expecting to see another list entry after this comma:"
2238 D.stack
2239 [ D.reflow $
2240 "Trailing commas are not allowed in lists, so the fix may be to delete the comma?"
2241 , D.toSimpleNote
2242 "I recommend using the following format for lists that span multiple lines:"
2243 , D.indent 4 $ D.vcat $
2244 [ "[ \"Alice\""
2245 , ", \"Bob\""
2246 , ", \"Chuck\""
2247 , "]"
2249 , D.reflow $
2250 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
2251 \ This style can be jarring for people coming from C-like syntax, but folks generally\
2252 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
2257toFuncReport :: Code.Source -> Context -> Func -> Row -> Col -> Report.Report
2258toFuncReport source context func startRow startCol =
2259 case func of
2260 FuncSpace space row col ->
2261 toSpaceReport source space row col
2263 FuncArg pattern row col ->
2264 error "TODO FuncArg" pattern row col
2266 FuncBody expr row col ->
2267 toExprReport source (InNode NFunc startRow startCol context) expr row col
2269 FuncArrow row col ->
2270 let
2271 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2272 region = toRegion row col
2273 in
2274 case Code.whatIsNext source row col of
2275 Code.Keyword keyword ->
2276 Report.Report "RESERVED WORD" region [] $
2277 Code.toSnippet source surroundings (Just region)
2279 D.reflow $
2280 "I was parsing an anonymous function, but I got stuck here:"
2282 D.reflow $
2283 "It looks like you are trying to use `" ++ keyword ++ "` as an argument, but\
2284 \ it is a reserved word in this language. Try using a different argument name!"
2287 _ ->
2288 Report.Report "UNFINISHED ANONYMOUS FUNCTION" region [] $
2289 Code.toSnippet source surroundings (Just region)
2291 D.reflow $
2292 "I just saw the beginning of an anonymous function, so I was expecting to see an arrow next:"
2294 D.fillSep $
2295 ["The","syntax","for","anonymous","functions","is"
2296 ,D.dullyellow "(\\x -> x + 1)"
2297 ,"so","I","am","missing","the","arrow","and","the","body","of","the","function."
2301 FuncIndentArg row col ->
2302 let
2303 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2304 region = toRegion row col
2305 in
2306 Report.Report "MISSING ARGUMENT" region [] $
2307 Code.toSnippet source surroundings (Just region)
2309 D.reflow $
2310 "I just saw the beginning of an anonymous function, so I was expecting to see an argument next:"
2312 D.stack
2313 [ D.fillSep
2314 ["Something","like",D.dullyellow"x","or",D.dullyellow "name" <> "."
2315 ,"Anything","that","starts","with","a","lower","case","letter!"
2317 , D.toSimpleNote $
2318 "The syntax for anonymous functions is (\\x -> x + 1) where the backslash\
2319 \ is meant to look a bit like a lambda if you squint. This visual pun seemed\
2320 \ like a better idea at the time!"
2324 FuncIndentArrow row col ->
2325 let
2326 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2327 region = toRegion row col
2328 in
2329 Report.Report "UNFINISHED ANONYMOUS FUNCTION" region [] $
2330 Code.toSnippet source surroundings (Just region)
2332 D.reflow $
2333 "I just saw the beginning of an anonymous function, so I was expecting to see an arrow next:"
2335 D.stack
2336 [ D.fillSep $
2337 ["The","syntax","for","anonymous","functions","is"
2338 ,D.dullyellow "(\\x -> x + 1)"
2339 ,"so","I","am","missing","the","arrow","and","the","body","of","the","function."
2341 , D.toSimpleNote $
2342 "It is possible that I am confused about indetation! I generally recommend\
2343 \ switching to named functions if the definition cannot fit inline nicely, so\
2344 \ either (1) try to fit the whole anonymous function on one line or (2) break\
2345 \ the whole thing out into a named function. Things tend to be clearer that way!"
2349 FuncIndentBody row col ->
2350 let
2351 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2352 region = toRegion row col
2353 in
2354 Report.Report "UNFINISHED ANONYMOUS FUNCTION" region [] $
2355 Code.toSnippet source surroundings (Just region)
2357 D.reflow $
2358 "I was expecting to see the body of your anonymous function next:"
2360 D.stack
2361 [ D.fillSep $
2362 ["The","syntax","for","anonymous","functions","is"
2363 ,D.dullyellow "(\\x -> x + 1)"
2364 ,"so","I","am","missing","all","the","stuff","after","the","arrow!"
2366 , D.toSimpleNote $
2367 "It is possible that I am confused about indetation! I generally recommend\
2368 \ switching to named functions if the definition cannot fit inline nicely, so\
2369 \ either (1) try to fit the whole anonymous function on one line or (2) break\
2370 \ the whole thing out into a named function. Things tend to be clearer that way!"
2378 case err of
2379 CommentOnNothing region ->
2380 Report.Report "STRAY COMMENT" region [] $
2381 Code.toSnippet source region Nothing
2383 "This documentation comment is not followed by anything."
2385 D.reflow $
2386 "All documentation comments need to be right above the declaration they\
2387 \ describe. Maybe some code got deleted or commented out by accident? Or\
2388 \ maybe this comment is here by accident?"
2391 UnexpectedPort region ->
2392 Report.Report "UNEXPECTED PORTS" region [] $
2393 Code.toSnippet source region Nothing
2395 D.reflow $
2396 "You are declaring ports in a normal module."
2398 D.stack
2399 [ D.fillSep
2400 ["Switch","this","to","say",D.green "port module","instead,"
2401 ,"marking","that","this","module","contains","port","declarations."
2403 , D.link "Note"
2404 "Ports are not a traditional FFI for calling JS functions directly. They need a different mindset! Read"
2405 "ports"
2406 "to learn the syntax and how to use it effectively."
2410 NoPorts region ->
2411 Report.Report "NO PORTS" region [] $
2412 Code.toSnippet source region Nothing
2414 D.reflow $
2415 "This module does not declare any ports, but it says it will:"
2417 D.fillSep
2418 ["Switch","this","to",D.green "module"
2419 ,"and","you","should","be","all","set!"
2423 ParseError row col context expectation ->
2424 let
2425 pos = A.Position row col
2426 region = A.Region pos pos
2427 in
2428 case expectation of
2430 DocComment ->
2431 Report.Report "EXPECTING DOC COMMENT" region [] $
2432 Code.toSnippet source region Nothing
2434 D.reflow $
2435 "I was expecting a doc comment here:"
2437 D.reflowLink
2438 "Check out" "TODO" "for examples of doc comments."
2441 -- Parse.Number
2443 Precedence ->
2444 Report.Report "EXPECTING PRECEDENCE" region [] $
2445 Code.toSnippet source region Nothing
2447 D.reflow $
2448 "I was expecting the precedence here:"
2450 D.reflow $
2451 "I need a single digit between 0 and 9 inclusive."
2454 Wildcard ->
2455 Report.Report "EXPECTING A WILDCARD" region [] $
2456 Code.toSnippet source region Nothing
2458 D.reflow $
2459 "I was expecting a _ here:"
2461 D.reflow $
2462 "An underscore indicates that “I do not care about this value” and is\
2463 \ called a wildcard pattern because it will match with any type of values."
2466 WildcardNotVar startCol endCol ->
2467 let
2468 badRegion =
2469 A.Region (A.Position row startCol) (A.Position row endCol)
2470 in
2471 Report.Report "INVALID PATTERN" badRegion [] $
2472 Code.toSnippet source badRegion Nothing
2474 D.reflow $
2475 "I was expecting to see an underscore without any additional characters:"
2477 D.reflow $
2478 "There are two options. Either (1) remove the extra characters and ignore the\
2479 \ value or (2) remove the starting underscore to give the value a normal name."
2482 -- Parse.Pattern
2484 FloatInPattern ->
2485 Report.Report "INVALID PATTERN" region [] $
2486 Code.toSnippet source region Nothing
2488 D.reflow $
2489 "I cannot pattern match with floating point numbers:"
2491 D.reflow $
2492 "Equality on floats can be unreliable, so you usually want to check that they\
2493 \ are nearby with some sort of (abs (actual - expected) < 0.001) check."
2496 -- Parse.Expression
2498 MatchingName name ->
2499 Report.Report "EXPECTING A DEFINITION" region [] $
2500 Code.toSnippet source region Nothing
2502 D.reflow $
2503 "I just saw the type annotation for `" ++ Name.toChars name
2504 ++ "` so I was expecting to see its definition here:"
2506 D.reflow $
2507 "Type annotations always appear directly above the relevant\
2508 \ definition, without anything else (even doc comments) in between."
2514 TypeWithBadDefinition region annName defName ->
2515 Report.Report "ANNOTATION MISMATCH" region [] $
2516 Code.toSnippet source region Nothing
2518 D.reflow $
2519 "I see a `" <> Name.toChars annName
2520 <> "` annotation, but it is followed by a `"
2521 <> Name.toChars defName <> "` definition."
2523 D.fillSep
2524 ["The","annotation","and","definition","names","must","match!"
2525 ,"Is","there","a","typo","between"
2526 , D.dullyellow (D.fromName annName)
2527 ,"and"
2528 , D.dullyellow (D.fromName defName) <> "?"