on 2bc07b6 help sign in
1784 lines 54 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 , Operator(..)
43 , toReport
44 )
45 where
48import Prelude hiding (Char, String)
49import qualified Data.Char as Char
50import qualified Data.Name as Name
51import Data.Word (Word16)
52import Numeric (showHex)
54import qualified Elm.ModuleName as ModuleName
55import Parse.Primitives (Row, Col)
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 | ImportIndentAs Row Col
109 | ImportIndentAlias Row Col
110 | ImportIndentExposing Row Col
111 | ImportIndentExposingList Row Col
112 --
113 | Infix Row Col
114 --
115 | Declarations Decl Row Col
118data Exposing
119 = ExposingSpace Space Row Col
120 | ExposingStart Row Col
121 | ExposingValue Row Col
122 | ExposingOperator Row Col
123 | ExposingOperatorReserved Operator Row Col
124 | ExposingOperatorRightParen Row Col
125 | ExposingEnd Row Col
126 --
127 | ExposingTypePrivacy Row Col
128 | ExposingTypePrivacyDots Row Col
129 | ExposingTypePrivacyEnd Row Col
130 --
131 | ExposingIndentEnd Row Col
132 | ExposingIndentValue Row Col
133 | ExposingIndentValueEnd Row Col
134 | ExposingIndentTypePrivacy Row Col
135 | ExposingIndentTypePrivacyDots Row Col
136 | ExposingIndentTypePrivacyEnd Row Col
140-- DECLARATIONS
143data Decl
144 = DeclStart Row Col
145 | DeclSpace Space Row Col
146 --
147 | Port Port Row Col
148 | DeclType DeclType Row Col
149 | DeclDef Name.Name DeclDef Row Col
150 --
151 | DeclFreshLineStart Row Col
152 | DeclFreshLineAfterDocComment Row Col
155data DeclDef
156 = DeclDefSpace Space Row Col
157 | DeclDefEquals Row Col
158 | DeclDefType Type Row Col
159 | DeclDefArg Pattern Row Col
160 | DeclDefBody Expr Row Col
161 | DeclDefNameRepeat Row Col
162 | DeclDefNameMatch Name.Name Row Col
163 --
164 | DeclDefIndentType Row Col
165 | DeclDefIndentEquals Row Col
166 | DeclDefIndentBody Row Col
167 --
168 | DeclDefFreshLineAfterType Row Col
171data Port
172 = PortSpace Space Row Col
173 | PortName Row Col
174 | PortColon Row Col
175 | PortType Type Row Col
176 | PortIndentName Row Col
177 | PortIndentColon Row Col
178 | PortIndentType Row Col
182-- TYPE DECLARATIONS
185data DeclType
186 = DT_Space Space Row Col
187 | DT_Name Row Col
188 | DT_Alias TypeAlias Row Col
189 | DT_Union CustomType Row Col
190 --
191 | DT_IndentName Row Col
194data TypeAlias
195 = AliasSpace Space Row Col
196 | AliasName Row Col
197 | AliasEquals Row Col
198 | AliasBody Type Row Col
199 --
200 | AliasIndentEquals Row Col
201 | AliasIndentBody Row Col
204data CustomType
205 = CT_Space Space Row Col
206 | CT_Name Row Col
207 | CT_Equals Row Col
208 | CT_Bar Row Col
209 | CT_Variant Row Col
210 | CT_VariantArg Type Row Col
211 --
212 | CT_IndentEquals Row Col
213 | CT_IndentBar Row Col
214 | CT_IndentAfterBar Row Col
215 | CT_IndentAfterEquals Row Col
219-- EXPRESSIONS
222data Expr
223 = Let Let Row Col
224 | Case Case Row Col
225 | If If Row Col
226 | List List Row Col
227 | Record Record Row Col
228 | Update Expr Row Col
229 | Tuple Tuple Row Col
230 | Func Func Row Col
231 --
232 | Dot Row Col
233 | Access Row Col
234 | OperatorRight Name.Name Row Col
235 | OperatorReserved Operator Row Col
236 --
237 | Start Row Col
238 | Char Char Row Col
239 | String String Row Col
240 | Number Number Row Col
241 | Space Space Row Col
242 | EndlessShader Row Col
243 | ShaderProblem [Char.Char] Row Col
244 | IndentOperatorRight Name.Name Row Col
245 | IndentMoreExpr Row Col
248data Record
249 = RecordOpen Row Col
250 | RecordEnd Row Col
251 | RecordField Row Col
252 | RecordEquals Row Col
253 | RecordExpr Expr Row Col
254 | RecordSpace Space Row Col
255 --
256 | RecordIndentOpen Row Col
257 | RecordIndentEnd Row Col
258 | RecordIndentField Row Col
259 | RecordIndentEquals Row Col
260 | RecordIndentExpr Row Col
263data Tuple
264 = TupleOpen Row Col
265 | TupleExpr Expr Row Col
266 | TupleSpace Space Row Col
267 | TupleEnd Row Col
268 | TupleOperatorClose Row Col
269 | TupleOperatorReserved Operator Row Col
270 --
271 | TupleIndentExpr Row Col
272 | TupleIndentEnd Row Col
275data List
276 = ListSpace Space Row Col
277 | ListOpen Row Col
278 | ListExpr Expr Row Col
279 | ListEnd Row Col
280 --
281 | ListIndentOpen Row Col
282 | ListIndentEnd Row Col
283 | ListIndentExpr Row Col
286data Func
287 = FuncSpace Space Row Col
288 | FuncArg Pattern Row Col
289 | FuncBody Expr Row Col
290 | FuncArrow Row Col
291 --
292 | FuncIndentArg Row Col
293 | FuncIndentArrow Row Col
294 | FuncIndentBody Row Col
297data Case
298 = CaseSpace Space Row Col
299 | CaseOf Row Col
300 | CasePattern Pattern Row Col
301 | CaseArrow Row Col
302 | CaseExpr Expr Row Col
303 | CaseBranch Expr Row Col
304 --
305 | CaseIndentOf Row Col
306 | CaseIndentExpr Row Col
307 | CaseIndentPattern Row Col
308 | CaseIndentArrow Row Col
309 | CaseIndentBranch Row Col
310 | CasePatternAlignment Word16 Row Col
313data If
314 = IfSpace Space Row Col
315 | IfThen Row Col
316 | IfElse Row Col
317 | IfElseBranchStart Row Col
318 --
319 | IfCondition Expr Row Col
320 | IfThenBranch Expr Row Col
321 | IfElseBranch Expr Row Col
322 --
323 | IfIndentCondition Row Col
324 | IfIndentThen Row Col
325 | IfIndentThenBranch Row Col
326 | IfIndentElseBranch Row Col
327 | IfIndentElse Row Col
330data Let
331 = LetSpace Space Row Col
332 | LetIn Row Col
333 | LetDefAlignment Word16 Row Col
334 | LetDefName Row Col
335 | LetDef Name.Name Def Row Col
336 | LetDestruct Destruct Row Col
337 | LetBody Expr Row Col
338 | LetIndentDef Row Col
339 | LetIndentIn Row Col
340 | LetIndentBody Row Col
343data Def
344 = DefSpace Space Row Col
345 | DefType Type Row Col
346 | DefNameRepeat Name.Name Row Col
347 | DefNameMatch Name.Name Name.Name Row Col
348 | DefArg Pattern Row Col
349 | DefEquals Row Col
350 | DefBody Expr Row Col
351 | DefIndentEquals Row Col
352 | DefIndentType Row Col
353 | DefIndentBody Row Col
354 | DefAlignment Word16 Row Col
357data Destruct
358 = DestructSpace Space Row Col
359 | DestructPattern Pattern Row Col
360 | DestructEquals Row Col
361 | DestructBody Expr Row Col
362 | DestructIndentEquals Row Col
363 | DestructIndentBody Row Col
367-- PATTERNS
370data Pattern
371 = PRecord PRecord Row Col
372 | PTuple PTuple Row Col
373 | PList PList Row Col
374 --
375 | PStart Row Col
376 | PChar Char Row Col
377 | PString String Row Col
378 | PNumber Number Row Col
379 | PFloat Int Row Col
380 | PAlias Row Col
381 | PWildcardNotVar Int Row Col
382 | PSpace Space Row Col
383 --
384 | PIndentStart Row Col
385 | PIndentAlias Row Col
388data PRecord
389 = PRecordOpen Row Col
390 | PRecordEnd Row Col
391 | PRecordField Row Col
392 | PRecordSpace Space Row Col
393 --
394 | PRecordIndentOpen Row Col
395 | PRecordIndentEnd Row Col
396 | PRecordIndentField Row Col
399data PTuple
400 = PTupleOpen Row Col
401 | PTupleEnd Row Col
402 | PTupleExpr Pattern Row Col
403 | PTupleSpace Space Row Col
404 --
405 | PTupleIndentOpen Row Col
406 | PTupleIndentEnd Row Col
407 | PTupleIndentExpr Row Col
410data PList
411 = PListOpen Row Col
412 | PListEnd Row Col
413 | PListExpr Pattern Row Col
414 | PListSpace Space Row Col
415 --
416 | PListIndentOpen Row Col
417 | PListIndentEnd Row Col
418 | PListIndentExpr Row Col
422-- TYPES
425data Type
426 = TRecord TRecord Row Col
427 | TTuple TTuple Row Col
428 | TVariant Row Col
429 | TArrow Row Col
430 --
431 | TStart Row Col
432 | TSpace Space Row Col
433 --
434 | TIndentStart Row Col
437data TRecord
438 = TRecordOpen Row Col
439 | TRecordEnd Row Col
440 --
441 | TRecordField Row Col
442 | TRecordColon Row Col
443 | TRecordType Type Row Col
444 --
445 | TRecordSpace Space Row Col
446 --
447 | TRecordIndentOpen Row Col
448 | TRecordIndentField Row Col
449 | TRecordIndentColon Row Col
450 | TRecordIndentType Row Col
451 | TRecordIndentEnd Row Col
454data TTuple
455 = TTupleOpen Row Col
456 | TTupleEnd Row Col
457 | TTupleType Type Row Col
458 | TTupleSpace Space Row Col
459 --
460 | TTupleIndentOpen Row Col
461 | TTupleIndentType Row Col
462 | TTupleIndentEnd Row Col
466-- LITERALS
469data Char
470 = CharEndless
471 | CharEscape Escape
472 | CharNotString Word16
475data String
476 = StringEndless_Single
477 | StringEndless_Multi
478 | StringEscape Escape
481data Escape
482 = EscapeUnknown
483 | BadUnicodeFormat Word16
484 | BadUnicodeCode Word16
485 | BadUnicodeLength Word16 Int Int
488data Number
489 = NumberEnd
490 | NumberDot Int
491 | NumberHexDigit
492 | NumberNoLeadingZero
496-- MISC
499data Space
500 = HasTab
501 | EndlessMultiComment
504data Operator
505 = OpDot
506 | OpPipe
507 | OpArrow
508 | OpEquals
509 | OpHasType
513-- TO REPORT
516toReport :: Code.Source -> Error -> Report.Report
517toReport source err =
518 case err of
519 ModuleNameUnspecified name ->
520 let
521 region = toRegion 1 1
522 in
523 Report.Report "MODULE NAME MISSING" region [] $
524 D.stack
525 [ D.reflow $
526 "I need the module name to be declared at the top of this file, like this:"
527 , D.indent 4 $ D.green $ D.fromChars $
528 "module " ++ ModuleName.toChars name ++ " exposing (..)"
529 , D.reflow $
530 "Try adding that as the first line of your file!"
531 , D.toSimpleNote $
532 "It is best to replace (..) with an explicit list of types and\
533 \ functions you want to expose. When you know a value is only used\
534 \ within this module, you can refactor without worrying about uses\
535 \ elsewhere. Limiting exposed values can also speed up compilation\
536 \ because I can skip a bunch of work if I see that the exposed API\
537 \ has not changed."
538 ]
540 ModuleNameMismatch expectedName (A.At region actualName) ->
541 Report.Report "MODULE NAME MISMATCH" region [ModuleName.toChars expectedName] $
542 Report.toCodeSnippet source region Nothing
543 (
544 "It looks like this module name is out of sync:"
545 ,
546 D.stack
547 [ D.reflow $
548 "I need it to match the file path, so I was expecting it to see `"
549 ++ ModuleName.toChars expectedName
550 ++ "` here. Make the following change, and you should be all set!"
551 , D.indent 4 $
552 D.dullyellow (D.fromName actualName) <> " -> " <> D.green (D.fromName expectedName)
553 , D.toSimpleNote $
554 "I require that module names correspond to file paths. This makes it much\
555 \ easier to explore unfamiliar codebases! So if you want to keep the current\
556 \ module name, try renaming the file instead."
557 ]
558 )
560 UnexpectedPort region ->
561 error "TODO UnexpectedPort" region
563 NoPorts region ->
564 error "TODO NoPorts" region
566 ParseError modul ->
567 toParseErrorReport source modul
570toParseErrorReport :: Code.Source -> Module -> Report.Report
571toParseErrorReport source modul =
572 case modul of
573 ModuleSpace space row col ->
574 toSpaceReport source space row col
576 ModuleEndOfFile row col ->
577 let
578 region = toRegion row col
579 in
580 Report.Report "EXPECTING END OF FILE" region [] $
581 Report.toCodeSnippet source region Nothing
582 (
583 D.reflow $
584 "I was not expecting to see anything more here:"
585 ,
586 D.reflow $
587 "I think I have read all the declarations in the file and that there is nothing\
588 \ left to see, so whatever I am running into is confusing me a lot!"
589 )
591 Module row col ->
592 error "TODO Module" row col
594 ModuleName row col ->
595 error "TODO ModuleName" row col
597 ModuleExposing row col ->
598 error "TODO ModuleExposing" row col
600 ModuleExposingList exposing row col ->
601 error "TODO ModuleExposingList" exposing row col
603 --
604 ModulePortModule row col ->
605 error "TODO ModulePortModule" row col
607 ModuleEffect row col ->
608 error "TODO ModuleEffect" row col
610 ModuleIndentStart row col ->
611 error "TODO ModuleIndentStart" row col
613 ModuleIndentName row col ->
614 error "TODO ModuleIndentName" row col
616 ModuleIndentExposing row col ->
617 error "TODO ModuleIndentExposing" row col
619 ModuleIndentExposingList row col ->
620 error "TODO ModuleIndentExposingList" row col
622 ModuleIndentPortModule row col ->
623 error "TODO ModuleIndentPortModule" row col
625 FreshLineModuleStart row col ->
626 error "TODO FreshLineModuleStart" row col
628 FreshLineAfterModuleLine row col ->
629 error "TODO FreshLineAfterModuleLine" row col
631 FreshLineAfterDocComment row col ->
632 error "TODO FreshLineAfterDocComment" row col
634 ImportStart row col ->
635 error "TODO ImportStart" row col
637 ImportName row col ->
638 error "TODO ImportName" row col
640 ImportAs row col ->
641 error "TODO ImportAs" row col
643 ImportAlias row col ->
644 error "TODO ImportAlias" row col
646 ImportExposing row col ->
647 error "TODO ImportExposing" row col
649 ImportExposingList exposing row col ->
650 error "TODO ImportExposingList" exposing row col
652 ImportEnd row col ->
653 error "TODO ImportEnd" row col
655 ImportIndentName row col ->
656 error "TODO ImportIndentName" row col
658 ImportIndentAs row col ->
659 error "TODO ImportIndentAs" row col
661 ImportIndentAlias row col ->
662 error "TODO ImportIndentAlias" row col
664 ImportIndentExposing row col ->
665 error "TODO ImportIndentExposing" row col
667 ImportIndentExposingList row col ->
668 error "TODO ImportIndentExposingList" row col
670 Infix row col ->
671 error "TODO Infix" row col
673 Declarations decl _ _ ->
674 toDeclarationsReport source decl
677toSpaceReport :: Code.Source -> Space -> Row -> Col -> Report.Report
678toSpaceReport source space row col =
679 case space of
680 HasTab ->
681 let
682 region = toRegion row col
683 in
684 Report.Report "NO TABS" region [] $
685 Report.toCodeSnippet source region Nothing
686 (
687 D.reflow $
688 "I ran into a tab, but tabs are not allowed in Elm files."
689 ,
690 D.reflow $
691 "Replace the tab with spaces."
692 )
694 EndlessMultiComment ->
695 let
696 region = toWiderRegion row col 2
697 in
698 Report.Report "ENDLESS COMMENT" region [] $
699 Report.toCodeSnippet source region Nothing
700 (
701 D.reflow $
702 "I cannot find the end of this multi-line comment:"
703 ,
704 D.stack -- "{-"
705 [ D.reflow "Add a -} somewhere after this to end the comment."
706 , D.toSimpleHint
707 "Multi-line comments can be nested in Elm, so {- {- -} -} is a comment\
708 \ that happens to contain another comment. Like parentheses and curly braces,\
709 \ the start and end markers must always be balanced. Maybe that is the problem?"
710 ]
711 )
714toRegion :: Row -> Col -> A.Region
715toRegion row col =
716 let
717 pos = A.Position row col
718 in
719 A.Region pos pos
722toWiderRegion :: Row -> Col -> Word16 -> A.Region
723toWiderRegion row col extra =
724 A.Region
725 (A.Position row col)
726 (A.Position row (col + extra))
729toDeclarationsReport :: Code.Source -> Decl -> Report.Report
730toDeclarationsReport source decl =
731 case decl of
732 DeclStart row col ->
733 error "TODO DeclStart" row col
735 DeclSpace space row col ->
736 toSpaceReport source space row col
738 Port port row col ->
739 error "TODO Port" port row col
741 DeclType declType row col ->
742 error "TODO DeclType" declType row col
744 DeclDef name declDef row col ->
745 toDeclDefReport source name declDef row col
747 DeclFreshLineStart row col ->
748 error "TODO DeclFreshLineStart" row col
750 DeclFreshLineAfterDocComment row col ->
751 error "TODO DeclFreshLineAfterDocComment" row col
754toDeclDefReport :: Code.Source -> Name.Name -> DeclDef -> Row -> Col -> Report.Report
755toDeclDefReport source name declDef _ _ =
756 case declDef of
757 DeclDefSpace space row col ->
758 toSpaceReport source space row col
760 DeclDefEquals row col ->
761 error "TODO DeclDefEquals" row col
763 DeclDefType tipe row col ->
764 error "TODO DeclDefType" tipe row col
766 DeclDefArg pattern row col ->
767 error "TODO DeclDefArg" pattern row col
769 DeclDefBody expr row col ->
770 toExprReport source name expr row col
772 DeclDefNameRepeat row col ->
773 error "TODO DeclDefNameRepeat" name row col
775 DeclDefNameMatch defName row col ->
776 error "TODO DeclDefNameMatch" name defName row col
778 DeclDefIndentType row col ->
779 error "TODO DeclDefIndentType" row col
781 DeclDefIndentEquals row col ->
782 error "TODO DeclDefIndentEquals" row col
784 DeclDefIndentBody row col ->
785 error "TODO DeclDefIndentBody" row col
787 DeclDefFreshLineAfterType row col ->
788 error "TODO DeclDefFreshLineAfterType" row col
792toExprReport :: Code.Source -> Name.Name -> Expr -> Row -> Col -> Report.Report
793toExprReport source name expr _ _ =
794 case expr of
795 Let _ _ _ ->
796 error "TODO Let"
798 Case _ _ _ ->
799 error "TODO Case"
801 If _ _ _ ->
802 error "TODO If"
804 List list row col ->
805 toListReport source name list row col
807 Record _ _ _ ->
808 error "TODO Record"
810 Update _ _ _ ->
811 error "TODO Update"
813 Tuple _ _ _ ->
814 error "TODO Tuple"
816 Func func row col ->
817 toFuncReport source name func row col
819 Dot row col ->
820 let region = toRegion row col in
821 Report.Report "EXPECTING RECORD ACCESSOR" region [] $
822 Report.toCodeSnippet source region Nothing
823 (
824 D.reflow $
825 "I was expecting to see a record accessor here:"
826 ,
827 D.fillSep
828 ["Something","like",D.dullyellow".name","or",D.dullyellow".price"
829 ,"that","accesses","a","value","from","a","record."
830 ]
831 )
833 Access row col ->
834 let region = toRegion row col in
835 Report.Report "EXPECTING RECORD ACCESSOR" region [] $
836 Report.toCodeSnippet source region Nothing
837 (
838 D.reflow $
839 "I am trying to parse a record accessor here:"
840 ,
841 D.stack
842 [
843 D.fillSep
844 ["Something","like",D.dullyellow".name","or",D.dullyellow".price"
845 ,"that","accesses","a","value","from","a","record."
846 ]
847 ,
848 D.toSimpleNote $
849 "Record field names must start with a lower case letter!"
850 ]
851 )
853 OperatorRight op row col ->
854 let region = toRegion row col in
855 Report.Report "MISSING EXPRESSION" region [] $
856 Report.toCodeSnippet source region Nothing
857 (
858 D.reflow $
859 "I need to see an expression after this " ++ Name.toChars op ++ " operator:"
860 ,
861 D.fillSep $
862 ["You","can","just","put","anything","for","now,","like"
863 ,D.dullyellow "42","or",D.dullyellow"\"hello\"" <> "."
864 ,"Once","there","is","something","there,","I","can","give","more"
865 ,"specific","hints","about","what","type","of","value","is","needed!"
866 ]
867 )
869 OperatorReserved operator row col ->
870 toOperatorReport source name operator row col
872 Start _ _ ->
873 error "TODO Start"
875 Char char row col ->
876 toCharReport source char row col
878 String string row col ->
879 toStringReport source string row col
881 Number number row col ->
882 toNumberReport source number row col
884 Space space row col ->
885 toSpaceReport source space row col
887 EndlessShader row col ->
888 let
889 region = toWiderRegion row col 6
890 in
891 Report.Report "ENDLESS SHADER" region [] $
892 Report.toCodeSnippet source region Nothing
893 (
894 D.reflow "I cannot find the end of this shader:"
895 ,
896 D.reflow "Add a |] somewhere after this to end the shader."
897 )
899 ShaderProblem problem row col ->
900 let
901 region = toRegion row col
902 in
903 Report.Report "SHADER PROBLEM" region [] $
904 Report.toCodeSnippet source region Nothing
905 (
906 D.reflow $
907 "I ran into a problem while parsing this GLSL block."
908 ,
909 D.stack
910 [ D.reflow $
911 "I use a 3rd party GLSL parser for now, and I did my best to extract their error message:"
912 , D.indent 4 $ D.vcat $
913 map D.fromChars (filter (/="") (lines problem))
914 ]
915 )
917 IndentOperatorRight op row col ->
918 let region = toRegion row col in
919 Report.Report "MISSING EXPRESSION" region [] $
920 Report.toCodeSnippet source region Nothing
921 (
922 D.reflow $
923 "I need to see an expression after this " ++ Name.toChars op ++ " operator:"
924 ,
925 D.stack
926 [
927 D.fillSep $
928 ["You","can","just","put","anything","for","now,","like"
929 ,D.dullyellow "42","or",D.dullyellow"\"hello\"" <> "."
930 ,"Once","there","is","something","there,","I","can","give","more"
931 ,"specific","hints","about","what","type","of","value","is","needed!"
932 ]
933 ,
934 D.toSimpleNote $
935 "I may be getting confused by your indentation? The easiest way to make sure\
936 \ this is not an indentation problem is to put the expression on the right of\
937 \ the " ++ Name.toChars op ++ " operator on the same line."
938 ]
939 )
941 IndentMoreExpr _ _ ->
942 error "TODO IndentMoreExpr"
945toCharReport :: Code.Source -> Char -> Row -> Col -> Report.Report
946toCharReport source char row col =
947 case char of
948 CharEndless ->
949 let
950 region = toRegion row col
951 in
952 Report.Report "MISSING SINGLE QUOTE" region [] $
953 Report.toCodeSnippet source region Nothing
954 (
955 D.reflow $
956 "I thought I was parsing a character, but I got to the end of\
957 \ the line without seeing the closing single quote:"
958 ,
959 D.reflow $
960 "Add a closing single quote here!"
961 )
963 CharEscape escape ->
964 toEscapeReport source escape row col
966 CharNotString width ->
967 let
968 region = toWiderRegion row col width
969 in
970 Report.Report "NEEDS DOUBLE QUOTES" region [] $
971 Report.toCodeSnippet source region Nothing
972 (
973 "The following string uses single quotes:"
974 ,
975 D.stack
976 [ "Please switch to double quotes instead:"
977 , D.indent 4 $
978 D.dullyellow "'this'" <> " => " <> D.green "\"this\""
979 , D.toSimpleNote $
980 "Elm uses double quotes for strings like \"hello\", whereas it uses single\
981 \ quotes for individual characters like 'a' and 'ø'. This distinction helps with\
982 \ code like (String.any (\\c -> c == 'X') \"90210\") where you are inspecting\
983 \ individual characters."
984 ]
985 )
988toStringReport :: Code.Source -> String -> Row -> Col -> Report.Report
989toStringReport source string row col =
990 case string of
991 StringEndless_Single ->
992 let
993 region = toRegion row col
994 in
995 Report.Report "ENDLESS STRING" region [] $
996 Report.toCodeSnippet source region Nothing
997 (
998 D.reflow $
999 "I got to the end of the line without seeing the closing double quote:"
1001 D.stack
1002 [ D.fillSep $
1003 ["Strings","look","like",D.green "\"this\"","with","double"
1004 ,"quotes","on","each","end.","Is","the","closing","double"
1005 ,"quote","missing","in","your","code?"
1007 , D.link "Note" "Read" "TODO" "if you want a string that spans multiple lines."
1011 StringEndless_Multi ->
1012 let
1013 region = toWiderRegion row col 3
1014 in
1015 Report.Report "ENDLESS STRING" region [] $
1016 Report.toCodeSnippet source region Nothing
1018 D.reflow $
1019 "I cannot find the end of this multi-line string:"
1021 D.stack
1022 [ D.reflow "Add a \"\"\" somewhere after this to end the string."
1023 , D.link "Hint" "Read" "TODO" "for more information on strings and multi-line strings."
1027 StringEscape escape ->
1028 toEscapeReport source escape row col
1031toEscapeReport :: Code.Source -> Escape -> Row -> Col -> Report.Report
1032toEscapeReport source escape row col =
1033 case escape of
1034 EscapeUnknown ->
1035 let
1036 region = toWiderRegion row col 2
1037 in
1038 Report.Report "UNKNOWN ESCAPE" region [] $
1039 Report.toCodeSnippet source region Nothing
1041 D.reflow $
1042 "Backslashes always start escaped characters, but I do not recognize this one:"
1044 D.stack
1045 [ D.reflow $
1046 "Valid escape characters include:"
1047 , D.dullyellow $ D.indent 4 $ D.vcat $
1048 [ "\\n"
1049 , "\\r"
1050 , "\\t"
1051 , "\\\""
1052 , "\\\'"
1053 , "\\\\"
1054 , "\\u{003D}"
1056 , D.reflow $
1057 "Do you want one of those instead? Maybe you need \\\\ to escape a backslash?"
1058 , D.toSimpleNote $
1059 "The last style lets encode ANY character by its Unicode code\
1060 \ point. That means \\u{0009} and \\t are the same. You can use\
1061 \ that style for anything not covered by the other six escapes!"
1065 BadUnicodeFormat width ->
1066 let
1067 region = toWiderRegion row col width
1068 in
1069 Report.Report "BAD UNICODE ESCAPE" region [] $
1070 Report.toCodeSnippet source region Nothing
1072 D.reflow $
1073 "I ran into an invalid Unicode escape:"
1075 D.stack
1076 [ D.reflow $
1077 "Here are some examples of valid Unicode escapes:"
1078 , D.dullyellow $ D.indent 4 $ D.vcat $
1079 [ "\\u{0041}"
1080 , "\\u{03BB}"
1081 , "\\u{6728}"
1082 , "\\u{1F60A}"
1084 , D.reflow $
1085 "Notice that the code point is always surrounded by curly braces.\
1086 \ Maybe you are missing the opening or closing curly brace?"
1089 BadUnicodeCode width ->
1090 let
1091 region = toWiderRegion row col width
1092 in
1093 Report.Report "BAD UNICODE ESCAPE" region [] $
1094 Report.toCodeSnippet source region Nothing
1096 D.reflow $
1097 "This is not a valid code point:"
1099 D.reflow $
1100 "The valid code points are between 0 and 10FFFF inclusive."
1103 BadUnicodeLength width numDigits badCode ->
1104 let
1105 region = toWiderRegion row col width
1106 in
1107 Report.Report "BAD UNICODE ESCAPE" region [] $
1108 Report.toCodeSnippet source region Nothing $
1109 if numDigits < 4 then
1111 D.reflow $
1112 "Every code point needs at least four digits:"
1114 let
1115 goodCode = replicate (4 - numDigits) '0' ++ map Char.toUpper (showHex badCode "")
1116 suggestion = "\\u{" <> D.fromChars goodCode <> "}"
1117 in
1118 D.fillSep ["Try",D.green suggestion,"instead?"]
1121 else
1123 D.reflow $
1124 "This code point has too many digits:"
1126 D.fillSep $
1127 ["Valid","code","points","are","between"
1128 ,D.green "\\u{0000}","and",D.green "\\u{10FFFF}" <> ","
1129 ,"so","try","trimming","any","leading","zeros","until"
1130 ,"you","have","between","four","and","six","digits."
1135toNumberReport :: Code.Source -> Number -> Row -> Col -> Report.Report
1136toNumberReport source number row col =
1137 let
1138 region = toRegion row col
1139 in
1140 case number of
1141 NumberEnd ->
1142 Report.Report "WEIRD NUMBER" region [] $
1143 Report.toCodeSnippet source region Nothing
1145 D.reflow $
1146 "I thought I was reading a number, but I ran into some weird stuff here:"
1148 D.stack
1149 [ D.reflow $
1150 "I recognize numbers in the following formats:"
1151 , D.indent 4 $ D.vcat [ "42", "3.14", "6.022e23", "0x002B" ]
1152 , D.reflow $
1153 "So is there a way to write it like one of those?"
1157 NumberDot int ->
1158 Report.Report "WEIRD NUMBER" region [] $
1159 Report.toCodeSnippet source region Nothing
1161 D.reflow $
1162 "Numbers cannot end with a dot like this:"
1164 D.fillSep
1165 ["Switching","to",D.green (D.fromChars (show int))
1166 ,"or",D.green (D.fromChars (show int ++ ".0"))
1167 ,"will","work","though!"
1171 NumberHexDigit ->
1172 Report.Report "WEIRD HEXIDECIMAL" region [] $
1173 Report.toCodeSnippet source region Nothing
1175 D.reflow $
1176 "I thought I was reading a hexidecimal number until I got here:"
1178 D.stack
1179 [ D.reflow $
1180 "Valid hexidecimal digits include 0123456789abcdefABCDEF, so I can\
1181 \ only recognize things like this:"
1182 , D.indent 4 $ D.vcat [ "0x2B", "0x002B", "0x00ffb3" ]
1186 NumberNoLeadingZero ->
1187 Report.Report "LEADING ZEROS" region [] $
1188 Report.toCodeSnippet source region Nothing
1190 D.reflow $
1191 "I do not accept numbers with leading zeros:"
1193 D.stack
1194 [ D.reflow $
1195 "Just delete the leading zeros and it should work!"
1196 , D.toSimpleNote $
1197 "Some languages let you to specify octal numbers by adding a leading zero.\
1198 \ So in C, writing 0111 is the same as writing 73. Some people are used to\
1199 \ that, but others probably want it to equal 111. Either path is going to\
1200 \ surprise people from certain backgrounds, so Elm tries to avoid this whole\
1201 \ situation."
1206toOperatorReport :: Code.Source -> Name.Name -> Operator -> Row -> Col -> Report.Report
1207toOperatorReport source name operator row col =
1208 case operator of
1209 OpDot ->
1210 let
1211 region = toRegion row col
1212 in
1213 Report.Report "UNEXPECTED SYMBOL" region [] $
1214 Report.toCodeSnippet source region Nothing
1216 "I was not expecting this dot:"
1218 D.reflow $
1219 "Dots are for record access and decimal points, so\
1220 \ they cannot float around on their own. Maybe\
1221 \ there is some extra whitespace?"
1224 OpPipe ->
1225 let
1226 region = toRegion row col
1227 in
1228 Report.Report "UNEXPECTED SYMBOL" region [] $
1229 Report.toCodeSnippet source region Nothing
1231 D.reflow $
1232 "I was not expecting this vertical bar:"
1234 D.reflow $
1235 "Vertical bars should only appear in custom type declarations. Maybe you want || instead?"
1238 OpArrow ->
1239 let
1240 region = toWiderRegion row col 2
1241 in
1242 Report.Report "UNEXPECTED ARROW" region [] $
1243 Report.toCodeSnippet source region Nothing $
1244 if error "TODO inCase" then
1246 D.reflow $
1247 "I was not expecting to see an arrow here:"
1249 D.stack
1251 D.reflow $
1252 "I think I am parsing a `case` expression right now, so it makes sense to\
1253 \ see arrows around here. This one is confusing me though!"
1255 D.toSimpleHint $
1256 "I may be getting confused by the indentation. Every pattern in a `case` must be\
1257 \ exactly aligned (with exactly the same amount of indentation) so maybe this arrow\
1258 \ appears after the next `case` pattern (correctly!) but the pattern itself is\
1259 \ indented too far?"
1263 else
1265 D.reflow $
1266 "I was not expecting an arrow here:"
1268 D.reflow $
1269 "Arrows should only appear in `case` expressions and anonymous functions. Maybe\
1270 \ you want > or >= instead?"
1273 OpEquals ->
1274 let
1275 region = toRegion row col
1276 in
1277 Report.Report "UNEXPECTED EQUALS" region [] $
1278 Report.toCodeSnippet source region Nothing
1280 D.reflow $
1281 "I was not expecting to see this equals sign:"
1283 D.stack
1285 D.reflow "Maybe you want == instead? To check if two values are equal?"
1287 D.toSimpleNote $
1288 if error "TODO is within record?" then
1289 "Records look like { x = 3, y = 4 } with the equals sign right\
1290 \ after the field name. So maybe you forgot a comma?"
1291 else
1292 "I may be getting confused by your indentation. Is this supposed to be part of\
1293 \ a definition AFTER the `" ++ Name.toChars name ++ "` definition? If so,\
1294 \ the problem may be a bit before the equals sign. I need all definitions to\
1295 \ be exactly aligned (with exactly the same indentation) so the problem may be that\
1296 \ this new definition is indented a bit too much."
1300 OpHasType ->
1301 let
1302 region = toRegion row col
1303 in
1304 Report.Report "UNEXPECTED SYMBOL" region [] $
1305 Report.toCodeSnippet source region Nothing $
1307 D.reflow $
1308 "I was not expecting to run into the \"has type\" symbol here:"
1310 D.stack
1312 D.fillSep
1313 ["Maybe","you","want",D.green "::","instead?"
1314 ,"To","put","something","on","the","front","of","a","list?"
1316 , D.toSimpleNote $
1317 "The single colon is reserved for type annotations and record types, but I think\
1318 \ I am parsing the definition of `" ++ Name.toChars name ++ "` right now."
1320 D.toSimpleNote $
1321 "I may be getting confused by your indentation. Is this supposed to be part of\
1322 \ a type annotation AFTER the `" ++ Name.toChars name ++ "` definition? If so,\
1323 \ the problem may be a bit before the \"has type\" symbol. I need all definitions to\
1324 \ be exactly aligned (with exactly the same indentation) so the problem may be that\
1325 \ this new definition is indented a bit too much."
1330toListReport :: Code.Source -> Name.Name -> List -> Row -> Col -> Report.Report
1331toListReport source name func startRow startCol =
1332 case func of
1333 ListSpace space row col ->
1334 toSpaceReport source space row col
1336 ListOpen row col ->
1337 error "TODO ListOpen" row col
1339 ListExpr expr row col ->
1340 toExprReport source name expr row col
1342 ListEnd row col ->
1343 error "TODO ListEnd" row col
1345 ListIndentOpen row col ->
1346 let
1347 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1348 region = toRegion row col
1349 in
1350 Report.Report "UNFINISHED LIST" region [] $
1351 Report.toCodeSnippet source surroundings (Just region)
1353 D.reflow $
1354 "I cannot find the end of this list:"
1356 D.stack
1357 [ D.fillSep $
1358 ["You","could","change","it","to","something","like"
1359 ,D.dullyellow "[3,4,5]"
1360 ,"or","even","just"
1361 ,D.dullyellow "[]" <> "."
1362 ,"Anything","where","there","is","an","open","and","close","square","brace,"
1363 ,"and","where","the","elements","of","the","list","are","separated","by","commas."
1365 , D.toSimpleNote
1366 "I may be confused by indentation. For example, if you are trying to define\
1367 \ a list across multiple lines, I recommend using this format:"
1368 , D.indent 4 $ D.vcat $
1369 [ "[ \"Alice\""
1370 , ", \"Bob\""
1371 , ", \"Chuck\""
1372 , "]"
1374 , D.reflow $
1375 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
1376 \ This style can be jarring for people coming from C-like syntax, but folks generally\
1377 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
1381 ListIndentEnd row col ->
1382 let
1383 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1384 region = toRegion row col
1385 in
1386 Report.Report "UNFINISHED LIST" region [] $
1387 Report.toCodeSnippet source surroundings (Just region)
1389 D.reflow $
1390 "I cannot find the end of this list:"
1392 D.stack
1393 [ D.fillSep $
1394 ["You","can","just","add","a","closing",D.dullyellow "]"
1395 ,"right","here,","and","I","will","be","all","set!"
1397 , D.toSimpleNote
1398 "I may be confused by indentation. For example, if you are trying to define\
1399 \ a list across multiple lines, I recommend using this format:"
1400 , D.indent 4 $ D.vcat $
1401 [ "[ \"Alice\""
1402 , ", \"Bob\""
1403 , ", \"Chuck\""
1404 , "]"
1406 , D.reflow $
1407 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
1408 \ This style can be jarring for people coming from C-like syntax, but folks generally\
1409 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
1413 ListIndentExpr 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 "UNFINISHED LIST" region [] $
1419 Report.toCodeSnippet source surroundings (Just region)
1421 D.reflow $
1422 "I was expecting to see another list entry after this comma:"
1424 D.stack
1425 [ D.reflow $
1426 "Trailing commas are not allowed in lists, so the fix may be to delete the comma?"
1427 , D.toSimpleNote
1428 "I recommend using the following format for lists that span multiple lines:"
1429 , D.indent 4 $ D.vcat $
1430 [ "[ \"Alice\""
1431 , ", \"Bob\""
1432 , ", \"Chuck\""
1433 , "]"
1435 , D.reflow $
1436 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
1437 \ This style can be jarring for people coming from C-like syntax, but folks generally\
1438 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
1443toFuncReport :: Code.Source -> Name.Name -> Func -> Row -> Col -> Report.Report
1444toFuncReport source name func startRow startCol =
1445 case func of
1446 FuncSpace space row col ->
1447 toSpaceReport source space row col
1449 FuncArg pattern row col ->
1450 error "TODO FuncArg" pattern row col
1452 FuncBody expr row col ->
1453 toExprReport source name expr row col
1455 FuncArrow row col ->
1456 let
1457 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1458 region = toRegion row col
1459 in
1460 Report.Report "UNFINISHED ANONYMOUS FUNCTION" region [] $
1461 Report.toCodeSnippet source surroundings (Just region)
1463 D.reflow $
1464 "I just saw the beginning of an anonymous function, so I was expecting to see an arrow next:"
1466 D.fillSep $
1467 ["The","syntax","for","anonymous","functions","is"
1468 ,D.dullyellow "(\\x -> x + 1)"
1469 ,"so","I","am","missing","the","arrow","and","the","body","of","the","function."
1473 FuncIndentArg row col ->
1474 let
1475 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1476 region = toRegion row col
1477 in
1478 Report.Report "MISSING ARGUMENT" region [] $
1479 Report.toCodeSnippet source surroundings (Just region)
1481 D.reflow $
1482 "I just saw the beginning of an anonymous function, so I was expecting to see an argument next:"
1484 D.stack
1485 [ D.fillSep
1486 ["Something","like",D.dullyellow"x","or",D.dullyellow "name" <> "."
1487 ,"Anything","that","starts","with","a","lower","case","letter!"
1489 , D.toSimpleNote $
1490 "The syntax for anonymous functions is (\\x -> x + 1) where the backslash\
1491 \ is meant to look a bit like a lambda if you squint. This visual pun seemed\
1492 \ like a better idea at the time!"
1496 FuncIndentArrow row col ->
1497 let
1498 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1499 region = toRegion row col
1500 in
1501 Report.Report "UNFINISHED ANONYMOUS FUNCTION" region [] $
1502 Report.toCodeSnippet source surroundings (Just region)
1504 D.reflow $
1505 "I just saw the beginning of an anonymous function, so I was expecting to see an arrow next:"
1507 D.stack
1508 [ D.fillSep $
1509 ["The","syntax","for","anonymous","functions","is"
1510 ,D.dullyellow "(\\x -> x + 1)"
1511 ,"so","I","am","missing","the","arrow","and","the","body","of","the","function."
1513 , D.toSimpleNote $
1514 "It is possible that I am confused about indetation! I generally recommend\
1515 \ switching to named functions if the definition cannot fit inline nicely, so\
1516 \ either (1) try to fit the whole anonymous function on one line or (2) break\
1517 \ the whole thing out into a named function. Things tend to be clearer that way!"
1521 FuncIndentBody row col ->
1522 let
1523 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1524 region = toRegion row col
1525 in
1526 Report.Report "UNFINISHED ANONYMOUS FUNCTION" region [] $
1527 Report.toCodeSnippet source surroundings (Just region)
1529 D.reflow $
1530 "I was expecting to see the body of your anonymous function next:"
1532 D.stack
1533 [ D.fillSep $
1534 ["The","syntax","for","anonymous","functions","is"
1535 ,D.dullyellow "(\\x -> x + 1)"
1536 ,"so","I","am","missing","all","the","stuff","after","the","arrow!"
1538 , D.toSimpleNote $
1539 "It is possible that I am confused about indetation! I generally recommend\
1540 \ switching to named functions if the definition cannot fit inline nicely, so\
1541 \ either (1) try to fit the whole anonymous function on one line or (2) break\
1542 \ the whole thing out into a named function. Things tend to be clearer that way!"
1550 case err of
1551 CommentOnNothing region ->
1552 Report.Report "STRAY COMMENT" region [] $
1553 Report.toCodeSnippet source region Nothing
1555 "This documentation comment is not followed by anything."
1557 D.reflow $
1558 "All documentation comments need to be right above the declaration they\
1559 \ describe. Maybe some code got deleted or commented out by accident? Or\
1560 \ maybe this comment is here by accident?"
1563 UnexpectedPort region ->
1564 Report.Report "UNEXPECTED PORTS" region [] $
1565 Report.toCodeSnippet source region Nothing
1567 D.reflow $
1568 "You are declaring ports in a normal module."
1570 D.stack
1571 [ D.fillSep
1572 ["Switch","this","to","say",D.green "port module","instead,"
1573 ,"marking","that","this","module","contains","port","declarations."
1575 , D.link "Note"
1576 "Ports are not a traditional FFI for calling JS functions directly. They need a different mindset! Read"
1577 "ports"
1578 "to learn the syntax and how to use it effectively."
1582 NoPorts region ->
1583 Report.Report "NO PORTS" region [] $
1584 Report.toCodeSnippet source region Nothing
1586 D.reflow $
1587 "This module does not declare any ports, but it says it will:"
1589 D.fillSep
1590 ["Switch","this","to",D.green "module"
1591 ,"and","you","should","be","all","set!"
1595 ParseError row col context expectation ->
1596 let
1597 pos = A.Position row col
1598 region = A.Region pos pos
1599 in
1600 case expectation of
1602 DocComment ->
1603 Report.Report "EXPECTING DOC COMMENT" region [] $
1604 Report.toCodeSnippet source region Nothing
1606 D.reflow $
1607 "I was expecting a doc comment here:"
1609 D.reflowLink
1610 "Check out" "TODO" "for examples of doc comments."
1613 -- Parse.Number
1615 Precedence ->
1616 Report.Report "EXPECTING PRECEDENCE" region [] $
1617 Report.toCodeSnippet source region Nothing
1619 D.reflow $
1620 "I was expecting the precedence here:"
1622 D.reflow $
1623 "I need a single digit between 0 and 9 inclusive."
1626 Operator ->
1627 Report.Report "EXPECTING AN OPERATOR" region [] $
1628 Report.toCodeSnippet source region Nothing
1630 D.reflow $
1631 "I was expecting an operator here:"
1633 D.stack
1634 [ D.reflow "Some of the most common operators are:"
1635 , D.indent 4 $ D.vcat ["+","-","*","&&","||"]
1636 , D.reflow "Something like that!"
1640 Wildcard ->
1641 Report.Report "EXPECTING A WILDCARD" region [] $
1642 Report.toCodeSnippet source region Nothing
1644 D.reflow $
1645 "I was expecting a _ here:"
1647 D.reflow $
1648 "An underscore indicates that “I do not care about this value” and is\
1649 \ called a wildcard pattern because it will match with any type of values."
1652 WildcardNotVar startCol endCol ->
1653 let
1654 badRegion =
1655 A.Region (A.Position row startCol) (A.Position row endCol)
1656 in
1657 Report.Report "INVALID PATTERN" badRegion [] $
1658 Report.toCodeSnippet source badRegion Nothing
1660 D.reflow $
1661 "I was expecting to see an underscore without any additional characters:"
1663 D.reflow $
1664 "There are two options. Either (1) remove the extra characters and ignore the\
1665 \ value or (2) remove the starting underscore to give the value a normal name."
1668 -- Parse.Pattern
1670 FloatInPattern ->
1671 Report.Report "INVALID PATTERN" region [] $
1672 Report.toCodeSnippet source region Nothing
1674 D.reflow $
1675 "I cannot pattern match with floating point numbers:"
1677 D.reflow $
1678 "Equality on floats can be unreliable, so you usually want to check that they\
1679 \ are nearby with some sort of (abs (actual - expected) < 0.001) check."
1682 FieldNamePattern ->
1683 Report.Report "EXPECTING A FIELD NAME" region [] $
1684 Report.toCodeSnippet source region Nothing
1686 D.reflow $
1687 "I was expecting a field name here:"
1689 D.fillSep $
1690 ["A","name","like",D.dullyellow "id" <> ",",D.dullyellow "status" <> ","
1691 ,"or","whatever","field","you","want","to","access."
1695 -- Parse.Expression
1697 MatchingName name ->
1698 Report.Report "EXPECTING A DEFINITION" region [] $
1699 Report.toCodeSnippet source region Nothing
1701 D.reflow $
1702 "I just saw the type annotation for `" ++ Name.toChars name
1703 ++ "` so I was expecting to see its definition here:"
1705 D.reflow $
1706 "Type annotations always appear directly above the relevant\
1707 \ definition, without anything else (even doc comments) in between."
1713 TypeWithBadDefinition region annName defName ->
1714 Report.Report "ANNOTATION MISMATCH" region [] $
1715 Report.toCodeSnippet source region Nothing
1717 D.reflow $
1718 "I see a `" <> Name.toChars annName
1719 <> "` annotation, but it is followed by a `"
1720 <> Name.toChars defName <> "` definition."
1722 D.fillSep
1723 ["The","annotation","and","definition","names","must","match!"
1724 ,"Is","there","a","typo","between"
1725 , D.dullyellow (D.fromName annName)
1726 ,"and"
1727 , D.dullyellow (D.fromName defName) <> "?"
1732-- CONTEXT
1735contextToString :: String -> String -> ContextStack -> String
1736contextToString defaultString prefixString stack =
1737 case stack of
1738 [] ->
1739 defaultString
1741 (context, _) : rest ->
1742 let anchor = getAnchor rest in
1743 prefixString <>
1744 case context of
1745 ExprIf -> "an `if` expression" <> anchor
1746 ExprLet -> "a `let` expression" <> anchor
1747 ExprFunc -> "an anonymous function" <> anchor
1748 ExprCase -> "a `case` expression" <> anchor
1749 ExprList -> "a list" <> anchor
1750 ExprTuple -> "an expression (in parentheses)" <> anchor
1751 ExprRecord -> "a record" <> anchor
1752 Definition name -> Name.toChars name <> "'s definition"
1753 Annotation name -> Name.toChars name <> "'s type annotation"
1754 TypeTuple -> "a type (in parentheses)" <> anchor
1755 TypeRecord -> "a record type" <> anchor
1756 PatternList -> "a list pattern" <> anchor
1757 PatternTuple -> "a pattern (in parentheses)" <> anchor
1758 PatternRecord -> "a record pattern" <> anchor
1759 Module -> "a module declaration"
1760 Import -> "an import"
1761 TypeUnion -> "a union type"
1762 TypeAlias -> "a type alias"
1763 Infix -> "an infix declaration"
1764 Port -> "a port declaration"
1767getAnchor :: ContextStack -> String
1768getAnchor stack =
1769 case stack of
1770 [] ->
1771 ""
1773 (context, _) : rest ->
1774 case context of
1775 Definition name ->
1776 " in " <> Name.toChars name <> "'s definition"
1778 Annotation name ->
1779 " in " <> Name.toChars name <> "'s type annotation"
1781 _ ->
1782 getAnchor rest