on 0bdcdd8 help sign in
2453 lines 79 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 error "TODO ImportStart" row col
625 ImportName row col ->
626 error "TODO ImportName" row col
628 ImportAs row col ->
629 error "TODO ImportAs" row col
631 ImportAlias row col ->
632 error "TODO ImportAlias" row col
634 ImportExposing row col ->
635 error "TODO ImportExposing" row col
637 ImportExposingList exposing row col ->
638 error "TODO ImportExposingList" exposing row col
640 ImportEnd row col ->
641 error "TODO ImportEnd" row col
643 ImportIndentName row col ->
644 error "TODO ImportIndentName" row col
646 ImportIndentAlias row col ->
647 error "TODO ImportIndentAlias" row col
649 ImportIndentExposingList row col ->
650 let
651 region = toRegion row col
652 in
653 Report.Report "UNFINISHED IMPORT" region [] $
654 Code.toSnippet source region Nothing
655 (
656 D.reflow $
657 "I was parsing an `import` until I got stuck here:"
658 ,
659 D.stack
660 [ D.reflow $
661 "I was expecting to see the list of exposed values next. For example, here\
662 \ are two ways to expose values from the `Html` module:"
663 , D.indent 4 $ D.vcat $
664 [ D.fillSep [D.blue "import","Html",D.blue "exposing",D.green "(..)"]
665 , D.fillSep [D.blue "import","Html",D.blue "exposing",D.green "(Html, div, text)"]
666 ]
667 , D.reflow $
668 "I generally recommend the second style. It is more explicit, making it\
669 \ much easier to figure out where values are coming from in large projects!"
670 ]
671 )
673 Infix row col ->
674 let
675 region = toRegion row col
676 in
677 Report.Report "BAD INFIX" region [] $
678 Code.toSnippet source region Nothing
679 (
680 D.reflow $
681 "Something went wrong in this infix operator declaration:"
682 ,
683 D.reflow $
684 "This feature is used by the @elm organization to define the\
685 \ languages built-in operators."
686 )
688 Declarations decl _ _ ->
689 toDeclarationsReport source decl
692toSpaceReport :: Code.Source -> Space -> Row -> Col -> Report.Report
693toSpaceReport source space row col =
694 case space of
695 HasTab ->
696 let
697 region = toRegion row col
698 in
699 Report.Report "NO TABS" region [] $
700 Code.toSnippet source region Nothing
701 (
702 D.reflow $
703 "I ran into a tab, but tabs are not allowed in Elm files."
704 ,
705 D.reflow $
706 "Replace the tab with spaces."
707 )
709 EndlessMultiComment ->
710 let
711 region = toWiderRegion row col 2
712 in
713 Report.Report "ENDLESS COMMENT" region [] $
714 Code.toSnippet source region Nothing
715 (
716 D.reflow $
717 "I cannot find the end of this multi-line comment:"
718 ,
719 D.stack -- "{-"
720 [ D.reflow "Add a -} somewhere after this to end the comment."
721 , D.toSimpleHint
722 "Multi-line comments can be nested in Elm, so {- {- -} -} is a comment\
723 \ that happens to contain another comment. Like parentheses and curly braces,\
724 \ the start and end markers must always be balanced. Maybe that is the problem?"
725 ]
726 )
729toRegion :: Row -> Col -> A.Region
730toRegion row col =
731 let
732 pos = A.Position row col
733 in
734 A.Region pos pos
737toWiderRegion :: Row -> Col -> Word16 -> A.Region
738toWiderRegion row col extra =
739 A.Region
740 (A.Position row col)
741 (A.Position row (col + extra))
744toDeclarationsReport :: Code.Source -> Decl -> Report.Report
745toDeclarationsReport source decl =
746 case decl of
747 DeclStart row col ->
748 error "TODO DeclStart" row col
750 DeclSpace space row col ->
751 toSpaceReport source space row col
753 Port port row col ->
754 error "TODO Port" port row col
756 DeclType declType row col ->
757 error "TODO DeclType" declType row col
759 DeclDef name declDef row col ->
760 toDeclDefReport source name declDef row col
762 DeclFreshLineStart row col ->
763 error "TODO DeclFreshLineStart" row col
765 DeclFreshLineAfterDocComment row col ->
766 error "TODO DeclFreshLineAfterDocComment" row col
769toDeclDefReport :: Code.Source -> Name.Name -> DeclDef -> Row -> Col -> Report.Report
770toDeclDefReport source name declDef startRow startCol =
771 case declDef of
772 DeclDefSpace space row col ->
773 toSpaceReport source space row col
775 DeclDefEquals row col ->
776 error "TODO DeclDefEquals" row col
778 DeclDefType tipe row col ->
779 error "TODO DeclDefType" tipe row col
781 DeclDefArg pattern row col ->
782 error "TODO DeclDefArg" pattern row col
784 DeclDefBody expr row col ->
785 toExprReport source (InDef name startRow startCol) expr row col
787 DeclDefNameRepeat row col ->
788 error "TODO DeclDefNameRepeat" name row col
790 DeclDefNameMatch defName row col ->
791 error "TODO DeclDefNameMatch" name defName row col
793 DeclDefIndentType row col ->
794 error "TODO DeclDefIndentType" row col
796 DeclDefIndentEquals row col ->
797 error "TODO DeclDefIndentEquals" row col
799 DeclDefIndentBody row col ->
800 error "TODO DeclDefIndentBody" row col
802 DeclDefFreshLineAfterType row col ->
803 error "TODO DeclDefFreshLineAfterType" row col
807-- CONTEXT
810data Context
811 = InNode Node Row Col Context
812 | InDef Name.Name Row Col
815data Node
816 = NRecord
817 | NParens
818 | NList
819 | NFunc
820 | NCond
821 | NThen
822 | NElse
823 deriving (Eq)
826getDefName :: Context -> Name.Name
827getDefName context =
828 case context of
829 InDef name _ _ -> name
830 InNode _ _ _ c -> getDefName c
833isWithin :: Node -> Context -> Bool
834isWithin desiredNode context =
835 case context of
836 InDef _ _ _ -> False
837 InNode actualNode _ _ _ -> desiredNode == actualNode
841-- EXPR REPORTS
844toExprReport :: Code.Source -> Context -> Expr -> Row -> Col -> Report.Report
845toExprReport source context expr startRow startCol =
846 case expr of
847 Let _ _ _ ->
848 error "TODO Let"
850 Case _ _ _ ->
851 error "TODO Case"
853 If if_ row col ->
854 toIfReport source context if_ row col
856 List list row col ->
857 toListReport source context list row col
859 Record record row col ->
860 toRecordReport source context record row col
862 Tuple tuple row col ->
863 toTupleReport source context tuple row col
865 Func func row col ->
866 toFuncReport source context func row col
868 Dot row col ->
869 let region = toRegion row col in
870 Report.Report "EXPECTING RECORD ACCESSOR" region [] $
871 Code.toSnippet source region Nothing
872 (
873 D.reflow $
874 "I was expecting to see a record accessor here:"
875 ,
876 D.fillSep
877 ["Something","like",D.dullyellow".name","or",D.dullyellow".price"
878 ,"that","accesses","a","value","from","a","record."
879 ]
880 )
882 Access row col ->
883 let region = toRegion row col in
884 Report.Report "EXPECTING RECORD ACCESSOR" region [] $
885 Code.toSnippet source region Nothing
886 (
887 D.reflow $
888 "I am trying to parse a record accessor here:"
889 ,
890 D.stack
891 [
892 D.fillSep
893 ["Something","like",D.dullyellow".name","or",D.dullyellow".price"
894 ,"that","accesses","a","value","from","a","record."
895 ]
896 ,
897 D.toSimpleNote $
898 "Record field names must start with a lower case letter!"
899 ]
900 )
902 OperatorRight op row col ->
903 let region = toRegion row col in
904 Report.Report "MISSING EXPRESSION" region [] $
905 Code.toSnippet source region Nothing
906 (
907 D.reflow $
908 "I was expecting to see an expression after this " ++ Name.toChars op ++ " operator:"
909 ,
910 D.stack
911 [ D.fillSep $
912 ["You","can","just","put","anything","for","now,","like"
913 ,D.dullyellow "42","or",D.dullyellow"\"hello\"" <> "."
914 ,"Once","there","is","something","there,","I","can","probably"
915 ,"give","a","more","specific","hint!"
916 ]
917 , D.toSimpleNote $
918 "This can also happen if run into reserved words like `let` or `as` unexpectedly.\
919 \ Or if I run into operators in unexpected spots. Point is, there are a\
920 \ couple ways I can get confused and give sort of weird advice!"
921 ]
922 )
924 OperatorReserved operator row col ->
925 toOperatorReport source context operator row col
927 Start row col ->
928 let
929 (contextRow, contextCol, aThing) =
930 case context of
931 InDef name r c -> (r, c, "the `" ++ Name.toChars name ++ "` definition")
932 InNode NRecord r c _ -> (r, c, "a record")
933 InNode NParens r c _ -> (r, c, "some parentheses")
934 InNode NList r c _ -> (r, c, "a list")
935 InNode NFunc r c _ -> (r, c, "an anonymous function")
936 InNode NCond r c _ -> (r, c, "an `if` expression")
937 InNode NThen r c _ -> (r, c, "an `if` expression")
938 InNode NElse r c _ -> (r, c, "an `if` expression")
939 -- TODO check if this is actually the best way to get error messages here
941 surroundings = A.Region (A.Position contextRow contextCol) (A.Position row col)
942 region = toRegion row col
943 in
944 Report.Report "MISSING EXPRESSION" region [] $
945 Code.toSnippet source surroundings (Just region)
946 (
947 D.reflow $
948 "I am partway through parsing " ++ aThing ++ ", but I got stuck here:"
949 ,
950 D.stack
951 [ D.fillSep $
952 ["I","was","expecting","to","see","an","expression","like"
953 ,D.dullyellow "42","or",D.dullyellow"\"hello\"" <> "."
954 ,"Once","there","is","something","there,","I","can","probably"
955 ,"give","a","more","specific","hint!"
956 ]
957 , D.toSimpleNote $
958 "This can also happen if run into reserved words like `let` or `as` unexpectedly.\
959 \ Or if I run into operators in unexpected spots. Point is, there are a\
960 \ couple ways I can get confused and give sort of weird advice!"
961 ]
962 )
964 Char char row col ->
965 toCharReport source char row col
967 String string row col ->
968 toStringReport source string row col
970 Number number row col ->
971 toNumberReport source number row col
973 Space space row col ->
974 toSpaceReport source space row col
976 EndlessShader row col ->
977 let
978 region = toWiderRegion row col 6
979 in
980 Report.Report "ENDLESS SHADER" region [] $
981 Code.toSnippet source region Nothing
982 (
983 D.reflow "I cannot find the end of this shader:"
984 ,
985 D.reflow "Add a |] somewhere after this to end the shader."
986 )
988 ShaderProblem problem row col ->
989 let
990 region = toRegion row col
991 in
992 Report.Report "SHADER PROBLEM" region [] $
993 Code.toSnippet source region Nothing
994 (
995 D.reflow $
996 "I ran into a problem while parsing this GLSL block."
997 ,
998 D.stack
999 [ D.reflow $
1000 "I use a 3rd party GLSL parser for now, and I did my best to extract their error message:"
1001 , D.indent 4 $ D.vcat $
1002 map D.fromChars (filter (/="") (lines problem))
1006 IndentOperatorRight op row col ->
1007 let
1008 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1009 region = toRegion row col
1010 in
1011 Report.Report "MISSING EXPRESSION" region [] $
1012 Code.toSnippet source surroundings (Just region)
1014 D.reflow $
1015 "I was expecting to see an expression after this " ++ Name.toChars op ++ " operator:"
1017 D.stack
1019 D.fillSep $
1020 ["You","can","just","put","anything","for","now,","like"
1021 ,D.dullyellow "42","or",D.dullyellow"\"hello\"" <> "."
1022 ,"Once","there","is","something","there,","I","can","probably"
1023 ,"give","a","more","specific","hint!"
1026 D.toSimpleNote $
1027 "I may be getting confused by your indentation? The easiest way to make sure\
1028 \ this is not an indentation problem is to put the expression on the right of\
1029 \ the " ++ Name.toChars op ++ " operator on the same line."
1033 IndentMoreExpr _ _ ->
1034 error "TODO IndentMoreExpr"
1038-- CHAR
1041toCharReport :: Code.Source -> Char -> Row -> Col -> Report.Report
1042toCharReport source char row col =
1043 case char of
1044 CharEndless ->
1045 let
1046 region = toRegion row col
1047 in
1048 Report.Report "MISSING SINGLE QUOTE" region [] $
1049 Code.toSnippet source region Nothing
1051 D.reflow $
1052 "I thought I was parsing a character, but I got to the end of\
1053 \ the line without seeing the closing single quote:"
1055 D.reflow $
1056 "Add a closing single quote here!"
1059 CharEscape escape ->
1060 toEscapeReport source escape row col
1062 CharNotString width ->
1063 let
1064 region = toWiderRegion row col width
1065 in
1066 Report.Report "NEEDS DOUBLE QUOTES" region [] $
1067 Code.toSnippet source region Nothing
1069 "The following string uses single quotes:"
1071 D.stack
1072 [ "Please switch to double quotes instead:"
1073 , D.indent 4 $
1074 D.dullyellow "'this'" <> " => " <> D.green "\"this\""
1075 , D.toSimpleNote $
1076 "Elm uses double quotes for strings like \"hello\", whereas it uses single\
1077 \ quotes for individual characters like 'a' and 'ø'. This distinction helps with\
1078 \ code like (String.any (\\c -> c == 'X') \"90210\") where you are inspecting\
1079 \ individual characters."
1085-- STRING
1088toStringReport :: Code.Source -> String -> Row -> Col -> Report.Report
1089toStringReport source string row col =
1090 case string of
1091 StringEndless_Single ->
1092 let
1093 region = toRegion row col
1094 in
1095 Report.Report "ENDLESS STRING" region [] $
1096 Code.toSnippet source region Nothing
1098 D.reflow $
1099 "I got to the end of the line without seeing the closing double quote:"
1101 D.stack
1102 [ D.fillSep $
1103 ["Strings","look","like",D.green "\"this\"","with","double"
1104 ,"quotes","on","each","end.","Is","the","closing","double"
1105 ,"quote","missing","in","your","code?"
1107 , D.link "Note" "Read" "TODO" "if you want a string that spans multiple lines."
1111 StringEndless_Multi ->
1112 let
1113 region = toWiderRegion row col 3
1114 in
1115 Report.Report "ENDLESS STRING" region [] $
1116 Code.toSnippet source region Nothing
1118 D.reflow $
1119 "I cannot find the end of this multi-line string:"
1121 D.stack
1122 [ D.reflow "Add a \"\"\" somewhere after this to end the string."
1123 , D.link "Hint" "Read" "TODO" "for more information on strings and multi-line strings."
1127 StringEscape escape ->
1128 toEscapeReport source escape row col
1132-- ESCAPES
1135toEscapeReport :: Code.Source -> Escape -> Row -> Col -> Report.Report
1136toEscapeReport source escape row col =
1137 case escape of
1138 EscapeUnknown ->
1139 let
1140 region = toWiderRegion row col 2
1141 in
1142 Report.Report "UNKNOWN ESCAPE" region [] $
1143 Code.toSnippet source region Nothing
1145 D.reflow $
1146 "Backslashes always start escaped characters, but I do not recognize this one:"
1148 D.stack
1149 [ D.reflow $
1150 "Valid escape characters include:"
1151 , D.dullyellow $ D.indent 4 $ D.vcat $
1152 [ "\\n"
1153 , "\\r"
1154 , "\\t"
1155 , "\\\""
1156 , "\\\'"
1157 , "\\\\"
1158 , "\\u{003D}"
1160 , D.reflow $
1161 "Do you want one of those instead? Maybe you need \\\\ to escape a backslash?"
1162 , D.toSimpleNote $
1163 "The last style lets encode ANY character by its Unicode code\
1164 \ point. That means \\u{0009} and \\t are the same. You can use\
1165 \ that style for anything not covered by the other six escapes!"
1169 BadUnicodeFormat width ->
1170 let
1171 region = toWiderRegion row col width
1172 in
1173 Report.Report "BAD UNICODE ESCAPE" region [] $
1174 Code.toSnippet source region Nothing
1176 D.reflow $
1177 "I ran into an invalid Unicode escape:"
1179 D.stack
1180 [ D.reflow $
1181 "Here are some examples of valid Unicode escapes:"
1182 , D.dullyellow $ D.indent 4 $ D.vcat $
1183 [ "\\u{0041}"
1184 , "\\u{03BB}"
1185 , "\\u{6728}"
1186 , "\\u{1F60A}"
1188 , D.reflow $
1189 "Notice that the code point is always surrounded by curly braces.\
1190 \ Maybe you are missing the opening or closing curly brace?"
1193 BadUnicodeCode width ->
1194 let
1195 region = toWiderRegion row col width
1196 in
1197 Report.Report "BAD UNICODE ESCAPE" region [] $
1198 Code.toSnippet source region Nothing
1200 D.reflow $
1201 "This is not a valid code point:"
1203 D.reflow $
1204 "The valid code points are between 0 and 10FFFF inclusive."
1207 BadUnicodeLength width numDigits badCode ->
1208 let
1209 region = toWiderRegion row col width
1210 in
1211 Report.Report "BAD UNICODE ESCAPE" region [] $
1212 Code.toSnippet source region Nothing $
1213 if numDigits < 4 then
1215 D.reflow $
1216 "Every code point needs at least four digits:"
1218 let
1219 goodCode = replicate (4 - numDigits) '0' ++ map Char.toUpper (showHex badCode "")
1220 suggestion = "\\u{" <> D.fromChars goodCode <> "}"
1221 in
1222 D.fillSep ["Try",D.green suggestion,"instead?"]
1225 else
1227 D.reflow $
1228 "This code point has too many digits:"
1230 D.fillSep $
1231 ["Valid","code","points","are","between"
1232 ,D.green "\\u{0000}","and",D.green "\\u{10FFFF}" <> ","
1233 ,"so","try","trimming","any","leading","zeros","until"
1234 ,"you","have","between","four","and","six","digits."
1240-- NUMBERS
1243toNumberReport :: Code.Source -> Number -> Row -> Col -> Report.Report
1244toNumberReport source number row col =
1245 let
1246 region = toRegion row col
1247 in
1248 case number of
1249 NumberEnd ->
1250 Report.Report "WEIRD NUMBER" region [] $
1251 Code.toSnippet source region Nothing
1253 D.reflow $
1254 "I thought I was reading a number, but I ran into some weird stuff here:"
1256 D.stack
1257 [ D.reflow $
1258 "I recognize numbers in the following formats:"
1259 , D.indent 4 $ D.vcat [ "42", "3.14", "6.022e23", "0x002B" ]
1260 , D.reflow $
1261 "So is there a way to write it like one of those?"
1265 NumberDot int ->
1266 Report.Report "WEIRD NUMBER" region [] $
1267 Code.toSnippet source region Nothing
1269 D.reflow $
1270 "Numbers cannot end with a dot like this:"
1272 D.fillSep
1273 ["Switching","to",D.green (D.fromChars (show int))
1274 ,"or",D.green (D.fromChars (show int ++ ".0"))
1275 ,"will","work","though!"
1279 NumberHexDigit ->
1280 Report.Report "WEIRD HEXIDECIMAL" region [] $
1281 Code.toSnippet source region Nothing
1283 D.reflow $
1284 "I thought I was reading a hexidecimal number until I got here:"
1286 D.stack
1287 [ D.reflow $
1288 "Valid hexidecimal digits include 0123456789abcdefABCDEF, so I can\
1289 \ only recognize things like this:"
1290 , D.indent 4 $ D.vcat [ "0x2B", "0x002B", "0x00ffb3" ]
1294 NumberNoLeadingZero ->
1295 Report.Report "LEADING ZEROS" region [] $
1296 Code.toSnippet source region Nothing
1298 D.reflow $
1299 "I do not accept numbers with leading zeros:"
1301 D.stack
1302 [ D.reflow $
1303 "Just delete the leading zeros and it should work!"
1304 , D.toSimpleNote $
1305 "Some languages let you to specify octal numbers by adding a leading zero.\
1306 \ So in C, writing 0111 is the same as writing 73. Some people are used to\
1307 \ that, but others probably want it to equal 111. Either path is going to\
1308 \ surprise people from certain backgrounds, so Elm tries to avoid this whole\
1309 \ situation."
1315-- OPERATORS
1318toOperatorReport :: Code.Source -> Context -> BadOperator -> Row -> Col -> Report.Report
1319toOperatorReport source context operator row col =
1320 case operator of
1321 BadDot ->
1322 let
1323 region = toRegion row col
1324 in
1325 Report.Report "UNEXPECTED SYMBOL" region [] $
1326 Code.toSnippet source region Nothing
1328 "I was not expecting this dot:"
1330 D.reflow $
1331 "Dots are for record access and decimal points, so\
1332 \ they cannot float around on their own. Maybe\
1333 \ there is some extra whitespace?"
1336 BadPipe ->
1337 let
1338 region = toRegion row col
1339 in
1340 Report.Report "UNEXPECTED SYMBOL" region [] $
1341 Code.toSnippet source region Nothing
1343 D.reflow $
1344 "I was not expecting this vertical bar:"
1346 D.reflow $
1347 "Vertical bars should only appear in custom type declarations. Maybe you want || instead?"
1350 BadArrow ->
1351 let
1352 region = toWiderRegion row col 2
1353 in
1354 Report.Report "UNEXPECTED ARROW" region [] $
1355 Code.toSnippet source region Nothing $
1356 if error "TODO inCase" then
1358 D.reflow $
1359 "I was not expecting to see an arrow here:"
1361 D.stack
1363 D.reflow $
1364 "I think I am parsing a `case` expression right now, so it makes sense to\
1365 \ see arrows around here. This one is confusing me though!"
1367 D.toSimpleHint $
1368 "I may be getting confused by the indentation. Every pattern in a `case` must be\
1369 \ exactly aligned (with exactly the same amount of indentation) so maybe this arrow\
1370 \ appears after the next `case` pattern (correctly!) but the pattern itself is\
1371 \ indented too far?"
1375 else
1377 D.reflow $
1378 "I was not expecting an arrow here:"
1380 D.reflow $
1381 "Arrows should only appear in `case` expressions and anonymous functions. Maybe\
1382 \ you want > or >= instead?"
1385 BadEquals ->
1386 let
1387 region = toRegion row col
1388 name = getDefName context
1389 in
1390 Report.Report "UNEXPECTED EQUALS" region [] $
1391 Code.toSnippet source region Nothing
1393 D.reflow $
1394 "I was not expecting to see this equals sign:"
1396 D.stack
1398 D.reflow "Maybe you want == instead? To check if two values are equal?"
1400 D.toSimpleNote $
1401 if isWithin NRecord context then
1402 "Records look like { x = 3, y = 4 } with the equals sign right\
1403 \ after the field name. So maybe you forgot a comma?"
1404 else
1405 "I may be getting confused by your indentation. Is this supposed to be part of\
1406 \ a definition AFTER the `" ++ Name.toChars name ++ "` definition? If so,\
1407 \ the problem may be a bit before the equals sign. I need all definitions to\
1408 \ be exactly aligned (with exactly the same indentation) so the problem may be that\
1409 \ this new definition is indented a bit too much."
1413 BadHasType ->
1414 let
1415 region = toRegion row col
1416 name = getDefName context
1417 in
1418 Report.Report "UNEXPECTED SYMBOL" region [] $
1419 Code.toSnippet source region Nothing $
1421 D.reflow $
1422 "I was not expecting to run into the \"has type\" symbol here:"
1424 D.stack
1426 D.fillSep
1427 ["Maybe","you","want",D.green "::","instead?"
1428 ,"To","put","something","on","the","front","of","a","list?"
1430 , D.toSimpleNote $
1431 "The single colon is reserved for type annotations and record types, but I think\
1432 \ I am parsing the definition of `" ++ Name.toChars name ++ "` right now."
1434 D.toSimpleNote $
1435 "I may be getting confused by your indentation. Is this supposed to be part of\
1436 \ a type annotation AFTER the `" ++ Name.toChars name ++ "` definition? If so,\
1437 \ the problem may be a bit before the \"has type\" symbol. I need all definitions to\
1438 \ be exactly aligned (with exactly the same indentation) so the problem may be that\
1439 \ this new definition is indented a bit too much."
1445-- IF
1448toIfReport :: Code.Source -> Context -> If -> Row -> Col -> Report.Report
1449toIfReport source context if_ startRow startCol =
1450 case if_ of
1451 IfSpace space row col ->
1452 toSpaceReport source space row col
1454 IfThen row col ->
1455 let
1456 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1457 region = toRegion row col
1458 in
1459 Report.Report "UNFINISHED IF" region [] $
1460 Code.toSnippet source surroundings (Just region)
1462 D.reflow $
1463 "I was expecting to see more of this `if` expression, but I got stuck here:"
1465 D.fillSep $
1466 ["I","was","expecting","to","see","the",D.green "then","keyword","next."
1470 IfElse row col ->
1471 let
1472 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1473 region = toRegion row col
1474 in
1475 Report.Report "UNFINISHED IF" region [] $
1476 Code.toSnippet source surroundings (Just region)
1478 D.reflow $
1479 "I was expecting to see more of this `if` expression, but I got stuck here:"
1481 D.fillSep $
1482 ["I","was","expecting","to","see","the",D.green "else","keyword","next."
1486 IfElseBranchStart row col ->
1487 let
1488 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1489 region = toRegion row col
1490 in
1491 Report.Report "UNFINISHED IF" region [] $
1492 Code.toSnippet source surroundings (Just region)
1494 D.reflow $
1495 "I just saw the start of an `else` branch, but then I got stuck here:"
1497 D.reflow $
1498 "I was expecting to see an expression next. Maybe it is not filled in yet?"
1501 IfCondition expr row col ->
1502 toExprReport source (InNode NCond startRow startCol context) expr row col
1504 IfThenBranch expr row col ->
1505 toExprReport source (InNode NThen startRow startCol context) expr row col
1507 IfElseBranch expr row col ->
1508 toExprReport source (InNode NElse startRow startCol context) expr row col
1510 IfIndentCondition row col ->
1511 let
1512 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1513 region = toRegion row col
1514 in
1515 Report.Report "UNFINISHED IF" region [] $
1516 Code.toSnippet source surroundings (Just region)
1518 D.reflow $
1519 "I was expecting to see more of this `if` expression, but I got stuck here:"
1521 D.stack
1522 [ D.fillSep $
1523 ["I","was","expecting","to","see","an","expression","like",D.dullyellow "x < 0"
1524 ,"that","evaluates","to","True","or","False."
1526 , D.toSimpleNote $
1527 "I can be confused by indentation. Maybe something is not indented enough?"
1531 IfIndentThen row col ->
1532 let
1533 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1534 region = toRegion row col
1535 in
1536 Report.Report "UNFINISHED IF" region [] $
1537 Code.toSnippet source surroundings (Just region)
1539 D.reflow $
1540 "I was expecting to see more of this `if` expression, but I got stuck here:"
1542 D.stack
1543 [ D.fillSep $
1544 ["I","was","expecting","to","see","the",D.green "then","keyword","next."
1546 , D.toSimpleNote $
1547 "I can be confused by indentation. Maybe something is not indented enough?"
1551 IfIndentThenBranch row col ->
1552 let
1553 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1554 region = toRegion row col
1555 in
1556 Report.Report "UNFINISHED IF" region [] $
1557 Code.toSnippet source surroundings (Just region)
1559 D.reflow $
1560 "I got stuck after the start of this `then` branch:"
1562 D.stack
1563 [ D.reflow $
1564 "I was expecting to see an expression next. Maybe it is not filled in yet?"
1565 , D.toSimpleNote $
1566 "I can be confused by indentation, so if the `then` branch is already\
1567 \ present, it may not be indented enough for me to recognize it."
1571 IfIndentElseBranch row col ->
1572 let
1573 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1574 region = toRegion row col
1575 in
1576 Report.Report "UNFINISHED IF" region [] $
1577 Code.toSnippet source surroundings (Just region)
1579 D.reflow $
1580 "I got stuck after the start of this `else` branch:"
1582 D.stack
1583 [ D.reflow $
1584 "I was expecting to see an expression next. Maybe it is not filled in yet?"
1585 , D.toSimpleNote $
1586 "I can be confused by indentation, so if the `else` branch is already\
1587 \ present, it may not be indented enough for me to recognize it."
1591 IfIndentElse row col ->
1592 let
1593 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1594 region = toRegion row col
1595 in
1596 Report.Report "UNFINISHED IF" region [] $
1597 Code.toSnippet source surroundings (Just region)
1599 D.reflow $
1600 "I was expecting to see an `else` branch after this:"
1602 D.stack
1603 [ D.reflow $
1604 "I know what to do when the condition is `True`, but not when it is `False`."
1605 , D.fillSep
1606 ["Add","an",D.green "else","branch","to","handle","that","scenario!"]
1612-- RECORD
1615toRecordReport :: Code.Source -> Context -> Record -> Row -> Col -> Report.Report
1616toRecordReport source context record startRow startCol =
1617 case record of
1618 RecordOpen row col ->
1619 let
1620 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1621 region = toRegion row col
1622 in
1623 case Code.whatIsNext source row col of
1624 Keyword keyword ->
1625 Report.Report "RESERVED WORD" region [] $
1626 Code.toSnippet source surroundings (Just region)
1628 D.reflow $
1629 "I just started parsing a record, but I got stuck on this field name:"
1631 D.reflow $
1632 "It looks like you are trying to use `" ++ keyword ++ "` as a field name, but \
1633 \ that is a reserved word. Try using a different name!"
1636 _ ->
1637 Report.Report "UNFINISHED RECORD" region [] $
1638 Code.toSnippet source surroundings (Just region)
1640 D.reflow $
1641 "I just started parsing a record, but I got stuck here:"
1643 D.fillSep
1644 ["Records","look","like",D.dullyellow "{ x = 3, y = 4 },"
1645 ,"so","I","was","expecting","to","see","a","field","name","next."
1649 RecordEnd row col ->
1650 let
1651 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1652 region = toRegion row col
1653 in
1654 Report.Report "UNFINISHED RECORD" region [] $
1655 Code.toSnippet source surroundings (Just region)
1657 D.reflow $
1658 "I am partway through parsing a record, but I got stuck here:"
1660 D.stack
1661 [ D.fillSep
1662 ["I","was","expecting","to","see","a","closing","curly","brace","before","this,"
1663 ,"so","try","adding","a",D.dullyellow "}","and","see","if","that","helps?"
1665 , D.toSimpleNote $
1666 "When I get stuck like this, it usually means that there is a missing parenthesis\
1667 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
1671 RecordField row col ->
1672 let
1673 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1674 region = toRegion row col
1675 in
1676 case Code.whatIsNext source row col of
1677 Code.Keyword keyword ->
1678 Report.Report "RESERVED WORD" region [] $
1679 Code.toSnippet source surroundings (Just region)
1681 D.reflow $
1682 "I am partway through parsing a record, but I got stuck on this field name:"
1684 D.reflow $
1685 "It looks like you are trying to use `" ++ keyword ++ "` as a field name, but \
1686 \ that is a reserved word. Try using a different name!"
1689 _ ->
1690 Report.Report "UNFINISHED RECORD" region [] $
1691 Code.toSnippet source surroundings (Just region)
1693 D.reflow $
1694 "I am partway through parsing a record, but I got stuck after that last comma:"
1696 addNoteForRecordError $
1697 D.reflow $
1698 "Trailing commas are not allowed in records, so I was expecting to see another\
1699 \ record field defined next. If you are done defining the record, the fix may\
1700 \ be to delete that last comma?"
1703 RecordEquals row col ->
1704 let
1705 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1706 region = toRegion row col
1707 in
1708 Report.Report "UNFINISHED RECORD" region [] $
1709 Code.toSnippet source surroundings (Just region)
1711 D.reflow $
1712 "I am partway through parsing a record, but I got stuck here:"
1714 addNoteForRecordError $
1715 D.fillSep $
1716 ["I","just","saw","a","field","name,","so","I","was","expecting","to","see"
1717 ,"an","equals","sign","next.","So","try","putting","an",D.green "=","sign","here?"
1721 RecordExpr expr row col ->
1722 toExprReport source (InNode NRecord startRow startCol context) expr row col
1724 RecordSpace space row col ->
1725 toSpaceReport source space row col
1727 RecordIndentOpen row col ->
1728 let
1729 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1730 region = toRegion row col
1731 in
1732 Report.Report "UNFINISHED RECORD" region [] $
1733 Code.toSnippet source surroundings (Just region)
1735 D.reflow $
1736 "I just saw the opening curly brace of a record, but then I got stuck here:"
1738 addNoteForRecordIndentError $
1739 D.fillSep $
1740 ["I","am","expecting","a","record","like",D.dullyellow "{ x = 3, y = 4 }","here."
1741 ,"Try","defining","some","fields","of","your","own?"
1745 RecordIndentEnd row col ->
1746 let
1747 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1748 region = toRegion row col
1749 in
1750 Report.Report "UNFINISHED RECORD" region [] $
1751 Code.toSnippet source surroundings (Just region)
1753 D.reflow $
1754 "I was expecting to see a closing curly brace next:"
1756 addNoteForRecordIndentError $
1757 D.fillSep $
1758 ["Try","putting","an",D.green "}","and","see","if","that","helps?"
1762 RecordIndentField row col ->
1763 let
1764 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1765 region = toRegion row col
1766 in
1767 Report.Report "UNFINISHED RECORD" region [] $
1768 Code.toSnippet source surroundings (Just region)
1770 D.reflow $
1771 "I am partway through parsing a record, but I got stuck after that last comma:"
1773 addNoteForRecordError $
1774 D.reflow $
1775 "Trailing commas are not allowed in records, so the fix may be to\
1776 \ delete that last comma? Or maybe you were in the middle of defining\
1777 \ an additional field?"
1780 RecordIndentEquals row col ->
1781 let
1782 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1783 region = toRegion row col
1784 in
1785 Report.Report "UNFINISHED RECORD" region [] $
1786 Code.toSnippet source surroundings (Just region)
1788 D.reflow $
1789 "I am partway through parsing a record. I just saw a record\
1790 \ field, so I was expecting to see an equals sign next:"
1792 addNoteForRecordIndentError $
1793 D.fillSep $
1794 ["Try","putting","an",D.green "=","followed","by","an","expression?"
1798 RecordIndentExpr row col ->
1799 let
1800 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1801 region = toRegion row col
1802 in
1803 Report.Report "UNFINISHED RECORD" region [] $
1804 Code.toSnippet source surroundings (Just region)
1806 D.reflow $
1807 "I am partway through parsing a record, and I was expecting to run into an expression next:"
1809 addNoteForRecordIndentError $
1810 D.fillSep $
1811 ["Try","putting","something,","like"
1812 ,D.dullyellow "42","or",D.dullyellow"\"hello\"","for","now?"
1817addNoteForRecordError :: D.Doc -> D.Doc
1818addNoteForRecordError normalRecommendation =
1819 D.stack $
1820 normalRecommendation
1822 [ D.toSimpleNote
1823 "If you are trying to define a record across multiple lines, I recommend using this format:"
1824 , D.indent 4 $ D.vcat $
1825 [ "{ name = \"Alice\""
1826 , ", age = 42"
1827 , ", height = 1.75"
1828 , "}"
1830 , D.reflow $
1831 "Notice that nothing comes directly after a newline. Each line starts with some spaces. I\
1832 \ know this style can be jarring for people coming from C-like syntax, but folks generally\
1833 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
1837addNoteForRecordIndentError :: D.Doc -> D.Doc
1838addNoteForRecordIndentError normalRecommendation =
1839 D.stack $
1840 normalRecommendation
1842 [ D.toSimpleNote
1843 "I may be confused by indentation. For example, if you are trying to define\
1844 \ a record across multiple lines, I recommend using this format:"
1845 , D.indent 4 $ D.vcat $
1846 [ "[ \"Alice\""
1847 , ", \"Bob\""
1848 , ", \"Chuck\""
1849 , "]"
1851 , D.reflow $
1852 "Notice that nothing comes directly after a newline. Each line starts with some spaces. I\
1853 \ know this style can be jarring for people coming from C-like syntax, but folks generally\
1854 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
1859-- TUPLE
1862toTupleReport :: Code.Source -> Context -> Tuple -> Row -> Col -> Report.Report
1863toTupleReport source context tuple startRow startCol =
1864 case tuple of
1865 TupleExpr expr row col ->
1866 toExprReport source (InNode NParens startRow startCol context) expr row col
1868 TupleSpace space row col ->
1869 toSpaceReport source space row col
1871 TupleEnd row col ->
1872 let
1873 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1874 region = toRegion row col
1875 in
1876 Report.Report "UNFINISHED PARENTHESES" region [] $
1877 Code.toSnippet source surroundings (Just region)
1879 D.reflow $
1880 "I was expecting to see a closing parentheses next, but I got stuck here:"
1882 D.stack
1883 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps?"]
1884 , D.toSimpleNote $
1885 "I can get stuck when I run into keywords, operators, parentheses, or brackets\
1886 \ unexpectedly. So there may be some earlier syntax trouble (like extra parenthesis\
1887 \ or missing brackets) that is confusing me."
1891 TupleOperatorClose row col ->
1892 let
1893 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1894 region = toRegion row col
1895 in
1896 Report.Report "UNFINISHED OPERATOR FUNCTION" region [] $
1897 Code.toSnippet source surroundings (Just region)
1899 D.reflow "I was expecting a closing parenthesis here:"
1901 D.stack
1902 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps!"]
1903 , D.toSimpleNote $
1904 "I think I am parsing an operator function right now, so I am expecting to see\
1905 \ something like (+) or (&&) where an operator is surrounded by parentheses with\
1906 \ no extra spaces."
1910 TupleOperatorReserved operator row col ->
1911 let
1912 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1913 region = toRegion row col
1914 in
1915 Report.Report "UNEXPECTED SYMBOL" region [] $
1916 Code.toSnippet source surroundings (Just region)
1918 D.reflow $
1919 "I ran into an unexpected symbol here:"
1921 D.fillSep $
1922 case operator of
1923 BadDot -> ["Maybe","you","wanted","a","record","accessor","like",D.dullyellow ".x","or",D.dullyellow ".name","instead?"]
1924 BadPipe -> ["Try",D.dullyellow "(||)","instead?","To","turn","boolean","OR","into","a","function?"]
1925 BadArrow -> ["Maybe","you","wanted",D.dullyellow "(>)","or",D.dullyellow "(>=)","instead?"]
1926 BadEquals -> ["Try",D.dullyellow "(==)","instead?","To","make","a","function","that","checks","equality?"]
1927 BadHasType -> ["Try",D.dullyellow "(::)","instead?","To","add","values","to","the","front","of","lists?"]
1930 TupleIndentExpr1 row col ->
1931 let
1932 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1933 region = toRegion row col
1934 in
1935 Report.Report "UNFINISHED PARENTHESES" region [] $
1936 Code.toSnippet source surroundings (Just region)
1938 D.reflow $
1939 "I just saw an open parenthesis, so I was expecting to see an expression next."
1941 D.stack
1942 [ D.fillSep $
1943 ["Something","like",D.dullyellow "(4 + 5)","or"
1944 ,D.dullyellow "(String.reverse \"desserts\")" <> "."
1945 ,"Anything","where","you","are","putting","parentheses","around","normal","expressions."
1947 , D.toSimpleNote $
1948 "I can get confused by indentation in cases like this, so\
1949 \ maybe you have an expression but it is not indented enough?"
1953 TupleIndentExprN row col ->
1954 let
1955 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1956 region = toRegion row col
1957 in
1958 Report.Report "UNFINISHED TUPLE" region [] $
1959 Code.toSnippet source surroundings (Just region)
1961 D.reflow $
1962 "I think I am in the middle of parsing a tuple. I just saw a comma, so I was expecting to see expression next."
1964 D.stack
1965 [ D.fillSep $
1966 ["A","tuple","looks","like",D.dullyellow "(3,4)","or"
1967 ,D.dullyellow "(\"Tom\",42)" <> ","
1968 ,"so","I","think","there","is","an","expression","missing","here?"
1970 , D.toSimpleNote $
1971 "I can get confused by indentation in cases like this, so\
1972 \ maybe you have an expression but it is not indented enough?"
1976 TupleIndentEnd row col ->
1977 let
1978 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1979 region = toRegion row col
1980 in
1981 Report.Report "UNFINISHED PARENTHESES" region [] $
1982 Code.toSnippet source surroundings (Just region)
1984 D.reflow $
1985 "I was expecting to see a closing parenthesis next:"
1987 D.stack
1988 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps!"]
1989 , D.toSimpleNote $
1990 "I can get confused by indentation in cases like this, so\
1991 \ maybe you have a closing parenthesis but it is not indented enough?"
1996toListReport :: Code.Source -> Context -> List -> Row -> Col -> Report.Report
1997toListReport source context list startRow startCol =
1998 case list of
1999 ListSpace space row col ->
2000 toSpaceReport source space row col
2002 ListOpen row col ->
2003 let
2004 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2005 region = toRegion row col
2006 in
2007 Report.Report "UNFINISHED LIST" region [] $
2008 Code.toSnippet source surroundings (Just region)
2010 D.reflow $
2011 "I am partway through parsing a list, but I got stuck here:"
2013 D.stack
2014 [ D.fillSep
2015 ["I","was","expecting","to","see","a","closing","square","bracket","before","this,"
2016 ,"so","try","adding","a",D.dullyellow "]","and","see","if","that","helps?"
2018 , D.toSimpleNote $
2019 "When I get stuck like this, it usually means that there is a missing parenthesis\
2020 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
2024 ListExpr expr row col ->
2025 case expr of
2026 Start r c ->
2027 let
2028 surroundings = A.Region (A.Position startRow startCol) (A.Position r c)
2029 region = toRegion r c
2030 in
2031 Report.Report "UNFINISHED LIST" region [] $
2032 Code.toSnippet source surroundings (Just region)
2034 D.reflow $
2035 "I was expecting to see another list entry after that last comma:"
2037 D.stack
2038 [ D.reflow $
2039 "Trailing commas are not allowed in lists, so the fix may be to delete the comma?"
2040 , D.toSimpleNote
2041 "I recommend using the following format for lists that span multiple lines:"
2042 , D.indent 4 $ D.vcat $
2043 [ "[ \"Alice\""
2044 , ", \"Bob\""
2045 , ", \"Chuck\""
2046 , "]"
2048 , D.reflow $
2049 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
2050 \ This style can be jarring for people coming from C-like syntax, but folks generally\
2051 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
2055 _ ->
2056 toExprReport source (InNode NList startRow startCol context) expr row col
2058 ListEnd row col ->
2059 let
2060 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2061 region = toRegion row col
2062 in
2063 Report.Report "UNFINISHED LIST" region [] $
2064 Code.toSnippet source surroundings (Just region)
2066 D.reflow $
2067 "I am partway through parsing a list, but I got stuck here:"
2069 D.stack
2070 [ D.fillSep
2071 ["I","was","expecting","to","see","a","closing","square","bracket","before","this,"
2072 ,"so","try","adding","a",D.dullyellow "]","and","see","if","that","helps?"
2074 , D.toSimpleNote $
2075 "When I get stuck like this, it usually means that there is a missing parenthesis\
2076 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
2080 ListIndentOpen row col ->
2081 let
2082 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2083 region = toRegion row col
2084 in
2085 Report.Report "UNFINISHED LIST" region [] $
2086 Code.toSnippet source surroundings (Just region)
2088 D.reflow $
2089 "I cannot find the end of this list:"
2091 D.stack
2092 [ D.fillSep $
2093 ["You","could","change","it","to","something","like"
2094 ,D.dullyellow "[3,4,5]"
2095 ,"or","even","just"
2096 ,D.dullyellow "[]" <> "."
2097 ,"Anything","where","there","is","an","open","and","close","square","brace,"
2098 ,"and","where","the","elements","of","the","list","are","separated","by","commas."
2100 , D.toSimpleNote
2101 "I may be confused by indentation. For example, if you are trying to define\
2102 \ a list across multiple lines, I recommend using this format:"
2103 , D.indent 4 $ D.vcat $
2104 [ "[ \"Alice\""
2105 , ", \"Bob\""
2106 , ", \"Chuck\""
2107 , "]"
2109 , D.reflow $
2110 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
2111 \ This style can be jarring for people coming from C-like syntax, but folks generally\
2112 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
2116 ListIndentEnd row col ->
2117 let
2118 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2119 region = toRegion row col
2120 in
2121 Report.Report "UNFINISHED LIST" region [] $
2122 Code.toSnippet source surroundings (Just region)
2124 D.reflow $
2125 "I cannot find the end of this list:"
2127 D.stack
2128 [ D.fillSep $
2129 ["You","can","just","add","a","closing",D.dullyellow "]"
2130 ,"right","here,","and","I","will","be","all","set!"
2132 , D.toSimpleNote
2133 "I may be confused by indentation. For example, if you are trying to define\
2134 \ a list across multiple lines, I recommend using this format:"
2135 , D.indent 4 $ D.vcat $
2136 [ "[ \"Alice\""
2137 , ", \"Bob\""
2138 , ", \"Chuck\""
2139 , "]"
2141 , D.reflow $
2142 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
2143 \ This style can be jarring for people coming from C-like syntax, but folks generally\
2144 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
2148 ListIndentExpr row col ->
2149 let
2150 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2151 region = toRegion row col
2152 in
2153 Report.Report "UNFINISHED LIST" region [] $
2154 Code.toSnippet source surroundings (Just region)
2156 D.reflow $
2157 "I was expecting to see another list entry after this comma:"
2159 D.stack
2160 [ D.reflow $
2161 "Trailing commas are not allowed in lists, so the fix may be to delete the comma?"
2162 , D.toSimpleNote
2163 "I recommend using the following format for lists that span multiple lines:"
2164 , D.indent 4 $ D.vcat $
2165 [ "[ \"Alice\""
2166 , ", \"Bob\""
2167 , ", \"Chuck\""
2168 , "]"
2170 , D.reflow $
2171 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
2172 \ This style can be jarring for people coming from C-like syntax, but folks generally\
2173 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
2178toFuncReport :: Code.Source -> Context -> Func -> Row -> Col -> Report.Report
2179toFuncReport source context func startRow startCol =
2180 case func of
2181 FuncSpace space row col ->
2182 toSpaceReport source space row col
2184 FuncArg pattern row col ->
2185 error "TODO FuncArg" pattern row col
2187 FuncBody expr row col ->
2188 toExprReport source (InNode NFunc startRow startCol context) expr row col
2190 FuncArrow row col ->
2191 let
2192 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2193 region = toRegion row col
2194 in
2195 case Code.whatIsNext source row col of
2196 Code.Keyword keyword ->
2197 Report.Report "RESERVED WORD" region [] $
2198 Code.toSnippet source surroundings (Just region)
2200 D.reflow $
2201 "I was parsing an anonymous function, but I got stuck here:"
2203 D.reflow $
2204 "It looks like you are trying to use `" ++ keyword ++ "` as an argument, but\
2205 \ it is a reserved word in this language. Try using a different argument name!"
2208 _ ->
2209 Report.Report "UNFINISHED ANONYMOUS FUNCTION" region [] $
2210 Code.toSnippet source surroundings (Just region)
2212 D.reflow $
2213 "I just saw the beginning of an anonymous function, so I was expecting to see an arrow next:"
2215 D.fillSep $
2216 ["The","syntax","for","anonymous","functions","is"
2217 ,D.dullyellow "(\\x -> x + 1)"
2218 ,"so","I","am","missing","the","arrow","and","the","body","of","the","function."
2222 FuncIndentArg row col ->
2223 let
2224 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2225 region = toRegion row col
2226 in
2227 Report.Report "MISSING ARGUMENT" region [] $
2228 Code.toSnippet source surroundings (Just region)
2230 D.reflow $
2231 "I just saw the beginning of an anonymous function, so I was expecting to see an argument next:"
2233 D.stack
2234 [ D.fillSep
2235 ["Something","like",D.dullyellow"x","or",D.dullyellow "name" <> "."
2236 ,"Anything","that","starts","with","a","lower","case","letter!"
2238 , D.toSimpleNote $
2239 "The syntax for anonymous functions is (\\x -> x + 1) where the backslash\
2240 \ is meant to look a bit like a lambda if you squint. This visual pun seemed\
2241 \ like a better idea at the time!"
2245 FuncIndentArrow row col ->
2246 let
2247 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2248 region = toRegion row col
2249 in
2250 Report.Report "UNFINISHED ANONYMOUS FUNCTION" region [] $
2251 Code.toSnippet source surroundings (Just region)
2253 D.reflow $
2254 "I just saw the beginning of an anonymous function, so I was expecting to see an arrow next:"
2256 D.stack
2257 [ D.fillSep $
2258 ["The","syntax","for","anonymous","functions","is"
2259 ,D.dullyellow "(\\x -> x + 1)"
2260 ,"so","I","am","missing","the","arrow","and","the","body","of","the","function."
2262 , D.toSimpleNote $
2263 "It is possible that I am confused about indetation! I generally recommend\
2264 \ switching to named functions if the definition cannot fit inline nicely, so\
2265 \ either (1) try to fit the whole anonymous function on one line or (2) break\
2266 \ the whole thing out into a named function. Things tend to be clearer that way!"
2270 FuncIndentBody row col ->
2271 let
2272 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2273 region = toRegion row col
2274 in
2275 Report.Report "UNFINISHED ANONYMOUS FUNCTION" region [] $
2276 Code.toSnippet source surroundings (Just region)
2278 D.reflow $
2279 "I was expecting to see the body of your anonymous function next:"
2281 D.stack
2282 [ D.fillSep $
2283 ["The","syntax","for","anonymous","functions","is"
2284 ,D.dullyellow "(\\x -> x + 1)"
2285 ,"so","I","am","missing","all","the","stuff","after","the","arrow!"
2287 , D.toSimpleNote $
2288 "It is possible that I am confused about indetation! I generally recommend\
2289 \ switching to named functions if the definition cannot fit inline nicely, so\
2290 \ either (1) try to fit the whole anonymous function on one line or (2) break\
2291 \ the whole thing out into a named function. Things tend to be clearer that way!"
2299 case err of
2300 CommentOnNothing region ->
2301 Report.Report "STRAY COMMENT" region [] $
2302 Code.toSnippet source region Nothing
2304 "This documentation comment is not followed by anything."
2306 D.reflow $
2307 "All documentation comments need to be right above the declaration they\
2308 \ describe. Maybe some code got deleted or commented out by accident? Or\
2309 \ maybe this comment is here by accident?"
2312 UnexpectedPort region ->
2313 Report.Report "UNEXPECTED PORTS" region [] $
2314 Code.toSnippet source region Nothing
2316 D.reflow $
2317 "You are declaring ports in a normal module."
2319 D.stack
2320 [ D.fillSep
2321 ["Switch","this","to","say",D.green "port module","instead,"
2322 ,"marking","that","this","module","contains","port","declarations."
2324 , D.link "Note"
2325 "Ports are not a traditional FFI for calling JS functions directly. They need a different mindset! Read"
2326 "ports"
2327 "to learn the syntax and how to use it effectively."
2331 NoPorts region ->
2332 Report.Report "NO PORTS" region [] $
2333 Code.toSnippet source region Nothing
2335 D.reflow $
2336 "This module does not declare any ports, but it says it will:"
2338 D.fillSep
2339 ["Switch","this","to",D.green "module"
2340 ,"and","you","should","be","all","set!"
2344 ParseError row col context expectation ->
2345 let
2346 pos = A.Position row col
2347 region = A.Region pos pos
2348 in
2349 case expectation of
2351 DocComment ->
2352 Report.Report "EXPECTING DOC COMMENT" region [] $
2353 Code.toSnippet source region Nothing
2355 D.reflow $
2356 "I was expecting a doc comment here:"
2358 D.reflowLink
2359 "Check out" "TODO" "for examples of doc comments."
2362 -- Parse.Number
2364 Precedence ->
2365 Report.Report "EXPECTING PRECEDENCE" region [] $
2366 Code.toSnippet source region Nothing
2368 D.reflow $
2369 "I was expecting the precedence here:"
2371 D.reflow $
2372 "I need a single digit between 0 and 9 inclusive."
2375 Wildcard ->
2376 Report.Report "EXPECTING A WILDCARD" region [] $
2377 Code.toSnippet source region Nothing
2379 D.reflow $
2380 "I was expecting a _ here:"
2382 D.reflow $
2383 "An underscore indicates that “I do not care about this value” and is\
2384 \ called a wildcard pattern because it will match with any type of values."
2387 WildcardNotVar startCol endCol ->
2388 let
2389 badRegion =
2390 A.Region (A.Position row startCol) (A.Position row endCol)
2391 in
2392 Report.Report "INVALID PATTERN" badRegion [] $
2393 Code.toSnippet source badRegion Nothing
2395 D.reflow $
2396 "I was expecting to see an underscore without any additional characters:"
2398 D.reflow $
2399 "There are two options. Either (1) remove the extra characters and ignore the\
2400 \ value or (2) remove the starting underscore to give the value a normal name."
2403 -- Parse.Pattern
2405 FloatInPattern ->
2406 Report.Report "INVALID PATTERN" region [] $
2407 Code.toSnippet source region Nothing
2409 D.reflow $
2410 "I cannot pattern match with floating point numbers:"
2412 D.reflow $
2413 "Equality on floats can be unreliable, so you usually want to check that they\
2414 \ are nearby with some sort of (abs (actual - expected) < 0.001) check."
2417 -- Parse.Expression
2419 MatchingName name ->
2420 Report.Report "EXPECTING A DEFINITION" region [] $
2421 Code.toSnippet source region Nothing
2423 D.reflow $
2424 "I just saw the type annotation for `" ++ Name.toChars name
2425 ++ "` so I was expecting to see its definition here:"
2427 D.reflow $
2428 "Type annotations always appear directly above the relevant\
2429 \ definition, without anything else (even doc comments) in between."
2435 TypeWithBadDefinition region annName defName ->
2436 Report.Report "ANNOTATION MISMATCH" region [] $
2437 Code.toSnippet source region Nothing
2439 D.reflow $
2440 "I see a `" <> Name.toChars annName
2441 <> "` annotation, but it is followed by a `"
2442 <> Name.toChars defName <> "` definition."
2444 D.fillSep
2445 ["The","annotation","and","definition","names","must","match!"
2446 ,"Is","there","a","typo","between"
2447 , D.dullyellow (D.fromName annName)
2448 ,"and"
2449 , D.dullyellow (D.fromName defName) <> "?"