on fea0186 help sign in
5760 lines 210 kB history raw
1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
3module Reporting.Error.Syntax
4 ( Error(..)
5 , toReport
6 --
7 , Module(..)
8 , Exposing(..)
9 --
10 , Decl(..)
11 , DeclType(..)
12 , TypeAlias(..)
13 , CustomType(..)
14 , DeclDef(..)
15 , Port(..)
16 --
17 , Expr(..)
18 , Record(..)
19 , Tuple(..)
20 , List(..)
21 , Func(..)
22 , Case(..)
23 , If(..)
24 , Let(..)
25 , Def(..)
26 , Destruct(..)
27 --
28 , Pattern(..)
29 , PRecord(..)
30 , PTuple(..)
31 , PList(..)
32 --
33 , Type(..)
34 , TRecord(..)
35 , TTuple(..)
36 --
37 , Char(..)
38 , String(..)
39 , Escape(..)
40 , Number(..)
41 --
42 , Space(..)
43 , toSpaceReport
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 Parse.Symbol (BadOperator(..))
57import qualified Reporting.Annotation as A
58import qualified Reporting.Doc as D
59import qualified Reporting.Report as Report
60import qualified Reporting.Render.Code as Code
64-- ALL SYNTAX ERRORS
67data Error
68 = ModuleNameUnspecified ModuleName.Raw
69 | ModuleNameMismatch ModuleName.Raw (A.Located ModuleName.Raw)
70 | UnexpectedPort A.Region
71 | NoPorts A.Region
72 | NoPortsInPackage (A.Located Name.Name)
73 | NoPortModulesInPackage A.Region
74 | NoEffectsOutsideKernel A.Region
75 | ParseError Module
79-- MODULE
82data Module
83 = ModuleSpace Space Row Col
84 | ModuleBadEnd Row Col
85 --
86 | ModuleProblem Row Col
87 | ModuleName Row Col
88 | ModuleExposing Exposing Row Col
89 --
90 | PortModuleProblem Row Col
91 | PortModuleName Row Col
92 | PortModuleExposing Exposing Row Col
93 --
94 | Effect Row Col
95 --
96 | FreshLine Row Col
97 --
98 | ImportStart Row Col
99 | ImportName Row Col
100 | ImportAs Row Col
101 | ImportAlias Row Col
102 | ImportExposing Row Col
103 | ImportExposingList Exposing Row Col
104 | ImportEnd Row Col -- different based on col=1 or if greater
105 --
106 | ImportIndentName Row Col
107 | ImportIndentAlias Row Col
108 | ImportIndentExposingList Row Col
109 --
110 | Infix Row Col
111 --
112 | Declarations Decl Row Col
115data Exposing
116 = ExposingSpace Space Row Col
117 | ExposingStart Row Col
118 | ExposingValue Row Col
119 | ExposingOperator Row Col
120 | ExposingOperatorReserved BadOperator Row Col
121 | ExposingOperatorRightParen Row Col
122 | ExposingTypePrivacy Row Col
123 | ExposingEnd Row Col
124 --
125 | ExposingIndentEnd Row Col
126 | ExposingIndentValue Row Col
130-- DECLARATIONS
133data Decl
134 = DeclStart Row Col
135 | DeclSpace Space Row Col
136 --
137 | Port Port Row Col
138 | DeclType DeclType Row Col
139 | DeclDef Name.Name DeclDef Row Col
140 --
141 | DeclFreshLineAfterDocComment Row Col
144data DeclDef
145 = DeclDefSpace Space Row Col
146 | DeclDefEquals Row Col
147 | DeclDefType Type Row Col
148 | DeclDefArg Pattern Row Col
149 | DeclDefBody Expr Row Col
150 | DeclDefNameRepeat Row Col
151 | DeclDefNameMatch Name.Name Row Col
152 --
153 | DeclDefIndentType Row Col
154 | DeclDefIndentEquals Row Col
155 | DeclDefIndentBody Row Col
158data Port
159 = PortSpace Space Row Col
160 | PortName Row Col
161 | PortColon Row Col
162 | PortType Type Row Col
163 | PortIndentName Row Col
164 | PortIndentColon Row Col
165 | PortIndentType Row Col
169-- TYPE DECLARATIONS
172data DeclType
173 = DT_Space Space Row Col
174 | DT_Name Row Col
175 | DT_Alias TypeAlias Row Col
176 | DT_Union CustomType Row Col
177 --
178 | DT_IndentName Row Col
181data TypeAlias
182 = AliasSpace Space Row Col
183 | AliasName Row Col
184 | AliasEquals Row Col
185 | AliasBody Type Row Col
186 --
187 | AliasIndentEquals Row Col
188 | AliasIndentBody Row Col
191data CustomType
192 = CT_Space Space Row Col
193 | CT_Name Row Col
194 | CT_Equals Row Col
195 | CT_Bar Row Col
196 | CT_Variant Row Col
197 | CT_VariantArg Type Row Col
198 --
199 | CT_IndentEquals Row Col
200 | CT_IndentBar Row Col
201 | CT_IndentAfterBar Row Col
202 | CT_IndentAfterEquals Row Col
206-- EXPRESSIONS
209data Expr
210 = Let Let Row Col
211 | Case Case Row Col
212 | If If Row Col
213 | List List Row Col
214 | Record Record Row Col
215 | Tuple Tuple Row Col
216 | Func Func Row Col
217 --
218 | Dot Row Col
219 | Access Row Col
220 | OperatorRight Name.Name Row Col
221 | OperatorReserved BadOperator Row Col
222 --
223 | Start Row Col
224 | Char Char Row Col
225 | String String Row Col
226 | Number Number Row Col
227 | Space Space Row Col
228 | EndlessShader Row Col
229 | ShaderProblem [Char.Char] Row Col
230 | IndentOperatorRight Name.Name Row Col
233data Record
234 = RecordOpen Row Col
235 | RecordEnd Row Col
236 | RecordField Row Col
237 | RecordEquals Row Col
238 | RecordExpr Expr Row Col
239 | RecordSpace Space Row Col
240 --
241 | RecordIndentOpen Row Col
242 | RecordIndentEnd Row Col
243 | RecordIndentField Row Col
244 | RecordIndentEquals Row Col
245 | RecordIndentExpr Row Col
248data Tuple
249 = TupleExpr Expr Row Col
250 | TupleSpace Space Row Col
251 | TupleEnd Row Col
252 | TupleOperatorClose Row Col
253 | TupleOperatorReserved BadOperator Row Col
254 --
255 | TupleIndentExpr1 Row Col
256 | TupleIndentExprN Row Col
257 | TupleIndentEnd Row Col
260data List
261 = ListSpace Space Row Col
262 | ListOpen Row Col
263 | ListExpr Expr Row Col
264 | ListEnd Row Col
265 --
266 | ListIndentOpen Row Col
267 | ListIndentEnd Row Col
268 | ListIndentExpr Row Col
271data Func
272 = FuncSpace Space Row Col
273 | FuncArg Pattern Row Col
274 | FuncBody Expr Row Col
275 | FuncArrow Row Col
276 --
277 | FuncIndentArg Row Col
278 | FuncIndentArrow Row Col
279 | FuncIndentBody Row Col
282data Case
283 = CaseSpace Space Row Col
284 | CaseOf Row Col
285 | CasePattern Pattern Row Col
286 | CaseArrow Row Col
287 | CaseExpr Expr Row Col
288 | CaseBranch Expr Row Col
289 --
290 | CaseIndentOf Row Col
291 | CaseIndentExpr Row Col
292 | CaseIndentPattern Row Col
293 | CaseIndentArrow Row Col
294 | CaseIndentBranch Row Col
295 | CasePatternAlignment Word16 Row Col
298data If
299 = IfSpace Space Row Col
300 | IfThen Row Col
301 | IfElse Row Col
302 | IfElseBranchStart Row Col
303 --
304 | IfCondition Expr Row Col
305 | IfThenBranch Expr Row Col
306 | IfElseBranch Expr Row Col
307 --
308 | IfIndentCondition Row Col
309 | IfIndentThen Row Col
310 | IfIndentThenBranch Row Col
311 | IfIndentElseBranch Row Col
312 | IfIndentElse Row Col
315data Let
316 = LetSpace Space Row Col
317 | LetIn Row Col
318 | LetDefAlignment Word16 Row Col
319 | LetDefName Row Col
320 | LetDef Name.Name Def Row Col
321 | LetDestruct Destruct Row Col
322 | LetBody Expr Row Col
323 | LetIndentDef Row Col
324 | LetIndentIn Row Col
325 | LetIndentBody Row Col
328data Def
329 = DefSpace Space Row Col
330 | DefType Type Row Col
331 | DefNameRepeat Row Col
332 | DefNameMatch Name.Name Row Col
333 | DefArg Pattern Row Col
334 | DefEquals Row Col
335 | DefBody Expr Row Col
336 | DefIndentEquals Row Col
337 | DefIndentType Row Col
338 | DefIndentBody Row Col
339 | DefAlignment Word16 Row Col
342data Destruct
343 = DestructSpace Space Row Col
344 | DestructPattern Pattern Row Col
345 | DestructEquals Row Col
346 | DestructBody Expr Row Col
347 | DestructIndentEquals Row Col
348 | DestructIndentBody Row Col
352-- PATTERNS
355data Pattern
356 = PRecord PRecord Row Col
357 | PTuple PTuple Row Col
358 | PList PList Row Col
359 --
360 | PStart Row Col
361 | PChar Char Row Col
362 | PString String Row Col
363 | PNumber Number Row Col
364 | PFloat Word16 Row Col
365 | PAlias Row Col
366 | PWildcardNotVar Name.Name Int Row Col
367 | PSpace Space Row Col
368 --
369 | PIndentStart Row Col
370 | PIndentAlias Row Col
373data PRecord
374 = PRecordOpen Row Col
375 | PRecordEnd Row Col
376 | PRecordField Row Col
377 | PRecordSpace Space Row Col
378 --
379 | PRecordIndentOpen Row Col
380 | PRecordIndentEnd Row Col
381 | PRecordIndentField Row Col
384data PTuple
385 = PTupleOpen Row Col
386 | PTupleEnd Row Col
387 | PTupleExpr Pattern Row Col
388 | PTupleSpace Space Row Col
389 --
390 | PTupleIndentEnd Row Col
391 | PTupleIndentExpr1 Row Col
392 | PTupleIndentExprN Row Col
395data PList
396 = PListOpen Row Col
397 | PListEnd Row Col
398 | PListExpr Pattern Row Col
399 | PListSpace Space Row Col
400 --
401 | PListIndentOpen Row Col
402 | PListIndentEnd Row Col
403 | PListIndentExpr Row Col
407-- TYPES
410data Type
411 = TRecord TRecord Row Col
412 | TTuple TTuple Row Col
413 --
414 | TStart Row Col
415 | TSpace Space Row Col
416 --
417 | TIndentStart Row Col
420data TRecord
421 = TRecordOpen Row Col
422 | TRecordEnd Row Col
423 --
424 | TRecordField Row Col
425 | TRecordColon Row Col
426 | TRecordType Type Row Col
427 --
428 | TRecordSpace Space Row Col
429 --
430 | TRecordIndentOpen Row Col
431 | TRecordIndentField Row Col
432 | TRecordIndentColon Row Col
433 | TRecordIndentType Row Col
434 | TRecordIndentEnd Row Col
437data TTuple
438 = TTupleOpen Row Col
439 | TTupleEnd Row Col
440 | TTupleType Type Row Col
441 | TTupleSpace Space Row Col
442 --
443 | TTupleIndentType1 Row Col
444 | TTupleIndentTypeN Row Col
445 | TTupleIndentEnd Row Col
449-- LITERALS
452data Char
453 = CharEndless
454 | CharEscape Escape
455 | CharNotString Word16
458data String
459 = StringEndless_Single
460 | StringEndless_Multi
461 | StringEscape Escape
464data Escape
465 = EscapeUnknown
466 | BadUnicodeFormat Word16
467 | BadUnicodeCode Word16
468 | BadUnicodeLength Word16 Int Int
471data Number
472 = NumberEnd
473 | NumberDot Int
474 | NumberHexDigit
475 | NumberNoLeadingZero
479-- MISC
482data Space
483 = HasTab
484 | EndlessMultiComment
488-- TO REPORT
491toReport :: Code.Source -> Error -> Report.Report
492toReport source err =
493 case err of
494 ModuleNameUnspecified name ->
495 let
496 region = toRegion 1 1
497 in
498 Report.Report "MODULE NAME MISSING" region [] $
499 D.stack
500 [ D.reflow $
501 "I need the module name to be declared at the top of this file, like this:"
502 , D.indent 4 $ D.fillSep $
503 [ D.cyan "module", D.fromName name, D.cyan "exposing", "(..)" ]
504 , D.reflow $
505 "Try adding that as the first line of your file!"
506 , D.toSimpleNote $
507 "It is best to replace (..) with an explicit list of types and\
508 \ functions you want to expose. When you know a value is only used\
509 \ within this module, you can refactor without worrying about uses\
510 \ elsewhere. Limiting exposed values can also speed up compilation\
511 \ because I can skip a bunch of work if I see that the exposed API\
512 \ has not changed."
513 ]
515 ModuleNameMismatch expectedName (A.At region actualName) ->
516 Report.Report "MODULE NAME MISMATCH" region [ModuleName.toChars expectedName] $
517 Code.toSnippet source region Nothing
518 (
519 "It looks like this module name is out of sync:"
520 ,
521 D.stack
522 [ D.reflow $
523 "I need it to match the file path, so I was expecting to see `"
524 ++ ModuleName.toChars expectedName
525 ++ "` here. Make the following change, and you should be all set!"
526 , D.indent 4 $
527 D.dullyellow (D.fromName actualName) <> " -> " <> D.green (D.fromName expectedName)
528 , D.toSimpleNote $
529 "I require that module names correspond to file paths. This makes it much\
530 \ easier to explore unfamiliar codebases! So if you want to keep the current\
531 \ module name, try renaming the file instead."
532 ]
533 )
535 UnexpectedPort region ->
536 Report.Report "UNEXPECTED PORTS" region [] $
537 Code.toSnippet source region Nothing
538 (
539 D.reflow $
540 "You are declaring ports in a normal module."
541 ,
542 D.stack
543 [ D.fillSep
544 ["Switch","this","to","say",D.cyan "port module","instead,"
545 ,"marking","that","this","module","contains","port","declarations."
546 ]
547 , D.link "Note"
548 "Ports are not a traditional FFI for calling JS functions directly. They need a different mindset! Read"
549 "ports"
550 "to learn the syntax and how to use it effectively."
551 ]
552 )
554 NoPorts region ->
555 Report.Report "NO PORTS" region [] $
556 Code.toSnippet source region Nothing
557 (
558 D.reflow $
559 "This module does not declare any ports, but it says it will:"
560 ,
561 D.fillSep
562 ["Switch","this","to",D.cyan "module"
563 ,"and","you","should","be","all","set!"
564 ]
565 )
567 NoPortsInPackage (A.At region _) ->
568 Report.Report "PACKAGES CANNOT HAVE PORTS" region [] $
569 Code.toSnippet source region Nothing
570 (
571 D.reflow $
572 "Packages cannot declare any ports, so I am getting stuck here:"
573 ,
574 D.stack
575 [ D.reflow $
576 "Remove this port declaration."
577 , noteForPortsInPackage
578 ]
579 )
581 NoPortModulesInPackage region ->
582 Report.Report "PACKAGES CANNOT HAVE PORTS" region [] $
583 Code.toSnippet source region Nothing
584 (
585 D.reflow $
586 "Packages cannot declare any ports, so I am getting stuck here:"
587 ,
588 D.stack
589 [ D.fillSep $
590 ["Remove","the",D.cyan "port","keyword","and","I"
591 ,"should","be","able","to","continue."
592 ]
593 , noteForPortsInPackage
594 ]
595 )
597 NoEffectsOutsideKernel region ->
598 Report.Report "INVALID EFFECT MODULE" region [] $
599 Code.toSnippet source region Nothing
600 (
601 D.reflow $
602 "It is not possible to declare an `effect module` outside the @elm organization,\
603 \ so I am getting stuck here:"
604 ,
605 D.stack
606 [ D.reflow $
607 "Switch to a normal module declaration."
608 , D.toSimpleNote $
609 "Effect modules are designed to allow certain core functionality to be\
610 \ defined separately from the compiler. So the @elm organization has access to\
611 \ this so that certain changes, extensions, and fixes can be introduced without\
612 \ needing to release new Elm binaries. For example, we want to make it possible\
613 \ to test effects, but this may require changes to the design of effect modules.\
614 \ By only having them defined in the @elm organization, that kind of design work\
615 \ can proceed much more smoothly."
616 ]
617 )
619 ParseError modul ->
620 toParseErrorReport source modul
623noteForPortsInPackage :: D.Doc
624noteForPortsInPackage =
625 D.stack
626 [ D.toSimpleNote $
627 "One of the major goals of the package ecosystem is to be completely written\
628 \ in Elm. This means when you install an Elm package, you can be sure you are safe\
629 \ from security issues (like code that runs side-effects on install) and that you\
630 \ are not going to get any runtime exceptions coming from your new dependency.\
631 \ This design also sets the Elm ecosystem up well to target other platforms (like\
632 \ mobile phones, WebAssembly, etc.) since no community code explicitly depends on\
633 \ JavaScript even existing."
634 , D.reflow $
635 "Given that overall goal, allowing ports in packages would lead to some pretty\
636 \ surprising behavior. If ports were allowed in packages, you could install a\
637 \ package but not realize that it brings in an indirect dependency that defines a\
638 \ port. Now you have a program that does not work and the fix is to realize that\
639 \ some JavaScript needs to be added. That would be extremely frustrating! So why\
640 \ not allow the package author to include the necessary JS code as well? Now we\
641 \ are back in conflict with our goals for the ecosystem overall."
642 ]
645toParseErrorReport :: Code.Source -> Module -> Report.Report
646toParseErrorReport source modul =
647 case modul of
648 ModuleSpace space row col ->
649 toSpaceReport source space row col
651 ModuleBadEnd row col ->
652 case Code.whatIsNext source row col of
653 Code.Keyword keyword ->
654 let
655 region = toKeywordRegion row col keyword
656 in
657 Report.Report "RESERVED WORD" region [] $
658 Code.toSnippet source region Nothing
659 (
660 D.reflow $
661 "I got stuck on this reserved word:"
662 ,
663 D.reflow $
664 "The name `" ++ keyword ++ "` is reserved, so try using a different name?"
665 )
667 Code.Operator op ->
668 let
669 region = toKeywordRegion row col op
670 in
671 Report.Report "UNEXPECTED SYMBOL" region [] $
672 Code.toSnippet source region Nothing
673 (
674 D.reflow $
675 "I ran into an unexpected symbol:"
676 ,
677 D.reflow $
678 "I was not expecting to see a " ++ op ++ " here. Try deleting it? Maybe\
679 \ I can give a better hint from there?"
680 )
682 Code.Close term bracket ->
683 let
684 region = toRegion row col
685 in
686 Report.Report ("UNEXPECTED " ++ map Char.toUpper term) region [] $
687 Code.toSnippet source region Nothing
688 (
689 D.reflow $
690 "I ran into an unexpected " ++ term ++ ":"
691 ,
692 D.reflow $
693 "This " ++ bracket : " does not match up with an earlier open " ++ term ++ ". Try deleting it?"
694 )
696 Code.Other maybeChar ->
697 let
698 region = toRegion row col
699 in
700 case maybeChar of
701 Just ';' ->
702 Report.Report "UNEXPECTED SEMICOLON" region [] $
703 Code.toSnippet source region Nothing
704 (
705 D.reflow $
706 "I got stuck on this semicolon:"
707 ,
708 D.stack
709 [ D.reflow $ "Try removing it?"
710 , D.toSimpleNote $
711 "Some languages require semicolons at the end of each statement. These are\
712 \ often called C-like languages, and they usually share a lot of language design\
713 \ choices. (E.g. side-effects, for loops, etc.) Elm manages effects with commands\
714 \ and subscriptions instead, so there is no special syntax for \"statements\" and\
715 \ therefore no need to use semicolons to separate them. I think this will make\
716 \ more sense as you work through <https://guide.elm-lang.org> though!"
717 ]
718 )
720 Just ',' ->
721 Report.Report "UNEXPECTED COMMA" region [] $
722 Code.toSnippet source region Nothing
723 (
724 D.reflow $
725 "I got stuck on this comma:"
726 ,
727 D.stack
728 [ D.reflow $
729 "I do not think I am parsing a list or tuple right now. Try deleting the comma?"
730 , D.toSimpleNote $
731 "If this is supposed to be part of a list, the problem may be a bit earlier.\
732 \ Perhaps the opening [ is missing? Or perhaps some value in the list has an extra\
733 \ closing ] that is making me think the list ended earlier? The same kinds of\
734 \ things could be going wrong if this is supposed to be a tuple."
735 ]
736 )
738 Just '`' ->
739 Report.Report "UNEXPECTED CHARACTER" region [] $
740 Code.toSnippet source region Nothing
741 (
742 D.reflow $
743 "I got stuck on this character:"
744 ,
745 D.stack
746 [ D.reflow $
747 "It is not used for anything in Elm syntax. It is used for multi-line strings in\
748 \ some languages though, so if you want a string that spans multiple lines, you\
749 \ can use Elm's multi-line string syntax like this:"
750 , D.vcat
751 [ D.fillSep [D.green "markdown","=",D.dullyellow "\"\"\""]
752 , mempty
753 , D.dullyellow "# Multi-line Strings"
754 , mempty
755 , D.dullyellow "- start with triple double quotes"
756 , D.dullyellow "- write whatever you want"
757 , D.dullyellow "- no need to escape newlines or double quotes"
758 , D.dullyellow "- end with triple double quotes"
759 , mempty
760 , D.dullyellow "\"\"\""
761 ]
762 , D.reflow $
763 "Otherwise I do not know what is going on! Try removing the character?"
764 ]
765 )
767 Just '$' ->
768 Report.Report "UNEXPECTED SYMBOL" region [] $
769 Code.toSnippet source region Nothing
770 (
771 D.reflow $
772 "I got stuck on this dollar sign:"
773 ,
774 D.reflow $
775 "It is not used for anything in Elm syntax. Are you coming from a language where\
776 \ dollar signs can be used in variable names? If so, try a name that (1) starts\
777 \ with a letter and (2) only contains letters, numbers, and underscores."
778 )
780 Just c | elem c ['#','@','!','%','~'] ->
781 Report.Report "UNEXPECTED SYMBOL" region [] $
782 Code.toSnippet source region Nothing
783 (
784 D.reflow $
785 "I got stuck on this symbol:"
786 ,
787 D.reflow $
788 "It is not used for anything in Elm syntax. Try removing it?"
789 )
791 _ ->
792 Report.Report "SYNTAX PROBLEM" region [] $
793 Code.toSnippet source region Nothing
794 (
795 D.reflow $
796 "I got stuck here:"
797 ,
798 D.reflow $
799 "Whatever I am running into is confusing me a lot! Normally I can give fairly\
800 \ specific hints, but something is really tripping me up this time."
801 )
803 ModuleProblem row col ->
804 let
805 region = toRegion row col
806 in
807 Report.Report "UNFINISHED MODULE DECLARATION" region [] $
808 Code.toSnippet source region Nothing
809 (
810 D.reflow $
811 "I am parsing an `module` declaration, but I got stuck here:"
812 ,
813 D.stack
814 [ D.reflow $
815 "Here are some examples of valid `module` declarations:"
816 , D.indent 4 $ D.vcat $
817 [ D.fillSep [D.cyan "module","Main",D.cyan "exposing","(..)"]
818 , D.fillSep [D.cyan "module","Dict",D.cyan "exposing","(Dict, empty, get)"]
819 ]
820 , D.reflow $
821 "I generally recommend using an explicit exposing list. I can skip compiling a bunch\
822 \ of files when the public interface of a module stays the same, so exposing fewer\
823 \ values can help improve compile times!"
824 ]
825 )
827 ModuleName row col ->
828 let
829 region = toRegion row col
830 in
831 Report.Report "EXPECTING MODULE NAME" region [] $
832 Code.toSnippet source region Nothing
833 (
834 D.reflow $
835 "I was parsing an `module` declaration until I got stuck here:"
836 ,
837 D.stack
838 [ D.reflow $
839 "I was expecting to see the module name next, like in these examples:"
840 , D.indent 4 $ D.vcat $
841 [ D.fillSep [D.cyan "module","Dict",D.cyan "exposing","(..)"]
842 , D.fillSep [D.cyan "module","Maybe",D.cyan "exposing","(..)"]
843 , D.fillSep [D.cyan "module","Html.Attributes",D.cyan "exposing","(..)"]
844 , D.fillSep [D.cyan "module","Json.Decode",D.cyan "exposing","(..)"]
845 ]
846 , D.reflow $
847 "Notice that the module names all start with capital letters. That is required!"
848 ]
849 )
851 ModuleExposing exposing row col ->
852 toExposingReport source exposing row col
854 PortModuleProblem row col ->
855 let
856 region = toRegion row col
857 in
858 Report.Report "UNFINISHED PORT MODULE DECLARATION" region [] $
859 Code.toSnippet source region Nothing
860 (
861 D.reflow $
862 "I am parsing an `port module` declaration, but I got stuck here:"
863 ,
864 D.stack
865 [ D.reflow $
866 "Here are some examples of valid `port module` declarations:"
867 , D.indent 4 $ D.vcat $
868 [ D.fillSep [D.cyan "port",D.cyan "module","WebSockets",D.cyan "exposing","(send, listen, keepAlive)"]
869 , D.fillSep [D.cyan "port",D.cyan "module","Maps",D.cyan "exposing","(Location, goto)"]
870 ]
871 , D.link "Note" "Read" "ports" "for more help."
872 ]
873 )
875 PortModuleName row col ->
876 let
877 region = toRegion row col
878 in
879 Report.Report "EXPECTING MODULE NAME" region [] $
880 Code.toSnippet source region Nothing
881 (
882 D.reflow $
883 "I was parsing an `module` declaration until I got stuck here:"
884 ,
885 D.stack
886 [ D.reflow $
887 "I was expecting to see the module name next, like in these examples:"
888 , D.indent 4 $ D.vcat $
889 [ D.fillSep [D.cyan "port",D.cyan "module","WebSockets",D.cyan "exposing","(send, listen, keepAlive)"]
890 , D.fillSep [D.cyan "port",D.cyan "module","Maps",D.cyan "exposing","(Location, goto)"]
891 ]
892 , D.reflow $
893 "Notice that the module names start with capital letters. That is required!"
894 ]
895 )
897 PortModuleExposing exposing row col ->
898 toExposingReport source exposing row col
900 Effect row col ->
901 let
902 region = toRegion row col
903 in
904 Report.Report "BAD MODULE DECLARATION" region [] $
905 Code.toSnippet source region Nothing
906 (
907 D.reflow $
908 "I cannot parse this module declaration:"
909 ,
910 D.reflow $
911 "This type of module is reserved for the @elm organization. It is used to\
912 \ define certain effects, avoiding building them into the compiler."
913 )
915 FreshLine row col ->
916 let
917 region = toRegion row col
919 toBadFirstLineReport keyword =
920 Report.Report "TOO MUCH INDENTATION" region [] $
921 Code.toSnippet source region Nothing
922 (
923 D.reflow $
924 "This `" ++ keyword ++ "` should not have any spaces before it:"
925 ,
926 D.reflow $
927 "Delete the spaces before `" ++ keyword ++ "` until there are none left!"
928 )
930 in
931 case Code.whatIsNext source row col of
932 Code.Keyword "module" -> toBadFirstLineReport "module"
933 Code.Keyword "import" -> toBadFirstLineReport "import"
934 Code.Keyword "type" -> toBadFirstLineReport "type"
935 Code.Keyword "port" -> toBadFirstLineReport "port"
936 _ ->
937 Report.Report "SYNTAX PROBLEM" region [] $
938 Code.toSnippet source region Nothing
939 (
940 D.reflow $
941 "I got stuck here:"
942 ,
943 D.stack
944 [ D.reflow $
945 "I am not sure what is going on, but I recommend starting an Elm\
946 \ file with the following lines:"
947 , D.vcat
948 [ D.fillSep [D.cyan "import","Html"]
949 , ""
950 , D.fillSep [D.green "main","="]
951 , D.indent 2 $ D.fillSep [D.cyan "Html" <> ".text",D.dullyellow "\"Hello!\""]
952 ]
953 , D.reflow $
954 "You should be able to copy those lines directly into your file. Check out the\
955 \ examples at <https://elm-lang.org/examples> for more help getting started!"
956 , D.toSimpleNote $
957 "This can also happen when something is indented too much!"
958 ]
959 )
961 ImportStart row col ->
962 toImportReport source row col
964 ImportName row col ->
965 let
966 region = toRegion row col
967 in
968 Report.Report "EXPECTING IMPORT NAME" region [] $
969 Code.toSnippet source region Nothing
970 (
971 D.reflow $
972 "I was parsing an `import` until I got stuck here:"
973 ,
974 D.stack
975 [ D.reflow $
976 "I was expecting to see a module name next, like in these examples:"
977 , D.indent 4 $ D.vcat $
978 [ D.fillSep [D.cyan "import","Dict"]
979 , D.fillSep [D.cyan "import","Maybe"]
980 , D.fillSep [D.cyan "import","Html.Attributes"]
981 , D.fillSep [D.cyan "import","Json.Decode"]
982 ]
983 , D.reflow $
984 "Notice that the module names all start with capital letters. That is required!"
985 ]
986 )
988 ImportAs row col ->
989 toImportReport source row col
991 ImportAlias row col ->
992 let
993 region = toRegion row col
994 in
995 Report.Report "EXPECTING IMPORT ALIAS" region [] $
996 Code.toSnippet source region Nothing
997 (
998 D.reflow $
999 "I was parsing an `import` until I got stuck here:"
1001 D.stack
1002 [ D.reflow $
1003 "I was expecting to see an alias next, like in these examples:"
1004 , D.indent 4 $ D.vcat $
1005 [ D.fillSep [D.cyan "import","Html.Attributes",D.cyan "as","Attr"]
1006 , D.fillSep [D.cyan "import","WebGL.Texture",D.cyan "as","Texture"]
1007 , D.fillSep [D.cyan "import","Json.Decode",D.cyan "as","D"]
1009 , D.reflow $
1010 "Notice that the alias always starts with a capital letter. That is required!"
1014 ImportExposing row col ->
1015 toImportReport source row col
1017 ImportExposingList exposing row col ->
1018 toExposingReport source exposing row col
1020 ImportEnd row col ->
1021 toImportReport source row col
1023 ImportIndentName row col ->
1024 toImportReport source row col
1026 ImportIndentAlias row col ->
1027 toImportReport source row col
1029 ImportIndentExposingList row col ->
1030 let
1031 region = toRegion row col
1032 in
1033 Report.Report "UNFINISHED IMPORT" region [] $
1034 Code.toSnippet source region Nothing
1036 D.reflow $
1037 "I was parsing an `import` until I got stuck here:"
1039 D.stack
1040 [ D.reflow $
1041 "I was expecting to see the list of exposed values next. For example, here\
1042 \ are two ways to expose values from the `Html` module:"
1043 , D.indent 4 $ D.vcat $
1044 [ D.fillSep [D.cyan "import","Html",D.cyan "exposing","(..)"]
1045 , D.fillSep [D.cyan "import","Html",D.cyan "exposing","(Html, div, text)"]
1047 , D.reflow $
1048 "I generally recommend the second style. It is more explicit, making it\
1049 \ much easier to figure out where values are coming from in large projects!"
1053 Infix row col ->
1054 let
1055 region = toRegion row col
1056 in
1057 Report.Report "BAD INFIX" region [] $
1058 Code.toSnippet source region Nothing
1060 D.reflow $
1061 "Something went wrong in this infix operator declaration:"
1063 D.reflow $
1064 "This feature is used by the @elm organization to define the\
1065 \ languages built-in operators."
1068 Declarations decl _ _ ->
1069 toDeclarationsReport source decl
1073-- IMPORTS
1076toImportReport :: Code.Source -> Row -> Col -> Report.Report
1077toImportReport source row col =
1078 let
1079 region = toRegion row col
1080 in
1081 Report.Report "UNFINISHED IMPORT" region [] $
1082 Code.toSnippet source region Nothing
1084 D.reflow $
1085 "I am partway through parsing an import, but I got stuck here:"
1087 D.stack
1088 [ D.reflow $
1089 "Here are some examples of valid `import` declarations:"
1090 , D.indent 4 $ D.vcat $
1091 [ D.fillSep [D.cyan "import","Html"]
1092 , D.fillSep [D.cyan "import","Html",D.cyan "as","H"]
1093 , D.fillSep [D.cyan "import","Html",D.cyan "as","H",D.cyan "exposing","(..)"]
1094 , D.fillSep [D.cyan "import","Html",D.cyan "exposing","(Html, div, text)"]
1096 , D.reflow $
1097 "You are probably trying to import a different module, but try to make it look like one of these examples!"
1103-- EXPOSING
1106toExposingReport :: Code.Source -> Exposing -> Row -> Col -> Report.Report
1107toExposingReport source exposing startRow startCol =
1108 case exposing of
1109 ExposingSpace space row col ->
1110 toSpaceReport source space row col
1112 ExposingStart row col ->
1113 let
1114 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1115 region = toRegion row col
1116 in
1117 Report.Report "PROBLEM IN EXPOSING" region [] $
1118 Code.toSnippet source surroundings (Just region)
1120 D.reflow $
1121 "I want to parse exposed values, but I am getting stuck here:"
1123 D.stack
1124 [ D.fillSep $
1125 ["Exposed","values","are","always","surrounded","by","parentheses."
1126 ,"So","try","adding","a",D.green "(","here?"
1128 , D.toSimpleNote "Here are some valid examples of `exposing` for reference:"
1129 , D.indent 4 $ D.vcat $
1130 [ D.fillSep [D.cyan "import","Html",D.cyan "exposing","(..)"]
1131 , D.fillSep [D.cyan "import","Html",D.cyan "exposing","(Html, div, text)"]
1133 , D.reflow $
1134 "If you are getting tripped up, you can just expose everything for now. It should\
1135 \ get easier to make an explicit exposing list as you see more examples in the wild."
1139 ExposingValue row col ->
1140 case Code.whatIsNext source row col of
1141 Code.Keyword keyword ->
1142 let
1143 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1144 region = toKeywordRegion row col keyword
1145 in
1146 Report.Report "RESERVED WORD" region [] $
1147 Code.toSnippet source surroundings (Just region)
1149 D.reflow $
1150 "I got stuck on this reserved word:"
1152 D.reflow $
1153 "It looks like you are trying to expose `" ++ keyword ++ "` but that is a reserved word. Is there a typo?"
1156 Code.Operator op ->
1157 let
1158 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1159 region = toKeywordRegion row col op
1160 in
1161 Report.Report "UNEXPECTED SYMBOL" region [] $
1162 Code.toSnippet source surroundings (Just region)
1164 D.reflow $
1165 "I got stuck on this symbol:"
1167 D.stack
1168 [ D.reflow $
1169 "If you are trying to expose an operator, add parentheses around it like this:"
1170 , D.indent 4 $ D.dullyellow (D.fromChars op) <> " -> " <> D.green ("(" <> D.fromChars op <> ")")
1174 _ ->
1175 let
1176 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1177 region = toRegion row col
1178 in
1179 Report.Report "PROBLEM IN EXPOSING" region [] $
1180 Code.toSnippet source surroundings (Just region)
1182 D.reflow $
1183 "I got stuck while parsing these exposed values:"
1185 D.stack
1186 [ D.reflow $
1187 "I do not have an exact recommendation, so here are some valid examples\
1188 \ of `exposing` for reference:"
1189 , D.indent 4 $ D.vcat $
1190 [ D.fillSep [D.cyan "import","Html",D.cyan "exposing","(..)"]
1191 , D.fillSep [D.cyan "import","Basics",D.cyan "exposing","(Int, Float, Bool(..), (+), not, sqrt)"]
1193 , D.reflow $
1194 "These examples show how to expose types, variants, operators, and functions. Everything\
1195 \ should be some permutation of these examples, just with different names."
1199 ExposingOperator row col ->
1200 let
1201 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1202 region = toRegion row col
1203 in
1204 Report.Report "PROBLEM IN EXPOSING" region [] $
1205 Code.toSnippet source surroundings (Just region)
1207 D.reflow $
1208 "I just saw an open parenthesis, so I was expecting an operator next:"
1210 D.fillSep $
1211 ["It","is","possible","to","expose","operators,","so","I","was","expecting"
1212 ,"to","see","something","like",D.dullyellow "(+)","or",D.dullyellow "(|=)"
1213 ,"or",D.dullyellow "(||)","after","I","saw","that","open","parenthesis."
1217 ExposingOperatorReserved op row col ->
1218 let
1219 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1220 region = toRegion row col
1221 in
1222 Report.Report "RESERVED SYMBOL" region [] $
1223 Code.toSnippet source surroundings (Just region)
1225 D.reflow $
1226 "I cannot expose this as an operator:"
1228 case op of
1229 BadDot -> D.reflow "Try getting rid of this entry? Maybe I can give you a better hint after that?"
1230 BadPipe -> D.fillSep ["Maybe","you","want",D.dullyellow "(||)","instead?"]
1231 BadArrow -> D.reflow "Try getting rid of this entry? Maybe I can give you a better hint after that?"
1232 BadEquals -> D.fillSep ["Maybe","you","want",D.dullyellow "(==)","instead?"]
1233 BadHasType -> D.fillSep ["Maybe","you","want",D.dullyellow "(::)","instead?"]
1236 ExposingOperatorRightParen row col ->
1237 let
1238 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1239 region = toRegion row col
1240 in
1241 Report.Report "PROBLEM IN EXPOSING" region [] $
1242 Code.toSnippet source surroundings (Just region)
1244 D.reflow $
1245 "It looks like you are exposing an operator, but I got stuck here:"
1247 D.fillSep $
1248 ["I","was","expecting","to","see","the","closing","parenthesis","immediately"
1249 ,"after","the","operator.","Try","adding","a",D.green ")","right","here?"
1253 ExposingEnd row col ->
1254 let
1255 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1256 region = toRegion row col
1257 in
1258 Report.Report "UNFINISHED EXPOSING" region [] $
1259 Code.toSnippet source surroundings (Just region)
1261 D.reflow $
1262 "I was partway through parsing exposed values, but I got stuck here:"
1264 D.reflow $
1265 "Maybe there is a comma missing before this?"
1268 ExposingTypePrivacy row col ->
1269 let
1270 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1271 region = toRegion row col
1272 in
1273 Report.Report "PROBLEM EXPOSING CUSTOM TYPE VARIANTS" region [] $
1274 Code.toSnippet source surroundings (Just region)
1276 D.reflow $
1277 "It looks like you are trying to expose the variants of a custom type:"
1279 D.stack
1280 [ D.fillSep $
1281 ["You","need","to","write","something","like"
1282 ,D.dullyellow "Status(..)","or",D.dullyellow "Entity(..)"
1283 ,"though.","It","is","all","or","nothing,","otherwise","`case`"
1284 ,"expressions","could","miss","a","variant","and","crash!"
1286 , D.toSimpleNote $
1287 "It is often best to keep the variants hidden! If someone pattern matches on\
1288 \ the variants, it is a MAJOR change if any new variants are added. Suddenly\
1289 \ their `case` expressions do not cover all variants! So if you do not need\
1290 \ people to pattern match, keep the variants hidden and expose functions to\
1291 \ construct values of this type. This way you can add new variants as a MINOR change!"
1295 ExposingIndentEnd row col ->
1296 let
1297 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1298 region = toRegion row col
1299 in
1300 Report.Report "UNFINISHED EXPOSING" region [] $
1301 Code.toSnippet source surroundings (Just region)
1303 D.reflow $
1304 "I was partway through parsing exposed values, but I got stuck here:"
1306 D.stack
1307 [ D.fillSep $
1308 ["I","was","expecting","a","closing","parenthesis."
1309 ,"Try","adding","a",D.green ")","right","here?"
1311 , D.toSimpleNote $
1312 "I can get confused when there is not enough indentation, so if you already\
1313 \ have a closing parenthesis, it probably just needs some spaces in front of it."
1317 ExposingIndentValue row col ->
1318 let
1319 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1320 region = toRegion row col
1321 in
1322 Report.Report "UNFINISHED EXPOSING" region [] $
1323 Code.toSnippet source surroundings (Just region)
1325 D.reflow $
1326 "I was partway through parsing exposed values, but I got stuck here:"
1328 D.reflow $
1329 "I was expecting another value to expose."
1334-- SPACES
1337toSpaceReport :: Code.Source -> Space -> Row -> Col -> Report.Report
1338toSpaceReport source space row col =
1339 case space of
1340 HasTab ->
1341 let
1342 region = toRegion row col
1343 in
1344 Report.Report "NO TABS" region [] $
1345 Code.toSnippet source region Nothing
1347 D.reflow $
1348 "I ran into a tab, but tabs are not allowed in Elm files."
1350 D.reflow $
1351 "Replace the tab with spaces."
1354 EndlessMultiComment ->
1355 let
1356 region = toWiderRegion row col 2
1357 in
1358 Report.Report "ENDLESS COMMENT" region [] $
1359 Code.toSnippet source region Nothing
1361 D.reflow $
1362 "I cannot find the end of this multi-line comment:"
1364 D.stack -- "{-"
1365 [ D.reflow "Add a -} somewhere after this to end the comment."
1366 , D.toSimpleHint
1367 "Multi-line comments can be nested in Elm, so {- {- -} -} is a comment\
1368 \ that happens to contain another comment. Like parentheses and curly braces,\
1369 \ the start and end markers must always be balanced. Maybe that is the problem?"
1375-- DECLARATIONS
1378toRegion :: Row -> Col -> A.Region
1379toRegion row col =
1380 let
1381 pos = A.Position row col
1382 in
1383 A.Region pos pos
1386toWiderRegion :: Row -> Col -> Word16 -> A.Region
1387toWiderRegion row col extra =
1388 A.Region
1389 (A.Position row col)
1390 (A.Position row (col + extra))
1393toKeywordRegion :: Row -> Col -> [Char.Char] -> A.Region
1394toKeywordRegion row col keyword =
1395 A.Region
1396 (A.Position row col)
1397 (A.Position row (col + fromIntegral (length keyword)))
1400toDeclarationsReport :: Code.Source -> Decl -> Report.Report
1401toDeclarationsReport source decl =
1402 case decl of
1403 DeclStart row col ->
1404 case Code.whatIsNext source row col of
1405 Code.Close term bracket ->
1406 let
1407 region = toRegion row col
1408 in
1409 Report.Report ("STRAY " ++ map Char.toUpper term) region [] $
1410 Code.toSnippet source region Nothing
1412 D.reflow $
1413 "I was not expecting to see a " ++ term ++ " here:"
1414 , D.reflow $
1415 "This " ++ bracket : " does not match up with an earlier open " ++ term ++ ". Try deleting it?"
1418 Code.Keyword keyword ->
1419 let
1420 region = toKeywordRegion row col keyword
1421 in
1422 Report.Report "RESERVED WORD" region [] $
1423 Code.toSnippet source region Nothing
1425 D.reflow $
1426 "I was not expecting to run into the `" ++ keyword ++ "` keyword here:"
1428 case keyword of
1429 "import" ->
1430 D.reflow $
1431 "It is reserved for declaring imports at the top of your module. If you want\
1432 \ another import, try moving it up top with the other imports. If you want to\
1433 \ define a value or function, try changing the name to something else!"
1435 "case" ->
1436 D.stack
1437 [ D.reflow $
1438 "It is reserved for writing `case` expressions. Try using a different name?"
1439 , D.toSimpleNote $
1440 "If you are trying to write a `case` expression, it needs to be part of a\
1441 \ definition. So you could write something like this instead:"
1442 , D.vcat $
1443 [ D.indent 0 $ D.fillSep [D.green "getWidth","maybeWidth","="]
1444 , D.indent 2 $ D.fillSep [D.cyan "case","maybeWidth",D.cyan "of"]
1445 , D.indent 4 $ D.fillSep [D.blue "Just","width","->"]
1446 , D.indent 6 $ D.fillSep ["width","+",D.dullyellow "200"]
1447 , ""
1448 , D.indent 4 $ D.fillSep [D.blue "Nothing","->"]
1449 , D.indent 6 $ D.fillSep [D.dullyellow "400"]
1451 , D.reflow $
1452 "This defines a `getWidth` function that we can use elsewhere in our program."
1455 "if" ->
1456 D.stack
1457 [ D.reflow $
1458 "It is reserved for writing `if` expressions. Try using a different name?"
1459 , D.toSimpleNote $
1460 "If you are trying to write an `if` expression, it needs to be part of a\
1461 \ definition. So you could write something like this instead:"
1462 , D.vcat $
1463 [ D.indent 0 $ D.fillSep [D.green "reviewPowerLevel","powerLevel","="]
1464 , D.indent 2 $ D.fillSep $
1465 [D.cyan "if","powerLevel",">",D.dullyellow "9000"
1466 ,D.cyan "then",D.dullyellow "\"OVER 9000!!!\""
1467 ,D.cyan "else",D.dullyellow "\"not bad\""
1470 , D.reflow $
1471 "This defines a `reviewPowerLevel` function that we can use elsewhere in our program."
1474 _ ->
1475 D.reflow $
1476 "It is a reserved word. Try changing the name to something else?"
1479 _ ->
1480 let
1481 region = toRegion row col
1482 in
1483 Report.Report "SYNTAX PROBLEM" region [] $
1484 Code.toSnippet source region Nothing
1486 D.reflow $
1487 "I was expecting to see a declaration, but I am getting stuck here:"
1489 D.stack
1490 [ case Code.whatIsNext source row col of
1491 Code.Other (Just char) | Char.isUpper char ->
1492 D.reflow $
1493 "All declarations start with lower-case letters in Elm, so maybe this letter can\
1494 \ be changed to lower-case?"
1496 _ ->
1497 D.reflow $
1498 "Declarations normally start with a lower-case name or the `type` keyword."
1499 , D.toSimpleHint $
1500 "Here are a couple valid declarations for reference:"
1501 , D.vcat
1502 [ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
1503 , D.fillSep [D.green "add","x","y","="]
1504 , D.fillSep [" ","x","+","y"]
1506 , D.fillSep [D.cyan "type",D.green "User","=","Anonymous","|","LoggedIn String"]
1507 , D.reflow $
1508 "Notice that these declarations start with lower-case letters. Capitalization\
1509 \ makes a difference in Elm!"
1513 DeclSpace space row col ->
1514 toSpaceReport source space row col
1516 Port port_ row col ->
1517 toPortReport source port_ row col
1519 DeclType declType row col ->
1520 toDeclTypeReport source declType row col
1522 DeclDef name declDef row col ->
1523 toDeclDefReport source name declDef row col
1525 DeclFreshLineAfterDocComment row col ->
1526 let
1527 region = toRegion row col
1528 in
1529 Report.Report "EXPECTING DECLARATION" region [] $
1530 Code.toSnippet source region Nothing
1532 D.reflow $
1533 "I just saw a doc comment, but then I got stuck here:"
1535 D.reflow $
1536 "I was expecting to see the corresponding declaration next, starting on a fresh\
1537 \ line with no indentation."
1542-- PORT
1545toPortReport :: Code.Source -> Port -> Row -> Col -> Report.Report
1546toPortReport source port_ startRow startCol =
1547 case port_ of
1548 PortSpace space row col ->
1549 toSpaceReport source space row col
1551 PortName row col ->
1552 case Code.whatIsNext source row col of
1553 Code.Keyword keyword ->
1554 let
1555 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1556 region = toKeywordRegion row col keyword
1557 in
1558 Report.Report "RESERVED WORD" region [] $
1559 Code.toSnippet source surroundings (Just region)
1561 D.reflow $
1562 "I cannot handle ports with names like this:"
1564 D.reflow $
1565 "You are trying to make a port named `" ++ keyword
1566 ++ "` but that is a reserved word. Try using some other name?"
1569 _ ->
1570 let
1571 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1572 region = toRegion row col
1573 in
1574 Report.Report "PORT PROBLEM" region [] $
1575 Code.toSnippet source surroundings (Just region)
1577 D.reflow $
1578 "I just saw the start of a `port` declaration, but then I got stuck here:"
1580 D.stack
1581 [ D.fillSep
1582 ["I","was","expecting","to","see","a","name","like"
1583 ,D.dullyellow "send","or",D.dullyellow "receive","next."
1584 ,"Something","that","starts","with","a","lower-case","letter."
1586 , portNote
1590 PortColon row col ->
1591 let
1592 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1593 region = toRegion row col
1594 in
1595 Report.Report "PORT PROBLEM" region [] $
1596 Code.toSnippet source surroundings (Just region)
1598 D.reflow $
1599 "I just saw the start of a `port` declaration, but then I got stuck here:"
1601 D.stack
1602 [ D.reflow $
1603 "I was expecting to see a colon next. And then a type that tells me\
1604 \ what type of values are going to flow through."
1605 , portNote
1609 PortType tipe row col ->
1610 toTypeReport source TC_Port tipe row col
1612 PortIndentName row col ->
1613 let
1614 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1615 region = toRegion row col
1616 in
1617 Report.Report "UNFINISHED PORT" region [] $
1618 Code.toSnippet source surroundings (Just region)
1620 D.reflow $
1621 "I just saw the start of a `port` declaration, but then I got stuck here:"
1623 D.stack
1624 [ D.fillSep
1625 ["I","was","expecting","to","see","a","name","like"
1626 ,D.dullyellow "send","or",D.dullyellow "receive","next."
1627 ,"Something","that","starts","with","a","lower-case","letter."
1629 , portNote
1633 PortIndentColon row col ->
1634 let
1635 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1636 region = toRegion row col
1637 in
1638 Report.Report "UNFINISHED PORT" region [] $
1639 Code.toSnippet source surroundings (Just region)
1641 D.reflow $
1642 "I just saw the start of a `port` declaration, but then I got stuck here:"
1644 D.stack
1645 [ D.reflow $
1646 "I was expecting to see a colon next. And then a type that tells me\
1647 \ what type of values are going to flow through."
1648 , portNote
1652 PortIndentType row col ->
1653 let
1654 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1655 region = toRegion row col
1656 in
1657 Report.Report "UNFINISHED PORT" region [] $
1658 Code.toSnippet source surroundings (Just region)
1660 D.reflow $
1661 "I just saw the start of a `port` declaration, but then I got stuck here:"
1663 D.stack
1664 [ D.reflow $
1665 "I was expecting to see a type next. Here are examples of outgoing and\
1666 \ incoming ports for reference:"
1667 , D.vcat
1668 [ D.fillSep [D.cyan "port","send",":","String -> Cmd msg"]
1669 , D.fillSep [D.cyan "port","receive",":","(String -> msg) -> Sub msg"]
1671 , D.reflow $
1672 "The first line defines a `send` port so you can send strings out to JavaScript.\
1673 \ Maybe you send them on a WebSocket or put them into IndexedDB. The second line\
1674 \ defines a `receive` port so you can receive strings from JavaScript. Maybe you\
1675 \ get receive messages when new WebSocket messages come in or when an entry in\
1676 \ IndexedDB changes for some external reason."
1681portNote :: D.Doc
1682portNote =
1683 D.stack
1684 [ D.toSimpleNote $
1685 "Here are some example `port` declarations for reference:"
1686 , D.vcat
1687 [ D.fillSep [D.cyan "port","send",":","String -> Cmd msg"]
1688 , D.fillSep [D.cyan "port","receive",":","(String -> msg) -> Sub msg"]
1690 , D.reflow $
1691 "The first line defines a `send` port so you can send strings out to JavaScript.\
1692 \ Maybe you send them on a WebSocket or put them into IndexedDB. The second line\
1693 \ defines a `receive` port so you can receive strings from JavaScript. Maybe you\
1694 \ get receive messages when new WebSocket messages come in or when the IndexedDB\
1695 \ is changed for some external reason."
1700-- DECL TYPE
1703toDeclTypeReport :: Code.Source -> DeclType -> Row -> Col -> Report.Report
1704toDeclTypeReport source declType startRow startCol =
1705 case declType of
1706 DT_Space space row col ->
1707 toSpaceReport source space row col
1709 DT_Name row col ->
1710 let
1711 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1712 region = toRegion row col
1713 in
1714 Report.Report "EXPECTING TYPE NAME" region [] $
1715 Code.toSnippet source surroundings (Just region)
1717 D.reflow $
1718 "I think I am parsing a type declaration, but I got stuck here:"
1720 D.stack
1721 [ D.fillSep $
1722 ["I","was","expecting","a","name","like",D.dullyellow "Status","or",D.dullyellow "Style"
1723 ,"next.","Just","make","sure","it","is","a","name","that","starts","with","a","capital","letter!"
1725 , customTypeNote
1729 DT_Alias typeAlias row col ->
1730 toTypeAliasReport source typeAlias row col
1732 DT_Union customType row col ->
1733 toCustomTypeReport source customType row col
1735 DT_IndentName row col ->
1736 let
1737 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1738 region = toRegion row col
1739 in
1740 Report.Report "EXPECTING TYPE NAME" region [] $
1741 Code.toSnippet source surroundings (Just region)
1743 D.reflow $
1744 "I think I am parsing a type declaration, but I got stuck here:"
1746 D.stack
1747 [ D.fillSep $
1748 ["I","was","expecting","a","name","like",D.dullyellow "Status","or",D.dullyellow "Style"
1749 ,"next.","Just","make","sure","it","is","a","name","that","starts","with","a","capital","letter!"
1751 , customTypeNote
1756toTypeAliasReport :: Code.Source -> TypeAlias -> Row -> Col -> Report.Report
1757toTypeAliasReport source typeAlias startRow startCol =
1758 case typeAlias of
1759 AliasSpace space row col ->
1760 toSpaceReport source space row col
1762 AliasName 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 "EXPECTING TYPE ALIAS NAME" region [] $
1768 Code.toSnippet source surroundings (Just region)
1770 D.reflow $
1771 "I am partway through parsing a type alias, but I got stuck here:"
1773 D.stack
1774 [ D.fillSep $
1775 ["I","was","expecting","a","name","like",D.dullyellow "Person","or",D.dullyellow "Point"
1776 ,"next.","Just","make","sure","it","is","a","name","that","starts","with","a","capital","letter!"
1778 , typeAliasNote
1782 AliasEquals row col ->
1783 case Code.whatIsNext source row col of
1784 Code.Keyword keyword ->
1785 let
1786 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1787 region = toKeywordRegion row col keyword
1788 in
1789 Report.Report "RESERVED WORD" region [] $
1790 Code.toSnippet source surroundings (Just region)
1792 D.reflow $
1793 "I ran into a reserved word unexpectedly while parsing this type alias:"
1795 D.stack
1796 [ D.reflow $
1797 "It looks like you are trying use `" ++ keyword
1798 ++ "` as a type variable, but it is a reserved word. Try using a different name?"
1799 , typeAliasNote
1803 _ ->
1804 let
1805 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1806 region = toRegion row col
1807 in
1808 Report.Report "PROBLEM IN TYPE ALIAS" region [] $
1809 Code.toSnippet source surroundings (Just region)
1811 D.reflow $
1812 "I am partway through parsing a type alias, but I got stuck here:"
1814 D.stack
1815 [ D.reflow $
1816 "I was expecting to see a type variable or an equals sign next."
1817 , typeAliasNote
1821 AliasBody tipe row col ->
1822 toTypeReport source TC_TypeAlias tipe row col
1824 AliasIndentEquals row col ->
1825 let
1826 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1827 region = toRegion row col
1828 in
1829 Report.Report "UNFINISHED TYPE ALIAS" region [] $
1830 Code.toSnippet source surroundings (Just region)
1832 D.reflow $
1833 "I am partway through parsing a type alias, but I got stuck here:"
1835 D.stack
1836 [ D.reflow $
1837 "I was expecting to see a type variable or an equals sign next."
1838 , typeAliasNote
1842 AliasIndentBody row col ->
1843 let
1844 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1845 region = toRegion row col
1846 in
1847 Report.Report "UNFINISHED TYPE ALIAS" region [] $
1848 Code.toSnippet source surroundings (Just region)
1850 D.reflow $
1851 "I am partway through parsing a type alias, but I got stuck here:"
1853 D.stack
1854 [ D.fillSep $
1855 ["I","was","expecting","to","see","a","type","next.","Something","as","simple"
1856 ,"as",D.dullyellow "Int","or",D.dullyellow "Float","would","work!"
1858 , typeAliasNote
1863typeAliasNote :: D.Doc
1864typeAliasNote =
1865 D.stack
1866 [ D.toSimpleNote $
1867 "Here is an example of a valid `type alias` for reference:"
1868 , D.vcat $
1869 [ D.indent 0 $ D.fillSep [D.cyan "type",D.cyan "alias",D.green "Person","="]
1870 , D.indent 2 $ D.vcat $
1871 ["{ name : String"
1872 ,", age : Int"
1873 ,", height : Float"
1874 ,"}"
1877 , D.reflow $
1878 "This would let us use `Person` as a shorthand for that record type. Using this\
1879 \ shorthand makes type annotations much easier to read, and makes changing code\
1880 \ easier if you decide later that there is more to a person than age and height!"
1884toCustomTypeReport :: Code.Source -> CustomType -> Row -> Col -> Report.Report
1885toCustomTypeReport source customType startRow startCol =
1886 case customType of
1887 CT_Space space row col ->
1888 toSpaceReport source space row col
1890 CT_Name row col ->
1891 let
1892 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1893 region = toRegion row col
1894 in
1895 Report.Report "EXPECTING TYPE NAME" region [] $
1896 Code.toSnippet source surroundings (Just region)
1898 D.reflow $
1899 "I think I am parsing a type declaration, but I got stuck here:"
1901 D.stack
1902 [ D.fillSep $
1903 ["I","was","expecting","a","name","like",D.dullyellow "Status","or",D.dullyellow "Style"
1904 ,"next.","Just","make","sure","it","is","a","name","that","starts","with","a","capital","letter!"
1906 , customTypeNote
1910 CT_Equals row col ->
1911 case Code.whatIsNext source row col of
1912 Code.Keyword keyword ->
1913 let
1914 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1915 region = toKeywordRegion row col keyword
1916 in
1917 Report.Report "RESERVED WORD" region [] $
1918 Code.toSnippet source surroundings (Just region)
1920 D.reflow $
1921 "I ran into a reserved word unexpectedly while parsing this custom type:"
1923 D.stack
1924 [ D.reflow $
1925 "It looks like you are trying use `" ++ keyword
1926 ++ "` as a type variable, but it is a reserved word. Try using a different name?"
1927 , customTypeNote
1931 _ ->
1932 let
1933 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1934 region = toRegion row col
1935 in
1936 Report.Report "PROBLEM IN CUSTOM TYPE" region [] $
1937 Code.toSnippet source surroundings (Just region)
1939 D.reflow $
1940 "I am partway through parsing a custom type, but I got stuck here:"
1942 D.stack
1943 [ D.reflow $
1944 "I was expecting to see a type variable or an equals sign next."
1945 , customTypeNote
1949 CT_Bar row col ->
1950 let
1951 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1952 region = toRegion row col
1953 in
1954 Report.Report "PROBLEM IN CUSTOM TYPE" region [] $
1955 Code.toSnippet source surroundings (Just region)
1957 D.reflow $
1958 "I am partway through parsing a custom type, but I got stuck here:"
1960 D.stack
1961 [ D.reflow $
1962 "I was expecting to see a vertical bar like | next."
1963 , customTypeNote
1967 CT_Variant row col ->
1968 let
1969 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1970 region = toRegion row col
1971 in
1972 Report.Report "PROBLEM IN CUSTOM TYPE" region [] $
1973 Code.toSnippet source surroundings (Just region)
1975 D.reflow $
1976 "I am partway through parsing a custom type, but I got stuck here:"
1978 D.stack
1979 [ D.fillSep $
1980 ["I","was","expecting","to","see","a","variant","name","next."
1981 ,"Something","like",D.dullyellow "Success","or",D.dullyellow "Sandwich" <> "."
1982 ,"Any","name","that","starts","with","a","capital","letter","really!"
1984 , customTypeNote
1988 CT_VariantArg tipe row col ->
1989 toTypeReport source TC_CustomType tipe row col
1991 CT_IndentEquals row col ->
1992 let
1993 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1994 region = toRegion row col
1995 in
1996 Report.Report "UNFINISHED CUSTOM TYPE" region [] $
1997 Code.toSnippet source surroundings (Just region)
1999 D.reflow $
2000 "I am partway through parsing a custom type, but I got stuck here:"
2002 D.stack
2003 [ D.reflow $
2004 "I was expecting to see a type variable or an equals sign next."
2005 , customTypeNote
2009 CT_IndentBar row col ->
2010 let
2011 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2012 region = toRegion row col
2013 in
2014 Report.Report "UNFINISHED CUSTOM TYPE" region [] $
2015 Code.toSnippet source surroundings (Just region)
2017 D.reflow $
2018 "I am partway through parsing a custom type, but I got stuck here:"
2020 D.stack
2021 [ D.reflow $
2022 "I was expecting to see a vertical bar like | next."
2023 , customTypeNote
2027 CT_IndentAfterBar row col ->
2028 let
2029 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2030 region = toRegion row col
2031 in
2032 Report.Report "UNFINISHED CUSTOM TYPE" region [] $
2033 Code.toSnippet source surroundings (Just region)
2035 D.reflow $
2036 "I am partway through parsing a custom type, but I got stuck here:"
2038 D.stack
2039 [ D.reflow $
2040 "I just saw a vertical bar, so I was expecting to see another variant defined next."
2041 , customTypeNote
2045 CT_IndentAfterEquals row col ->
2046 let
2047 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2048 region = toRegion row col
2049 in
2050 Report.Report "UNFINISHED CUSTOM TYPE" region [] $
2051 Code.toSnippet source surroundings (Just region)
2053 D.reflow $
2054 "I am partway through parsing a custom type, but I got stuck here:"
2056 D.stack
2057 [ D.reflow $
2058 "I just saw an equals sign, so I was expecting to see the first variant defined next."
2059 , customTypeNote
2064customTypeNote :: D.Doc
2065customTypeNote =
2066 D.stack
2067 [ D.toSimpleNote $
2068 "Here is an example of a valid `type` declaration for reference:"
2069 , D.vcat $
2070 [ D.indent 0 $ D.fillSep [D.cyan "type",D.green "Status"]
2071 , D.indent 2 $ D.fillSep ["=","Failure"]
2072 , D.indent 2 $ D.fillSep ["|","Waiting"]
2073 , D.indent 2 $ D.fillSep ["|","Success","String"]
2075 , D.reflow $
2076 "This defines a new `Status` type with three variants. This could be useful if\
2077 \ we are waiting for an HTTP request. Maybe we start with `Waiting` and then\
2078 \ switch to `Failure` or `Success \"message from server\"` depending on how\
2079 \ things go. Notice that the Success variant has some associated data, allowing\
2080 \ us to store a String if the request goes well!"
2085-- DECL DEF
2088toDeclDefReport :: Code.Source -> Name.Name -> DeclDef -> Row -> Col -> Report.Report
2089toDeclDefReport source name declDef startRow startCol =
2090 case declDef of
2091 DeclDefSpace space row col ->
2092 toSpaceReport source space row col
2094 DeclDefEquals row col ->
2095 case Code.whatIsNext source row col of
2096 Code.Keyword keyword ->
2097 let
2098 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2099 region = toKeywordRegion row col keyword
2100 in
2101 Report.Report "RESERVED WORD" region [] $
2102 Code.toSnippet source surroundings (Just region)
2104 D.fillSep
2105 ["The","name"
2106 ,"`" <> D.cyan (D.fromChars keyword) <> "`"
2107 ,"is","reserved","in","Elm,","so","it","cannot"
2108 ,"be","used","as","an","argument","here:"
2111 D.stack
2112 [ D.reflow $
2113 "Try renaming it to something else."
2114 , case keyword of
2115 "as" ->
2116 D.toFancyNote
2117 ["This","keyword","is","reserved","for","pattern","matches","like"
2118 ,"((x,y)",D.cyan "as","point)","where","you","want","to","name","a","tuple","and"
2119 ,"the","values","it","contains."
2122 _ ->
2123 D.toSimpleNote $
2124 "The `" ++ keyword ++ "` keyword has a special meaning in Elm, so it can only be used in certain situations."
2128 Code.Operator "->" ->
2129 let
2130 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2131 region = toWiderRegion row col 2
2132 in
2133 Report.Report "MISSING COLON?" region [] $
2134 Code.toSnippet source surroundings (Just region)
2136 D.reflow $
2137 "I was not expecting to see an arrow here:"
2139 D.stack
2140 [ D.fillSep
2141 ["This","usually","means","a",D.green ":","is","missing","a","bit","earlier","in"
2142 ,"a","type","annotation.","It","could","be","something","else","though,","so"
2143 ,"here","is","a","valid","definition","for","reference:"
2145 , D.vcat
2146 [ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
2147 , D.fillSep [D.green "add","x","y","="]
2148 , D.fillSep [" ","x","+","y"]
2150 , D.reflow $
2151 "Try to use that format with your `" ++ Name.toChars name ++ "` definition!"
2155 Code.Operator op ->
2156 let
2157 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2158 region = toKeywordRegion row col op
2159 in
2160 Report.Report "UNEXPECTED SYMBOL" region [] $
2161 Code.toSnippet source surroundings (Just region)
2163 D.reflow $
2164 "I was not expecting to see this symbol here:"
2166 D.stack
2167 [ D.reflow $
2168 "I am not sure what is going wrong exactly, so here is a valid\
2169 \ definition (with an optional type annotation) for reference:"
2170 , D.vcat
2171 [ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
2172 , D.fillSep [D.green "add","x","y","="]
2173 , D.fillSep [" ","x","+","y"]
2175 , D.reflow $
2176 "Try to use that format with your `" ++ Name.toChars name ++ "` definition!"
2180 _ ->
2181 let
2182 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2183 region = toRegion row col
2184 in
2185 Report.Report "PROBLEM IN DEFINITION" region [] $
2186 Code.toSnippet source surroundings (Just region)
2188 D.reflow $
2189 "I got stuck while parsing the `" ++ Name.toChars name ++ "` definition:"
2191 D.stack
2192 [ D.reflow $
2193 "I am not sure what is going wrong exactly, so here is a valid\
2194 \ definition (with an optional type annotation) for reference:"
2195 , D.vcat
2196 [ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
2197 , D.fillSep [D.green "add","x","y","="]
2198 , D.fillSep [" ","x","+","y"]
2200 , D.reflow $
2201 "Try to use that format!"
2205 DeclDefType tipe row col ->
2206 toTypeReport source (TC_Annotation name) tipe row col
2208 DeclDefArg pattern row col ->
2209 toPatternReport source PArg pattern row col
2211 DeclDefBody expr row col ->
2212 toExprReport source (InDef name startRow startCol) expr row col
2214 DeclDefNameRepeat row col ->
2215 let
2216 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2217 region = toRegion row col
2218 in
2219 Report.Report "EXPECTING DEFINITION" region [] $
2220 Code.toSnippet source surroundings (Just region)
2222 D.reflow $
2223 "I just saw the type annotation for `" ++ Name.toChars name
2224 ++ "` so I was expecting to see its definition here:"
2226 D.stack
2227 [ D.reflow $
2228 "Type annotations always appear directly above the relevant\
2229 \ definition, without anything else in between. (Not even doc comments!)"
2230 , declDefNote
2234 DeclDefNameMatch defName row col ->
2235 let
2236 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2237 region = toRegion row col
2238 in
2239 Report.Report "NAME MISMATCH" region [] $
2240 Code.toSnippet source surroundings (Just region)
2242 D.reflow $
2243 "I just saw a type annotation for `" ++ Name.toChars name ++ "`, but it is followed by a definition for `" ++ Name.toChars defName ++ "`:"
2245 D.stack
2246 [ D.reflow $
2247 "These names do not match! Is there a typo?"
2248 , D.indent 4 $ D.fillSep $
2249 [D.dullyellow (D.fromName defName),"->",D.green (D.fromName name)]
2253 DeclDefIndentType row col ->
2254 let
2255 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2256 region = toRegion row col
2257 in
2258 Report.Report "UNFINISHED DEFINITION" region [] $
2259 Code.toSnippet source surroundings (Just region)
2261 D.reflow $
2262 "I got stuck while parsing the `" ++ Name.toChars name ++ "` type annotation:"
2264 D.stack
2265 [ D.reflow $
2266 "I just saw a colon, so I am expecting to see a type next."
2267 , declDefNote
2271 DeclDefIndentEquals row col ->
2272 let
2273 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2274 region = toRegion row col
2275 in
2276 Report.Report "UNFINISHED DEFINITION" region [] $
2277 Code.toSnippet source surroundings (Just region)
2279 D.reflow $
2280 "I got stuck while parsing the `" ++ Name.toChars name ++ "` definition:"
2282 D.stack
2283 [ D.reflow $
2284 "I was expecting to see an argument or an equals sign next."
2285 , declDefNote
2289 DeclDefIndentBody row col ->
2290 let
2291 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2292 region = toRegion row col
2293 in
2294 Report.Report "UNFINISHED DEFINITION" region [] $
2295 Code.toSnippet source surroundings (Just region)
2297 D.reflow $
2298 "I got stuck while parsing the `" ++ Name.toChars name ++ "` definition:"
2300 D.stack
2301 [ D.reflow $
2302 "I was expecting to see an expression next. What is it equal to?"
2303 , declDefNote
2308declDefNote :: D.Doc
2309declDefNote =
2310 D.stack
2311 [ D.reflow $
2312 "Here is a valid definition (with a type annotation) for reference:"
2313 , D.vcat
2314 [ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
2315 , D.fillSep [D.green "add","x","y","="]
2316 , D.fillSep [" ","x","+","y"]
2318 , D.reflow $
2319 "The top line (called a \"type annotation\") is optional. You can leave it off\
2320 \ if you want. As you get more comfortable with Elm and as your project grows,\
2321 \ it becomes more and more valuable to add them though! They work great as\
2322 \ compiler-verified documentation, and they often improve error messages!"
2327-- CONTEXT
2330data Context
2331 = InNode Node Row Col Context
2332 | InDef Name.Name Row Col
2333 | InDestruct Row Col
2336data Node
2337 = NRecord
2338 | NParens
2339 | NList
2340 | NFunc
2341 | NCond
2342 | NThen
2343 | NElse
2344 | NCase
2345 | NBranch
2346 deriving (Eq)
2349getDefName :: Context -> Maybe Name.Name
2350getDefName context =
2351 case context of
2352 InDestruct _ _ -> Nothing
2353 InDef name _ _ -> Just name
2354 InNode _ _ _ c -> getDefName c
2357isWithin :: Node -> Context -> Bool
2358isWithin desiredNode context =
2359 case context of
2360 InDestruct _ _ -> False
2361 InDef _ _ _ -> False
2362 InNode actualNode _ _ _ -> desiredNode == actualNode
2366-- EXPR REPORTS
2369toExprReport :: Code.Source -> Context -> Expr -> Row -> Col -> Report.Report
2370toExprReport source context expr startRow startCol =
2371 case expr of
2372 Let let_ row col ->
2373 toLetReport source context let_ row col
2375 Case case_ row col ->
2376 toCaseReport source context case_ row col
2378 If if_ row col ->
2379 toIfReport source context if_ row col
2381 List list row col ->
2382 toListReport source context list row col
2384 Record record row col ->
2385 toRecordReport source context record row col
2387 Tuple tuple row col ->
2388 toTupleReport source context tuple row col
2390 Func func row col ->
2391 toFuncReport source context func row col
2393 Dot row col ->
2394 let region = toRegion row col in
2395 Report.Report "EXPECTING RECORD ACCESSOR" region [] $
2396 Code.toSnippet source region Nothing
2398 D.reflow $
2399 "I was expecting to see a record accessor here:"
2401 D.fillSep
2402 ["Something","like",D.dullyellow".name","or",D.dullyellow".price"
2403 ,"that","accesses","a","value","from","a","record."
2407 Access row col ->
2408 let region = toRegion row col in
2409 Report.Report "EXPECTING RECORD ACCESSOR" region [] $
2410 Code.toSnippet source region Nothing
2412 D.reflow $
2413 "I am trying to parse a record accessor here:"
2415 D.stack
2417 D.fillSep
2418 ["Something","like",D.dullyellow".name","or",D.dullyellow".price"
2419 ,"that","accesses","a","value","from","a","record."
2422 D.toSimpleNote $
2423 "Record field names must start with a lower case letter!"
2427 OperatorRight op row col ->
2428 let
2429 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2430 region = toRegion row col
2431 isMath = elem op ["-","+","*","/","^"]
2432 in
2433 Report.Report "MISSING EXPRESSION" region [] $
2434 Code.toSnippet source surroundings (Just region)
2436 D.reflow $
2437 "I just saw a " ++ Name.toChars op ++ " "
2438 ++ (if isMath then "sign" else "operator")
2439 ++ ", so I am getting stuck here:"
2441 if isMath then
2442 D.fillSep
2443 ["I","was","expecting","to","see","an","expression","next."
2444 ,"Something","like",D.dullyellow "42","or",D.dullyellow "1000"
2445 ,"that","makes","sense","with","a",D.fromName op,"sign."
2447 else if op == "&&" || op == "||" then
2448 D.fillSep
2449 ["I","was","expecting","to","see","an","expression","next."
2450 ,"Something","like",D.dullyellow "True","or",D.dullyellow "False"
2451 ,"that","makes","sense","with","boolean","logic."
2453 else if op == "|>" then
2454 D.reflow $
2455 "I was expecting to see a function next."
2456 else if op == "<|" then
2457 D.reflow $
2458 "I was expecting to see an argument next."
2459 else
2460 D.reflow $
2461 "I was expecting to see an expression next."
2464 OperatorReserved operator row col ->
2465 toOperatorReport source context operator row col
2467 Start row col ->
2468 let
2469 (contextRow, contextCol, aThing) =
2470 case context of
2471 InDestruct r c -> (r, c, "a definition")
2472 InDef name r c -> (r, c, "the `" ++ Name.toChars name ++ "` definition")
2473 InNode NRecord r c _ -> (r, c, "a record")
2474 InNode NParens r c _ -> (r, c, "some parentheses")
2475 InNode NList r c _ -> (r, c, "a list")
2476 InNode NFunc r c _ -> (r, c, "an anonymous function")
2477 InNode NCond r c _ -> (r, c, "an `if` expression")
2478 InNode NThen r c _ -> (r, c, "an `if` expression")
2479 InNode NElse r c _ -> (r, c, "an `if` expression")
2480 InNode NCase r c _ -> (r, c, "a `case` expression")
2481 InNode NBranch r c _ -> (r, c, "a `case` expression")
2483 surroundings = A.Region (A.Position contextRow contextCol) (A.Position row col)
2484 region = toRegion row col
2485 in
2486 Report.Report "MISSING EXPRESSION" region [] $
2487 Code.toSnippet source surroundings (Just region)
2489 D.reflow $
2490 "I am partway through parsing " ++ aThing ++ ", but I got stuck here:"
2492 D.stack
2493 [ D.fillSep $
2494 ["I","was","expecting","to","see","an","expression","like"
2495 ,D.dullyellow "42","or",D.dullyellow"\"hello\"" <> "."
2496 ,"Once","there","is","something","there,","I","can","probably"
2497 ,"give","a","more","specific","hint!"
2499 , D.toSimpleNote $
2500 "This can also happen if run into reserved words like `let` or `as` unexpectedly.\
2501 \ Or if I run into operators in unexpected spots. Point is, there are a\
2502 \ couple ways I can get confused and give sort of weird advice!"
2506 Char char row col ->
2507 toCharReport source char row col
2509 String string row col ->
2510 toStringReport source string row col
2512 Number number row col ->
2513 toNumberReport source number row col
2515 Space space row col ->
2516 toSpaceReport source space row col
2518 EndlessShader row col ->
2519 let
2520 region = toWiderRegion row col 6
2521 in
2522 Report.Report "ENDLESS SHADER" region [] $
2523 Code.toSnippet source region Nothing
2525 D.reflow "I cannot find the end of this shader:"
2527 D.reflow "Add a |] somewhere after this to end the shader."
2530 ShaderProblem problem row col ->
2531 let
2532 region = toRegion row col
2533 in
2534 Report.Report "SHADER PROBLEM" region [] $
2535 Code.toSnippet source region Nothing
2537 D.reflow $
2538 "I ran into a problem while parsing this GLSL block."
2540 D.stack
2541 [ D.reflow $
2542 "I use a 3rd party GLSL parser for now, and I did my best to extract their error message:"
2543 , D.indent 4 $ D.vcat $
2544 map D.fromChars (filter (/="") (lines problem))
2548 IndentOperatorRight op row col ->
2549 let
2550 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2551 region = toRegion row col
2552 in
2553 Report.Report "MISSING EXPRESSION" region [] $
2554 Code.toSnippet source surroundings (Just region)
2556 D.reflow $
2557 "I was expecting to see an expression after this " ++ Name.toChars op ++ " operator:"
2559 D.stack
2561 D.fillSep $
2562 ["You","can","just","put","anything","for","now,","like"
2563 ,D.dullyellow "42","or",D.dullyellow"\"hello\"" <> "."
2564 ,"Once","there","is","something","there,","I","can","probably"
2565 ,"give","a","more","specific","hint!"
2568 D.toSimpleNote $
2569 "I may be getting confused by your indentation? The easiest way to make sure\
2570 \ this is not an indentation problem is to put the expression on the right of\
2571 \ the " ++ Name.toChars op ++ " operator on the same line."
2577-- CHAR
2580toCharReport :: Code.Source -> Char -> Row -> Col -> Report.Report
2581toCharReport source char row col =
2582 case char of
2583 CharEndless ->
2584 let
2585 region = toRegion row col
2586 in
2587 Report.Report "MISSING SINGLE QUOTE" region [] $
2588 Code.toSnippet source region Nothing
2590 D.reflow $
2591 "I thought I was parsing a character, but I got to the end of\
2592 \ the line without seeing the closing single quote:"
2594 D.reflow $
2595 "Add a closing single quote here!"
2598 CharEscape escape ->
2599 toEscapeReport source escape row col
2601 CharNotString width ->
2602 let
2603 region = toWiderRegion row col width
2604 in
2605 Report.Report "NEEDS DOUBLE QUOTES" region [] $
2606 Code.toSnippet source region Nothing
2608 "The following string uses single quotes:"
2610 D.stack
2611 [ "Please switch to double quotes instead:"
2612 , D.indent 4 $
2613 D.dullyellow "'this'" <> " => " <> D.green "\"this\""
2614 , D.toSimpleNote $
2615 "Elm uses double quotes for strings like \"hello\", whereas it uses single\
2616 \ quotes for individual characters like 'a' and 'ø'. This distinction helps with\
2617 \ code like (String.any (\\c -> c == 'X') \"90210\") where you are inspecting\
2618 \ individual characters."
2624-- STRING
2627toStringReport :: Code.Source -> String -> Row -> Col -> Report.Report
2628toStringReport source string row col =
2629 case string of
2630 StringEndless_Single ->
2631 let
2632 region = toRegion row col
2633 in
2634 Report.Report "ENDLESS STRING" region [] $
2635 Code.toSnippet source region Nothing
2637 D.reflow $
2638 "I got to the end of the line without seeing the closing double quote:"
2640 D.stack
2641 [ D.fillSep $
2642 ["Strings","look","like",D.green "\"this\"","with","double"
2643 ,"quotes","on","each","end.","Is","the","closing","double"
2644 ,"quote","missing","in","your","code?"
2646 , D.toSimpleNote $
2647 "For a string that spans multiple lines, you can use the multi-line string\
2648 \ syntax like this:"
2649 , D.vcat
2650 [ D.fillSep [D.green "markdown","=",D.dullyellow "\"\"\""]
2651 , mempty
2652 , D.dullyellow "# Multi-line Strings"
2653 , mempty
2654 , D.dullyellow "- start with triple double quotes"
2655 , D.dullyellow "- write whatever you want"
2656 , D.dullyellow "- no need to escape newlines or double quotes"
2657 , D.dullyellow "- end with triple double quotes"
2658 , mempty
2659 , D.dullyellow "\"\"\""
2664 StringEndless_Multi ->
2665 let
2666 region = toWiderRegion row col 3
2667 in
2668 Report.Report "ENDLESS STRING" region [] $
2669 Code.toSnippet source region Nothing
2671 D.reflow $
2672 "I cannot find the end of this multi-line string:"
2674 D.stack
2675 [ D.reflow "Add a \"\"\" somewhere after this to end the string."
2676 , D.toSimpleNote $
2677 "Here is a valid multi-line string for reference:"
2678 , D.vcat
2679 [ D.fillSep [D.green "markdown","=",D.dullyellow "\"\"\""]
2680 , mempty
2681 , D.dullyellow "# Multi-line Strings"
2682 , mempty
2683 , D.dullyellow "- start with triple double quotes"
2684 , D.dullyellow "- write whatever you want"
2685 , D.dullyellow "- no need to escape newlines or double quotes"
2686 , D.dullyellow "- end with triple double quotes"
2687 , mempty
2688 , D.dullyellow "\"\"\""
2693 StringEscape escape ->
2694 toEscapeReport source escape row col
2698-- ESCAPES
2701toEscapeReport :: Code.Source -> Escape -> Row -> Col -> Report.Report
2702toEscapeReport source escape row col =
2703 case escape of
2704 EscapeUnknown ->
2705 let
2706 region = toWiderRegion row col 2
2707 in
2708 Report.Report "UNKNOWN ESCAPE" region [] $
2709 Code.toSnippet source region Nothing
2711 D.reflow $
2712 "Backslashes always start escaped characters, but I do not recognize this one:"
2714 D.stack
2715 [ D.reflow $
2716 "Valid escape characters include:"
2717 , D.dullyellow $ D.indent 4 $ D.vcat $
2718 [ "\\n"
2719 , "\\r"
2720 , "\\t"
2721 , "\\\""
2722 , "\\\'"
2723 , "\\\\"
2724 , "\\u{003D}"
2726 , D.reflow $
2727 "Do you want one of those instead? Maybe you need \\\\ to escape a backslash?"
2728 , D.toSimpleNote $
2729 "The last style lets encode ANY character by its Unicode code\
2730 \ point. That means \\u{0009} and \\t are the same. You can use\
2731 \ that style for anything not covered by the other six escapes!"
2735 BadUnicodeFormat width ->
2736 let
2737 region = toWiderRegion row col width
2738 in
2739 Report.Report "BAD UNICODE ESCAPE" region [] $
2740 Code.toSnippet source region Nothing
2742 D.reflow $
2743 "I ran into an invalid Unicode escape:"
2745 D.stack
2746 [ D.reflow $
2747 "Here are some examples of valid Unicode escapes:"
2748 , D.dullyellow $ D.indent 4 $ D.vcat $
2749 [ "\\u{0041}"
2750 , "\\u{03BB}"
2751 , "\\u{6728}"
2752 , "\\u{1F60A}"
2754 , D.reflow $
2755 "Notice that the code point is always surrounded by curly braces.\
2756 \ Maybe you are missing the opening or closing curly brace?"
2759 BadUnicodeCode width ->
2760 let
2761 region = toWiderRegion row col width
2762 in
2763 Report.Report "BAD UNICODE ESCAPE" region [] $
2764 Code.toSnippet source region Nothing
2766 D.reflow $
2767 "This is not a valid code point:"
2769 D.reflow $
2770 "The valid code points are between 0 and 10FFFF inclusive."
2773 BadUnicodeLength width numDigits badCode ->
2774 let
2775 region = toWiderRegion row col width
2776 in
2777 Report.Report "BAD UNICODE ESCAPE" region [] $
2778 Code.toSnippet source region Nothing $
2779 if numDigits < 4 then
2781 D.reflow $
2782 "Every code point needs at least four digits:"
2784 let
2785 goodCode = replicate (4 - numDigits) '0' ++ map Char.toUpper (showHex badCode "")
2786 suggestion = "\\u{" <> D.fromChars goodCode <> "}"
2787 in
2788 D.fillSep ["Try",D.green suggestion,"instead?"]
2791 else
2793 D.reflow $
2794 "This code point has too many digits:"
2796 D.fillSep $
2797 ["Valid","code","points","are","between"
2798 ,D.green "\\u{0000}","and",D.green "\\u{10FFFF}" <> ","
2799 ,"so","try","trimming","any","leading","zeros","until"
2800 ,"you","have","between","four","and","six","digits."
2806-- NUMBERS
2809toNumberReport :: Code.Source -> Number -> Row -> Col -> Report.Report
2810toNumberReport source number row col =
2811 let
2812 region = toRegion row col
2813 in
2814 case number of
2815 NumberEnd ->
2816 Report.Report "WEIRD NUMBER" region [] $
2817 Code.toSnippet source region Nothing
2819 D.reflow $
2820 "I thought I was reading a number, but I ran into some weird stuff here:"
2822 D.stack
2823 [ D.reflow $
2824 "I recognize numbers in the following formats:"
2825 , D.indent 4 $ D.vcat [ "42", "3.14", "6.022e23", "0x002B" ]
2826 , D.reflow $
2827 "So is there a way to write it like one of those?"
2831 NumberDot int ->
2832 Report.Report "WEIRD NUMBER" region [] $
2833 Code.toSnippet source region Nothing
2835 D.reflow $
2836 "Numbers cannot end with a dot like this:"
2838 D.fillSep
2839 ["Switching","to",D.green (D.fromChars (show int))
2840 ,"or",D.green (D.fromChars (show int ++ ".0"))
2841 ,"will","work","though!"
2845 NumberHexDigit ->
2846 Report.Report "WEIRD HEXIDECIMAL" region [] $
2847 Code.toSnippet source region Nothing
2849 D.reflow $
2850 "I thought I was reading a hexidecimal number until I got here:"
2852 D.stack
2853 [ D.reflow $
2854 "Valid hexidecimal digits include 0123456789abcdefABCDEF, so I can\
2855 \ only recognize things like this:"
2856 , D.indent 4 $ D.vcat [ "0x2B", "0x002B", "0x00ffb3" ]
2860 NumberNoLeadingZero ->
2861 Report.Report "LEADING ZEROS" region [] $
2862 Code.toSnippet source region Nothing
2864 D.reflow $
2865 "I do not accept numbers with leading zeros:"
2867 D.stack
2868 [ D.reflow $
2869 "Just delete the leading zeros and it should work!"
2870 , D.toSimpleNote $
2871 "Some languages let you to specify octal numbers by adding a leading zero.\
2872 \ So in C, writing 0111 is the same as writing 73. Some people are used to\
2873 \ that, but others probably want it to equal 111. Either path is going to\
2874 \ surprise people from certain backgrounds, so Elm tries to avoid this whole\
2875 \ situation."
2881-- OPERATORS
2884toOperatorReport :: Code.Source -> Context -> BadOperator -> Row -> Col -> Report.Report
2885toOperatorReport source context operator row col =
2886 case operator of
2887 BadDot ->
2888 let
2889 region = toRegion row col
2890 in
2891 Report.Report "UNEXPECTED SYMBOL" region [] $
2892 Code.toSnippet source region Nothing
2894 "I was not expecting this dot:"
2896 D.reflow $
2897 "Dots are for record access and decimal points, so\
2898 \ they cannot float around on their own. Maybe\
2899 \ there is some extra whitespace?"
2902 BadPipe ->
2903 let
2904 region = toRegion row col
2905 in
2906 Report.Report "UNEXPECTED SYMBOL" region [] $
2907 Code.toSnippet source region Nothing
2909 D.reflow $
2910 "I was not expecting this vertical bar:"
2912 D.reflow $
2913 "Vertical bars should only appear in custom type declarations. Maybe you want || instead?"
2916 BadArrow ->
2917 let
2918 region = toWiderRegion row col 2
2919 in
2920 Report.Report "UNEXPECTED ARROW" region [] $
2921 Code.toSnippet source region Nothing $
2922 if isWithin NCase context then
2924 D.reflow $
2925 "I am parsing a `case` expression right now, but this arrow is confusing me:"
2927 D.stack
2928 [ D.reflow "Maybe the `of` keyword is missing on a previous line?"
2929 , noteForCaseError
2933 else if isWithin NBranch context then
2935 D.reflow $
2936 "I am parsing a `case` expression right now, but this arrow is confusing me:"
2938 D.stack
2939 [ D.reflow $
2940 "It makes sense to see arrows around here, so I suspect it is something earlier. Maybe this pattern is indented a bit farther than the previous patterns?"
2941 , noteForCaseIndentError
2945 else
2947 D.reflow $
2948 "I was partway through parsing an expression when I got stuck on this arrow:"
2950 D.stack
2951 [ "Arrows should only appear in `case` expressions and anonymous functions.\n\
2952 \Maybe it was supposed to be a > sign instead?"
2953 , D.toSimpleNote $
2954 "The syntax for anonymous functions is (\\x -> x + 1) so the arguments all appear\
2955 \ after the backslash and before the arrow. Maybe a backslash is missing earlier?"
2959 BadEquals ->
2960 let
2961 region = toRegion row col
2962 in
2963 Report.Report "UNEXPECTED EQUALS" region [] $
2964 Code.toSnippet source region Nothing
2966 D.reflow $
2967 "I was not expecting to see this equals sign:"
2969 D.stack
2971 D.reflow "Maybe you want == instead? To check if two values are equal?"
2973 D.toSimpleNote $
2974 if isWithin NRecord context then
2975 "Records look like { x = 3, y = 4 } with the equals sign right\
2976 \ after the field name. So maybe you forgot a comma?"
2977 else
2978 case getDefName context of
2979 Nothing ->
2980 "I may be getting confused by your indentation. I need all definitions to be indented\
2981 \ exactly the same amount, so if this is meant to be a new definition, it may have too\
2982 \ many spaces in front of it."
2984 Just name ->
2985 "I may be getting confused by your indentation. I think I am still parsing the `"
2986 ++ Name.toChars name ++ "` definition. Is this supposed to be part of a definition\
2987 \ after that? If so, the problem may be a bit before the equals sign. I need all\
2988 \ definitions to be indented exactly the same amount, so the problem may be that\
2989 \ this new definition has too many spaces in front of it."
2993 BadHasType ->
2994 let
2995 region = toRegion row col
2996 in
2997 Report.Report "UNEXPECTED SYMBOL" region [] $
2998 Code.toSnippet source region Nothing $
3000 D.reflow $
3001 "I was not expecting to run into the \"has type\" symbol here:"
3003 case getDefName context of
3004 Nothing ->
3005 D.fillSep
3006 ["Maybe","you","want",D.green "::","instead?"
3007 ,"To","put","something","on","the","front","of","a","list?"
3010 Just name ->
3011 D.stack
3013 D.fillSep
3014 ["Maybe","you","want",D.green "::","instead?"
3015 ,"To","put","something","on","the","front","of","a","list?"
3017 , D.toSimpleNote $
3018 "The single colon is reserved for type annotations and record types, but I think\
3019 \ I am parsing the definition of `" ++ Name.toChars name ++ "` right now."
3021 D.toSimpleNote $
3022 "I may be getting confused by your indentation. Is this supposed to be part of\
3023 \ a type annotation AFTER the `" ++ Name.toChars name ++ "` definition? If so,\
3024 \ the problem may be a bit before the \"has type\" symbol. I need all definitions to\
3025 \ be exactly aligned (with exactly the same indentation) so the problem may be that\
3026 \ this new definition is indented a bit too much."
3032-- CASE
3035toLetReport :: Code.Source -> Context -> Let -> Row -> Col -> Report.Report
3036toLetReport source context let_ startRow startCol =
3037 case let_ of
3038 LetSpace space row col ->
3039 toSpaceReport source space row col
3041 LetIn row col ->
3042 let
3043 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3044 region = toRegion row col
3045 in
3046 Report.Report "LET PROBLEM" region [] $
3047 Code.toSnippet source surroundings (Just region)
3049 D.reflow $
3050 "I was partway through parsing a `let` expression, but I got stuck here:"
3052 D.stack
3053 [ D.fillSep $
3054 ["Based","on","the","indentation,","I","was","expecting","to","see","the",D.cyan "in"
3055 ,"keyword","next.","Is","there","a","typo?"
3057 , D.toSimpleNote $
3058 "This can also happen if you are trying to define another value within the `let` but\
3059 \ it is not indented enough. Make sure each definition has exactly the same amount of\
3060 \ spaces before it. They should line up exactly!"
3064 LetDefAlignment _ row col ->
3065 let
3066 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3067 region = toRegion row col
3068 in
3069 Report.Report "LET PROBLEM" region [] $
3070 Code.toSnippet source surroundings (Just region)
3072 D.reflow $
3073 "I was partway through parsing a `let` expression, but I got stuck here:"
3075 D.stack
3076 [ D.fillSep $
3077 ["Based","on","the","indentation,","I","was","expecting","to","see","the",D.cyan "in"
3078 ,"keyword","next.","Is","there","a","typo?"
3080 , D.toSimpleNote $
3081 "This can also happen if you are trying to define another value within the `let` but\
3082 \ it is not indented enough. Make sure each definition has exactly the same amount of\
3083 \ spaces before it. They should line up exactly!"
3087 LetDefName row col ->
3088 case Code.whatIsNext source row col of
3089 Code.Keyword keyword ->
3090 let
3091 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3092 region = toKeywordRegion row col keyword
3093 in
3094 Report.Report "RESERVED WORD" region [] $
3095 Code.toSnippet source surroundings (Just region)
3097 D.reflow $
3098 "I was partway through parsing a `let` expression, but I got stuck here:"
3100 D.reflow $
3101 "It looks like you are trying to use `" ++ keyword ++ "` as a variable name, but\
3102 \ it is a reserved word! Try using a different name instead."
3105 _ ->
3106 toUnfinishLetReport source row col startRow startCol $
3107 D.reflow $
3108 "I was expecting the name of a definition next."
3110 LetDef name def row col ->
3111 toLetDefReport source name def row col
3113 LetDestruct destruct row col ->
3114 toLetDestructReport source destruct row col
3116 LetBody expr row col ->
3117 toExprReport source context expr row col
3119 LetIndentDef row col ->
3120 toUnfinishLetReport source row col startRow startCol $
3121 D.reflow $
3122 "I was expecting a value to be defined here."
3124 LetIndentIn row col ->
3125 toUnfinishLetReport source row col startRow startCol $
3126 D.fillSep $
3127 ["I","was","expecting","to","see","the",D.cyan "in","keyword","next."
3128 ,"Or","maybe","more","of","that","expression?"
3131 LetIndentBody row col ->
3132 toUnfinishLetReport source row col startRow startCol $
3133 D.reflow $
3134 "I was expecting an expression next. Tell me what should happen with the value you just defined!"
3137toUnfinishLetReport :: Code.Source -> Row -> Col -> Row -> Col -> D.Doc -> Report.Report
3138toUnfinishLetReport source row col startRow startCol message =
3139 let
3140 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3141 region = toRegion row col
3142 in
3143 Report.Report "UNFINISHED LET" region [] $
3144 Code.toSnippet source surroundings (Just region)
3146 D.reflow $
3147 "I was partway through parsing a `let` expression, but I got stuck here:"
3149 D.stack
3150 [ message
3151 , D.toSimpleNote $
3152 "Here is an example with a valid `let` expression for reference:"
3153 , D.vcat $
3154 [ D.indent 0 $ D.fillSep [D.green "viewPerson","person","="]
3155 , D.indent 2 $ D.fillSep [D.cyan "let"]
3156 , D.indent 4 $ D.fillSep ["fullName","="]
3157 , D.indent 6 $ D.fillSep ["person.firstName","++",D.dullyellow "\" \"","++","person.lastName"]
3158 , D.indent 2 $ D.fillSep [D.cyan "in"]
3159 , D.indent 2 $ D.fillSep ["div","[]","[","text","fullName","]"]
3161 , D.reflow $
3162 "Here we defined a `viewPerson` function that turns a person into some HTML. We use\
3163 \ a `let` expression to define the `fullName` we want to show. Notice the indentation! The\
3164 \ `fullName` is indented more than the `let` keyword, and the actual value of `fullName` is\
3165 \ indented a bit more than that. That is important!"
3170toLetDefReport :: Code.Source -> Name.Name -> Def -> Row -> Col -> Report.Report
3171toLetDefReport source name def startRow startCol =
3172 case def of
3173 DefSpace space row col ->
3174 toSpaceReport source space row col
3176 DefType tipe row col ->
3177 toTypeReport source (TC_Annotation name) tipe row col
3179 DefNameRepeat row col ->
3180 let
3181 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3182 region = toRegion row col
3183 in
3184 Report.Report "EXPECTING DEFINITION" region [] $
3185 Code.toSnippet source surroundings (Just region)
3187 D.reflow $
3188 "I just saw the type annotation for `" ++ Name.toChars name
3189 ++ "` so I was expecting to see its definition here:"
3191 D.stack
3192 [ D.reflow $
3193 "Type annotations always appear directly above the relevant\
3194 \ definition, without anything else in between."
3195 , defNote
3199 DefNameMatch defName row col ->
3200 let
3201 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3202 region = toRegion row col
3203 in
3204 Report.Report "NAME MISMATCH" region [] $
3205 Code.toSnippet source surroundings (Just region)
3207 D.reflow $
3208 "I just saw a type annotation for `" ++ Name.toChars name ++ "`, but it is followed by a definition for `" ++ Name.toChars defName ++ "`:"
3210 D.stack
3211 [ D.reflow $
3212 "These names do not match! Is there a typo?"
3213 , D.indent 4 $ D.fillSep $
3214 [D.dullyellow (D.fromName defName),"->",D.green (D.fromName name)]
3218 DefArg pattern row col ->
3219 toPatternReport source PArg pattern row col
3221 DefEquals row col ->
3222 case Code.whatIsNext source row col of
3223 Code.Keyword keyword ->
3224 let
3225 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3226 region = toKeywordRegion row col keyword
3227 in
3228 Report.Report "RESERVED WORD" region [] $
3229 Code.toSnippet source surroundings (Just region)
3231 D.fillSep
3232 ["The","name"
3233 ,"`" <> D.cyan (D.fromChars keyword) <> "`"
3234 ,"is","reserved","in","Elm,","so","it","cannot"
3235 ,"be","used","as","an","argument","here:"
3238 D.stack
3239 [ D.reflow $
3240 "Try renaming it to something else."
3241 , case keyword of
3242 "as" ->
3243 D.toFancyNote
3244 ["This","keyword","is","reserved","for","pattern","matches","like"
3245 ,"((x,y)",D.cyan "as","point)","where","you","want","to","name","a","tuple","and"
3246 ,"the","values","it","contains."
3249 _ ->
3250 D.toSimpleNote $
3251 "The `" ++ keyword ++ "` keyword has a special meaning in Elm, so it can only be used in certain situations."
3255 Code.Operator "->" ->
3256 let
3257 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3258 region = toWiderRegion row col 2
3259 in
3260 Report.Report "MISSING COLON?" region [] $
3261 Code.toSnippet source surroundings (Just region)
3263 D.reflow $
3264 "I was not expecting to see an arrow here:"
3266 D.stack
3267 [ D.fillSep
3268 ["This","usually","means","a",D.green ":","is","missing","a","bit","earlier","in"
3269 ,"a","type","annotation.","It","could","be","something","else","though,","so"
3270 ,"here","is","a","valid","definition","for","reference:"
3272 , D.vcat
3273 [ D.indent 4 $ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
3274 , D.indent 4 $ D.fillSep [D.green "add","x","y","="]
3275 , D.indent 6 $ D.fillSep ["x","+","y"]
3277 , D.reflow $
3278 "Try to use that format with your `" ++ Name.toChars name ++ "` definition!"
3282 Code.Operator op ->
3283 let
3284 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3285 region = toKeywordRegion row col op
3286 in
3287 Report.Report "UNEXPECTED SYMBOL" region [] $
3288 Code.toSnippet source surroundings (Just region)
3290 D.reflow $
3291 "I was not expecting to see this symbol here:"
3293 D.stack
3294 [ D.reflow $
3295 "I am not sure what is going wrong exactly, so here is a valid\
3296 \ definition (with an optional type annotation) for reference:"
3297 , D.vcat
3298 [ D.indent 4 $ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
3299 , D.indent 4 $ D.fillSep [D.green "add","x","y","="]
3300 , D.indent 6 $ D.fillSep ["x","+","y"]
3302 , D.reflow $
3303 "Try to use that format with your `" ++ Name.toChars name ++ "` definition!"
3307 _ ->
3308 let
3309 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3310 region = toRegion row col
3311 in
3312 Report.Report "PROBLEM IN DEFINITION" region [] $
3313 Code.toSnippet source surroundings (Just region)
3315 D.reflow $
3316 "I got stuck while parsing the `" ++ Name.toChars name ++ "` definition:"
3318 D.stack
3319 [ D.reflow $
3320 "I am not sure what is going wrong exactly, so here is a valid\
3321 \ definition (with an optional type annotation) for reference:"
3322 , D.vcat
3323 [ D.indent 4 $ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
3324 , D.indent 4 $ D.fillSep [D.green "add","x","y","="]
3325 , D.indent 4 $ D.fillSep ["x","+","y"]
3327 , D.reflow $
3328 "Try to use that format!"
3332 DefBody expr row col ->
3333 toExprReport source (InDef name startRow startCol) expr row col
3335 DefIndentEquals row col ->
3336 let
3337 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3338 region = toRegion row col
3339 in
3340 Report.Report "UNFINISHED DEFINITION" region [] $
3341 Code.toSnippet source surroundings (Just region)
3343 D.reflow $
3344 "I got stuck while parsing the `" ++ Name.toChars name ++ "` definition:"
3346 D.stack
3347 [ D.reflow $
3348 "I was expecting to see an argument or an equals sign next."
3349 , defNote
3353 DefIndentType row col ->
3354 let
3355 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3356 region = toRegion row col
3357 in
3358 Report.Report "UNFINISHED DEFINITION" region [] $
3359 Code.toSnippet source surroundings (Just region)
3361 D.reflow $
3362 "I got stuck while parsing the `" ++ Name.toChars name ++ "` type annotation:"
3364 D.stack
3365 [ D.reflow $
3366 "I just saw a colon, so I am expecting to see a type next."
3367 , defNote
3371 DefIndentBody row col ->
3372 let
3373 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3374 region = toRegion row col
3375 in
3376 Report.Report "UNFINISHED DEFINITION" region [] $
3377 Code.toSnippet source surroundings (Just region)
3379 D.reflow $
3380 "I got stuck while parsing the `" ++ Name.toChars name ++ "` definition:"
3382 D.stack
3383 [ D.reflow $
3384 "I was expecting to see an expression next. What is it equal to?"
3385 , declDefNote
3389 DefAlignment indent row col ->
3390 let
3391 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3392 region = toRegion row col
3393 offset = indent - col
3394 in
3395 Report.Report "PROBLEM IN DEFINITION" region [] $
3396 Code.toSnippet source surroundings (Just region)
3398 D.reflow $
3399 "I got stuck while parsing the `" ++ Name.toChars name ++ "` definition:"
3401 D.reflow $
3402 "I just saw a type annotation indented " ++ show indent ++ " spaces, so I was\
3403 \ expecting to see the corresponding definition next with the exact same amount\
3404 \ of indentation. It looks like this line needs "
3405 ++ show offset ++ " more " ++ (if offset == 1 then "space" else "spaces") ++ "?"
3410defNote :: D.Doc
3411defNote =
3412 D.stack
3413 [ D.reflow $
3414 "Here is a valid definition (with a type annotation) for reference:"
3415 , D.vcat
3416 [ D.indent 4 $ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
3417 , D.indent 4 $ D.fillSep [D.green "add","x","y","="]
3418 , D.indent 6 $ D.fillSep ["x","+","y"]
3420 , D.reflow $
3421 "The top line (called a \"type annotation\") is optional. You can leave it off\
3422 \ if you want. As you get more comfortable with Elm and as your project grows,\
3423 \ it becomes more and more valuable to add them though! They work great as\
3424 \ compiler-verified documentation, and they often improve error messages!"
3428toLetDestructReport :: Code.Source -> Destruct -> Row -> Col -> Report.Report
3429toLetDestructReport source destruct startRow startCol =
3430 case destruct of
3431 DestructSpace space row col ->
3432 toSpaceReport source space row col
3434 DestructPattern pattern row col ->
3435 toPatternReport source PLet pattern row col
3437 DestructEquals row col ->
3438 let
3439 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3440 region = toRegion row col
3441 in
3442 Report.Report "PROBLEM IN DEFINITION" region [] $
3443 Code.toSnippet source surroundings (Just region)
3445 D.reflow $
3446 "I got stuck trying to parse this definition:"
3448 case Code.whatIsNext source row col of
3449 Code.Operator ":" ->
3450 D.stack
3451 [ D.reflow $
3452 "I was expecting to see an equals sign next, followed by an expression\
3453 \ telling me what to compute."
3454 , D.toSimpleNote $
3455 "It looks like you may be trying to write a type annotation? It is not\
3456 \ possible to add type annotations on destructuring definitions like this.\
3457 \ You can assign a name to the overall structure, put a type annotation on\
3458 \ that, and then destructure separately though."
3461 _ ->
3462 D.reflow $
3463 "I was expecting to see an equals sign next, followed by an expression\
3464 \ telling me what to compute."
3467 DestructBody expr row col ->
3468 toExprReport source (InDestruct startRow startCol) expr row col
3470 DestructIndentEquals row col ->
3471 let
3472 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3473 region = toRegion row col
3474 in
3475 Report.Report "UNFINISHED DEFINITION" region [] $
3476 Code.toSnippet source surroundings (Just region)
3478 D.reflow $
3479 "I got stuck trying to parse this definition:"
3481 D.reflow $
3482 "I was expecting to see an equals sign next, followed by an expression\
3483 \ telling me what to compute."
3486 DestructIndentBody row col ->
3487 let
3488 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3489 region = toRegion row col
3490 in
3491 Report.Report "UNFINISHED DEFINITION" region [] $
3492 Code.toSnippet source surroundings (Just region)
3494 D.reflow $
3495 "I got stuck while parsing this definition:"
3497 D.reflow $
3498 "I was expecting to see an expression next. What is it equal to?"
3503-- CASE
3506toCaseReport :: Code.Source -> Context -> Case -> Row -> Col -> Report.Report
3507toCaseReport source context case_ startRow startCol =
3508 case case_ of
3509 CaseSpace space row col ->
3510 toSpaceReport source space row col
3512 CaseOf row col ->
3513 toUnfinishCaseReport source row col startRow startCol $
3514 D.fillSep ["I","was","expecting","to","see","the",D.dullyellow "of","keyword","next."]
3516 CasePattern pattern row col ->
3517 toPatternReport source PCase pattern row col
3519 CaseArrow row col ->
3520 case Code.whatIsNext source row col of
3521 Code.Keyword keyword ->
3522 let
3523 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3524 region = toKeywordRegion row col keyword
3525 in
3526 Report.Report "RESERVED WORD" region [] $
3527 Code.toSnippet source surroundings (Just region)
3529 D.reflow $
3530 "I am partway through parsing a `case` expression, but I got stuck here:"
3532 D.reflow $
3533 "It looks like you are trying to use `" ++ keyword ++ "` in one of your\
3534 \ patterns, but it is a reserved word. Try using a different name?"
3537 Code.Operator ":" ->
3538 let
3539 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3540 region = toRegion row col
3541 in
3542 Report.Report "UNEXPECTED OPERATOR" region [] $
3543 Code.toSnippet source surroundings (Just region)
3545 D.reflow $
3546 "I am partway through parsing a `case` expression, but I got stuck here:"
3548 D.fillSep $
3549 ["I","am","seeing",D.dullyellow ":","but","maybe","you","want",D.green "::","instead?"
3550 ,"For","pattern","matching","on","lists?"
3554 Code.Operator "=" ->
3555 let
3556 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3557 region = toRegion row col
3558 in
3559 Report.Report "UNEXPECTED OPERATOR" region [] $
3560 Code.toSnippet source surroundings (Just region)
3562 D.reflow $
3563 "I am partway through parsing a `case` expression, but I got stuck here:"
3565 D.fillSep $
3566 ["I","am","seeing",D.dullyellow "=","but","maybe","you","want",D.green "->","instead?"
3570 _ ->
3571 let
3572 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3573 region = toRegion row col
3574 in
3575 Report.Report "MISSING ARROW" region [] $
3576 Code.toSnippet source surroundings (Just region)
3578 D.reflow $
3579 "I am partway through parsing a `case` expression, but I got stuck here:"
3581 D.stack
3582 [ D.reflow "I was expecting to see an arrow next."
3583 , noteForCaseIndentError
3587 CaseExpr expr row col ->
3588 toExprReport source (InNode NCase startRow startCol context) expr row col
3590 CaseBranch expr row col ->
3591 toExprReport source (InNode NBranch startRow startCol context) expr row col
3593 CaseIndentOf row col ->
3594 toUnfinishCaseReport source row col startRow startCol $
3595 D.fillSep ["I","was","expecting","to","see","the",D.dullyellow "of","keyword","next."]
3597 CaseIndentExpr row col ->
3598 toUnfinishCaseReport source row col startRow startCol $
3599 D.reflow "I was expecting to see a expression next."
3601 CaseIndentPattern row col ->
3602 toUnfinishCaseReport source row col startRow startCol $
3603 D.reflow "I was expecting to see a pattern next."
3605 CaseIndentArrow row col ->
3606 toUnfinishCaseReport source row col startRow startCol $
3607 D.fillSep
3608 ["I","just","saw","a","pattern,","so","I","was","expecting"
3609 ,"to","see","a",D.dullyellow "->","next."
3612 CaseIndentBranch row col ->
3613 toUnfinishCaseReport source row col startRow startCol $
3614 D.reflow $
3615 "I was expecting to see an expression next. What should I do when\
3616 \ I run into this particular pattern?"
3618 CasePatternAlignment indent row col ->
3619 toUnfinishCaseReport source row col startRow startCol $
3620 D.reflow $
3621 "I suspect this is a pattern that is not indented far enough? (" ++ show indent ++ " spaces)"
3624toUnfinishCaseReport :: Code.Source -> Row -> Col -> Row -> Col -> D.Doc -> Report.Report
3625toUnfinishCaseReport source row col startRow startCol message =
3626 let
3627 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3628 region = toRegion row col
3629 in
3630 Report.Report "UNFINISHED CASE" region [] $
3631 Code.toSnippet source surroundings (Just region)
3633 D.reflow $
3634 "I was partway through parsing a `case` expression, but I got stuck here:"
3636 D.stack
3637 [ message
3638 , noteForCaseError
3643noteForCaseError :: D.Doc
3644noteForCaseError =
3645 D.stack
3646 [ D.toSimpleNote $
3647 "Here is an example of a valid `case` expression for reference."
3648 , D.vcat $
3649 [ D.indent 4 $ D.fillSep [D.cyan "case","maybeWidth",D.cyan "of"]
3650 , D.indent 6 $ D.fillSep [D.blue "Just","width","->"]
3651 , D.indent 8 $ D.fillSep ["width","+",D.dullyellow "200"]
3652 , ""
3653 , D.indent 6 $ D.fillSep [D.blue "Nothing","->"]
3654 , D.indent 8 $ D.fillSep [D.dullyellow "400"]
3656 , D.reflow $
3657 "Notice the indentation. Each pattern is aligned, and each branch is indented\
3658 \ a bit more than the corresponding pattern. That is important!"
3662noteForCaseIndentError :: D.Doc
3663noteForCaseIndentError =
3664 D.stack
3665 [ D.toSimpleNote $
3666 "Sometimes I get confused by indentation, so try to make your `case` look\
3667 \ something like this:"
3668 , D.vcat $
3669 [ D.indent 4 $ D.fillSep [D.cyan "case","maybeWidth",D.cyan "of"]
3670 , D.indent 6 $ D.fillSep [D.blue "Just","width","->"]
3671 , D.indent 8 $ D.fillSep ["width","+",D.dullyellow "200"]
3672 , ""
3673 , D.indent 6 $ D.fillSep [D.blue "Nothing","->"]
3674 , D.indent 8 $ D.fillSep [D.dullyellow "400"]
3676 , D.reflow $
3677 "Notice the indentation! Patterns are aligned with each other. Same indentation.\
3678 \ The expressions after each arrow are all indented a bit more than the patterns.\
3679 \ That is important!"
3684-- IF
3687toIfReport :: Code.Source -> Context -> If -> Row -> Col -> Report.Report
3688toIfReport source context if_ startRow startCol =
3689 case if_ of
3690 IfSpace space row col ->
3691 toSpaceReport source space row col
3693 IfThen row col ->
3694 let
3695 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3696 region = toRegion row col
3697 in
3698 Report.Report "UNFINISHED IF" region [] $
3699 Code.toSnippet source surroundings (Just region)
3701 D.reflow $
3702 "I was expecting to see more of this `if` expression, but I got stuck here:"
3704 D.fillSep $
3705 ["I","was","expecting","to","see","the",D.cyan "then","keyword","next."
3709 IfElse row col ->
3710 let
3711 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3712 region = toRegion row col
3713 in
3714 Report.Report "UNFINISHED IF" region [] $
3715 Code.toSnippet source surroundings (Just region)
3717 D.reflow $
3718 "I was expecting to see more of this `if` expression, but I got stuck here:"
3720 D.fillSep $
3721 ["I","was","expecting","to","see","the",D.cyan "else","keyword","next."
3725 IfElseBranchStart row col ->
3726 let
3727 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3728 region = toRegion row col
3729 in
3730 Report.Report "UNFINISHED IF" region [] $
3731 Code.toSnippet source surroundings (Just region)
3733 D.reflow $
3734 "I just saw the start of an `else` branch, but then I got stuck here:"
3736 D.reflow $
3737 "I was expecting to see an expression next. Maybe it is not filled in yet?"
3740 IfCondition expr row col ->
3741 toExprReport source (InNode NCond startRow startCol context) expr row col
3743 IfThenBranch expr row col ->
3744 toExprReport source (InNode NThen startRow startCol context) expr row col
3746 IfElseBranch expr row col ->
3747 toExprReport source (InNode NElse startRow startCol context) expr row col
3749 IfIndentCondition row col ->
3750 let
3751 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3752 region = toRegion row col
3753 in
3754 Report.Report "UNFINISHED IF" region [] $
3755 Code.toSnippet source surroundings (Just region)
3757 D.reflow $
3758 "I was expecting to see more of this `if` expression, but I got stuck here:"
3760 D.stack
3761 [ D.fillSep $
3762 ["I","was","expecting","to","see","an","expression","like",D.dullyellow "x < 0"
3763 ,"that","evaluates","to","True","or","False."
3765 , D.toSimpleNote $
3766 "I can be confused by indentation. Maybe something is not indented enough?"
3770 IfIndentThen row col ->
3771 let
3772 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3773 region = toRegion row col
3774 in
3775 Report.Report "UNFINISHED IF" region [] $
3776 Code.toSnippet source surroundings (Just region)
3778 D.reflow $
3779 "I was expecting to see more of this `if` expression, but I got stuck here:"
3781 D.stack
3782 [ D.fillSep $
3783 ["I","was","expecting","to","see","the",D.cyan "then","keyword","next."
3785 , D.toSimpleNote $
3786 "I can be confused by indentation. Maybe something is not indented enough?"
3790 IfIndentThenBranch row col ->
3791 let
3792 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3793 region = toRegion row col
3794 in
3795 Report.Report "UNFINISHED IF" region [] $
3796 Code.toSnippet source surroundings (Just region)
3798 D.reflow $
3799 "I got stuck after the start of this `then` branch:"
3801 D.stack
3802 [ D.reflow $
3803 "I was expecting to see an expression next. Maybe it is not filled in yet?"
3804 , D.toSimpleNote $
3805 "I can be confused by indentation, so if the `then` branch is already\
3806 \ present, it may not be indented enough for me to recognize it."
3810 IfIndentElseBranch row col ->
3811 let
3812 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3813 region = toRegion row col
3814 in
3815 Report.Report "UNFINISHED IF" region [] $
3816 Code.toSnippet source surroundings (Just region)
3818 D.reflow $
3819 "I got stuck after the start of this `else` branch:"
3821 D.stack
3822 [ D.reflow $
3823 "I was expecting to see an expression next. Maybe it is not filled in yet?"
3824 , D.toSimpleNote $
3825 "I can be confused by indentation, so if the `else` branch is already\
3826 \ present, it may not be indented enough for me to recognize it."
3830 IfIndentElse row col ->
3831 case Code.nextLineStartsWithKeyword "else" source row of
3832 Just (elseRow, elseCol) ->
3833 let
3834 surroundings = A.Region (A.Position startRow startCol) (A.Position elseRow elseCol)
3835 region = toWiderRegion elseRow elseCol 4
3836 in
3837 Report.Report "WEIRD ELSE BRANCH" region [] $
3838 Code.toSnippet source surroundings (Just region)
3840 D.reflow $
3841 "I was partway through an `if` expression when I got stuck here:"
3843 D.fillSep $
3844 ["I","think","this",D.cyan "else","keyword","needs","to","be","indented","more."
3845 ,"Try","adding","some","spaces","before","it."
3849 Nothing ->
3850 let
3851 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3852 region = toRegion row col
3853 in
3854 Report.Report "UNFINISHED IF" region [] $
3855 Code.toSnippet source surroundings (Just region)
3857 D.reflow $
3858 "I was expecting to see an `else` branch after this:"
3860 D.stack
3861 [ D.fillSep
3862 ["I","know","what","to","do","when","the","condition","is","True,"
3863 ,"but","what","happens","when","it","is","False?"
3864 ,"Add","an",D.cyan "else","branch","to","handle","that","scenario!"
3871-- RECORD
3874toRecordReport :: Code.Source -> Context -> Record -> Row -> Col -> Report.Report
3875toRecordReport source context record startRow startCol =
3876 case record of
3877 RecordOpen row col ->
3878 case Code.whatIsNext source row col of
3879 Code.Keyword keyword ->
3880 let
3881 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3882 region = toKeywordRegion row col keyword
3883 in
3884 Report.Report "RESERVED WORD" region [] $
3885 Code.toSnippet source surroundings (Just region)
3887 D.reflow $
3888 "I just started parsing a record, but I got stuck on this field name:"
3890 D.reflow $
3891 "It looks like you are trying to use `" ++ keyword ++ "` as a field name, but \
3892 \ that is a reserved word. Try using a different name!"
3895 _ ->
3896 let
3897 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3898 region = toRegion row col
3899 in
3900 Report.Report "PROBLEM IN RECORD" region [] $
3901 Code.toSnippet source surroundings (Just region)
3903 D.reflow $
3904 "I just started parsing a record, but I got stuck here:"
3906 D.stack
3907 [ D.fillSep
3908 ["I","was","expecting","to","see","a","record","field","defined","next,"
3909 ,"so","I","am","looking","for","a","name","like"
3910 ,D.dullyellow "userName","or",D.dullyellow "plantHeight" <> "."
3912 , D.toSimpleNote $
3913 "Field names must start with a lower-case letter. After that, you can use\
3914 \ any sequence of letters, numbers, and underscores."
3915 , noteForRecordError
3919 RecordEnd row col ->
3920 let
3921 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3922 region = toRegion row col
3923 in
3924 Report.Report "PROBLEM IN RECORD" region [] $
3925 Code.toSnippet source surroundings (Just region)
3927 D.reflow $
3928 "I am partway through parsing a record, but I got stuck here:"
3930 D.stack
3931 [ D.fillSep
3932 ["I","was","expecting","to","see","a","closing","curly","brace","before","this,"
3933 ,"so","try","adding","a",D.dullyellow "}","and","see","if","that","helps?"
3935 , D.toSimpleNote $
3936 "When I get stuck like this, it usually means that there is a missing parenthesis\
3937 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
3941 RecordField row col ->
3942 case Code.whatIsNext source row col of
3943 Code.Keyword keyword ->
3944 let
3945 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3946 region = toKeywordRegion row col keyword
3947 in
3948 Report.Report "RESERVED WORD" region [] $
3949 Code.toSnippet source surroundings (Just region)
3951 D.reflow $
3952 "I am partway through parsing a record, but I got stuck on this field name:"
3954 D.reflow $
3955 "It looks like you are trying to use `" ++ keyword ++ "` as a field name, but \
3956 \ that is a reserved word. Try using a different name!"
3959 Code.Other (Just ',') ->
3960 let
3961 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3962 region = toRegion row col
3963 in
3964 Report.Report "EXTRA COMMA" region [] $
3965 Code.toSnippet source surroundings (Just region)
3967 D.reflow $
3968 "I am partway through parsing a record, but I got stuck here:"
3970 D.stack
3971 [ D.reflow $
3972 "I am seeing two commas in a row. This is the second one!"
3973 , D.reflow $
3974 "Just delete one of the commas and you should be all set!"
3975 , noteForRecordError
3979 Code.Close _ '}' ->
3980 let
3981 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3982 region = toRegion row col
3983 in
3984 Report.Report "EXTRA COMMA" region [] $
3985 Code.toSnippet source surroundings (Just region)
3987 D.reflow $
3988 "I am partway through parsing a record, but I got stuck here:"
3990 D.stack
3991 [ D.reflow $
3992 "Trailing commas are not allowed in records. Try deleting the comma that appears\
3993 \ before this closing curly brace."
3994 , noteForRecordError
3998 _ ->
3999 let
4000 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4001 region = toRegion row col
4002 in
4003 Report.Report "PROBLEM IN RECORD" region [] $
4004 Code.toSnippet source surroundings (Just region)
4006 D.reflow $
4007 "I am partway through parsing a record, but I got stuck here:"
4009 D.stack
4010 [ D.fillSep
4011 ["I","was","expecting","to","see","another","record","field","defined","next,"
4012 ,"so","I","am","looking","for","a","name","like"
4013 ,D.dullyellow "userName","or",D.dullyellow "plantHeight" <> "."
4015 , D.toSimpleNote $
4016 "Field names must start with a lower-case letter. After that, you can use\
4017 \ any sequence of letters, numbers, and underscores."
4018 , noteForRecordError
4022 RecordEquals row col ->
4023 let
4024 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4025 region = toRegion row col
4026 in
4027 Report.Report "PROBLEM IN RECORD" region [] $
4028 Code.toSnippet source surroundings (Just region)
4030 D.reflow $
4031 "I am partway through parsing a record, but I got stuck here:"
4033 D.stack
4034 [ D.fillSep $
4035 ["I","just","saw","a","field","name,","so","I","was","expecting","to","see"
4036 ,"an","equals","sign","next.","So","try","putting","an",D.green "=","sign","here?"
4038 , noteForRecordError
4042 RecordExpr expr row col ->
4043 toExprReport source (InNode NRecord startRow startCol context) expr row col
4045 RecordSpace space row col ->
4046 toSpaceReport source space row col
4048 RecordIndentOpen row col ->
4049 let
4050 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4051 region = toRegion row col
4052 in
4053 Report.Report "UNFINISHED RECORD" region [] $
4054 Code.toSnippet source surroundings (Just region)
4056 D.reflow $
4057 "I just saw the opening curly brace of a record, but then I got stuck here:"
4059 addNoteForRecordIndentError $
4060 D.fillSep $
4061 ["I","am","expecting","a","record","like",D.dullyellow "{ x = 3, y = 4 }","here."
4062 ,"Try","defining","some","fields","of","your","own?"
4066 RecordIndentEnd row col ->
4067 case Code.nextLineStartsWithCloseCurly source row of
4068 Just (curlyRow, curlyCol) ->
4069 let
4070 surroundings = A.Region (A.Position startRow startCol) (A.Position curlyRow curlyCol)
4071 region = toRegion curlyRow curlyCol
4072 in
4073 Report.Report "NEED MORE INDENTATION" region [] $
4074 Code.toSnippet source surroundings (Just region)
4076 D.reflow $
4077 "I was partway through parsing a record, but I got stuck here:"
4079 D.stack
4080 [ D.reflow $
4081 "I need this curly brace to be indented more. Try adding some spaces before it!"
4082 , noteForRecordError
4086 Nothing ->
4087 let
4088 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4089 region = toRegion row col
4090 in
4091 Report.Report "UNFINISHED RECORD" region [] $
4092 Code.toSnippet source surroundings (Just region)
4094 D.reflow $
4095 "I was partway through parsing a record, but I got stuck here:"
4097 addNoteForRecordIndentError $
4098 D.fillSep $
4099 ["I","was","expecting","to","see","a","closing","curly","brace","next."
4100 ,"Try","putting","a",D.green "}","next","and","see","if","that","helps?"
4104 RecordIndentField row col ->
4105 let
4106 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4107 region = toRegion row col
4108 in
4109 Report.Report "UNFINISHED RECORD" region [] $
4110 Code.toSnippet source surroundings (Just region)
4112 D.reflow $
4113 "I am partway through parsing a record, but I got stuck after that last comma:"
4115 D.stack
4116 [ D.reflow $
4117 "Trailing commas are not allowed in records, so the fix may be to\
4118 \ delete that last comma? Or maybe you were in the middle of defining\
4119 \ an additional field?"
4120 , noteForRecordError
4124 RecordIndentEquals row col ->
4125 let
4126 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4127 region = toRegion row col
4128 in
4129 Report.Report "UNFINISHED RECORD" region [] $
4130 Code.toSnippet source surroundings (Just region)
4132 D.reflow $
4133 "I am partway through parsing a record. I just saw a record\
4134 \ field, so I was expecting to see an equals sign next:"
4136 addNoteForRecordIndentError $
4137 D.fillSep $
4138 ["Try","putting","an",D.green "=","followed","by","an","expression?"
4142 RecordIndentExpr row col ->
4143 let
4144 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4145 region = toRegion row col
4146 in
4147 Report.Report "UNFINISHED RECORD" region [] $
4148 Code.toSnippet source surroundings (Just region)
4150 D.reflow $
4151 "I am partway through parsing a record, and I was expecting to run into an expression next:"
4153 addNoteForRecordIndentError $
4154 D.fillSep $
4155 ["Try","putting","something","like"
4156 ,D.dullyellow "42","or",D.dullyellow"\"hello\"","for","now?"
4161noteForRecordError :: D.Doc
4162noteForRecordError =
4163 D.stack $
4164 [ D.toSimpleNote
4165 "If you are trying to define a record across multiple lines, I recommend using this format:"
4166 , D.indent 4 $ D.vcat $
4167 [ "{ name = \"Alice\""
4168 , ", age = 42"
4169 , ", height = 1.75"
4170 , "}"
4172 , D.reflow $
4173 "Notice that each line starts with some indentation. Usually two or four spaces. I\
4174 \ know this style can be jarring for people coming from C-like syntax, but folks generally\
4175 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
4179addNoteForRecordIndentError :: D.Doc -> D.Doc
4180addNoteForRecordIndentError normalRecommendation =
4181 D.stack $
4182 normalRecommendation
4184 [ D.toSimpleNote
4185 "I may be confused by indentation. For example, if you are trying to define\
4186 \ a record across multiple lines, I recommend using this format:"
4187 , D.indent 4 $ D.vcat $
4188 [ "{ name = \"Alice\""
4189 , ", age = 42"
4190 , ", height = 1.75"
4191 , "}"
4193 , D.reflow $
4194 "Notice that each line starts with some indentation. Usually two or four spaces. I\
4195 \ know this style can be jarring for people coming from C-like syntax, but folks generally\
4196 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
4201-- TUPLE
4204toTupleReport :: Code.Source -> Context -> Tuple -> Row -> Col -> Report.Report
4205toTupleReport source context tuple startRow startCol =
4206 case tuple of
4207 TupleExpr expr row col ->
4208 toExprReport source (InNode NParens startRow startCol context) expr row col
4210 TupleSpace space row col ->
4211 toSpaceReport source space row col
4213 TupleEnd row col ->
4214 let
4215 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4216 region = toRegion row col
4217 in
4218 Report.Report "UNFINISHED PARENTHESES" region [] $
4219 Code.toSnippet source surroundings (Just region)
4221 D.reflow $
4222 "I was expecting to see a closing parentheses next, but I got stuck here:"
4224 D.stack
4225 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps?"]
4226 , D.toSimpleNote $
4227 "I can get stuck when I run into keywords, operators, parentheses, or brackets\
4228 \ unexpectedly. So there may be some earlier syntax trouble (like extra parenthesis\
4229 \ or missing brackets) that is confusing me."
4233 TupleOperatorClose row col ->
4234 let
4235 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4236 region = toRegion row col
4237 in
4238 Report.Report "UNFINISHED OPERATOR FUNCTION" region [] $
4239 Code.toSnippet source surroundings (Just region)
4241 D.reflow "I was expecting a closing parenthesis here:"
4243 D.stack
4244 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps!"]
4245 , D.toSimpleNote $
4246 "I think I am parsing an operator function right now, so I am expecting to see\
4247 \ something like (+) or (&&) where an operator is surrounded by parentheses with\
4248 \ no extra spaces."
4252 TupleOperatorReserved operator row col ->
4253 let
4254 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4255 region = toRegion row col
4256 in
4257 Report.Report "UNEXPECTED SYMBOL" region [] $
4258 Code.toSnippet source surroundings (Just region)
4260 D.reflow $
4261 "I ran into an unexpected symbol here:"
4263 D.fillSep $
4264 case operator of
4265 BadDot -> ["Maybe","you","wanted","a","record","accessor","like",D.dullyellow ".x","or",D.dullyellow ".name","instead?"]
4266 BadPipe -> ["Try",D.dullyellow "(||)","instead?","To","turn","boolean","OR","into","a","function?"]
4267 BadArrow -> ["Maybe","you","wanted",D.dullyellow "(>)","or",D.dullyellow "(>=)","instead?"]
4268 BadEquals -> ["Try",D.dullyellow "(==)","instead?","To","make","a","function","that","checks","equality?"]
4269 BadHasType -> ["Try",D.dullyellow "(::)","instead?","To","add","values","to","the","front","of","lists?"]
4272 TupleIndentExpr1 row col ->
4273 let
4274 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4275 region = toRegion row col
4276 in
4277 Report.Report "UNFINISHED PARENTHESES" region [] $
4278 Code.toSnippet source surroundings (Just region)
4280 D.reflow $
4281 "I just saw an open parenthesis, so I was expecting to see an expression next."
4283 D.stack
4284 [ D.fillSep $
4285 ["Something","like",D.dullyellow "(4 + 5)","or"
4286 ,D.dullyellow "(String.reverse \"desserts\")" <> "."
4287 ,"Anything","where","you","are","putting","parentheses","around","normal","expressions."
4289 , D.toSimpleNote $
4290 "I can get confused by indentation in cases like this, so\
4291 \ maybe you have an expression but it is not indented enough?"
4295 TupleIndentExprN row col ->
4296 let
4297 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4298 region = toRegion row col
4299 in
4300 Report.Report "UNFINISHED TUPLE" region [] $
4301 Code.toSnippet source surroundings (Just region)
4303 D.reflow $
4304 "I think I am in the middle of parsing a tuple. I just saw a comma, so I was expecting to see an expression next."
4306 D.stack
4307 [ D.fillSep $
4308 ["A","tuple","looks","like",D.dullyellow "(3,4)","or"
4309 ,D.dullyellow "(\"Tom\",42)" <> ","
4310 ,"so","I","think","there","is","an","expression","missing","here?"
4312 , D.toSimpleNote $
4313 "I can get confused by indentation in cases like this, so\
4314 \ maybe you have an expression but it is not indented enough?"
4318 TupleIndentEnd row col ->
4319 let
4320 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4321 region = toRegion row col
4322 in
4323 Report.Report "UNFINISHED PARENTHESES" region [] $
4324 Code.toSnippet source surroundings (Just region)
4326 D.reflow $
4327 "I was expecting to see a closing parenthesis next:"
4329 D.stack
4330 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps!"]
4331 , D.toSimpleNote $
4332 "I can get confused by indentation in cases like this, so\
4333 \ maybe you have a closing parenthesis but it is not indented enough?"
4338toListReport :: Code.Source -> Context -> List -> Row -> Col -> Report.Report
4339toListReport source context list startRow startCol =
4340 case list of
4341 ListSpace space row col ->
4342 toSpaceReport source space row col
4344 ListOpen row col ->
4345 let
4346 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4347 region = toRegion row col
4348 in
4349 Report.Report "UNFINISHED LIST" region [] $
4350 Code.toSnippet source surroundings (Just region)
4352 D.reflow $
4353 "I am partway through parsing a list, but I got stuck here:"
4355 D.stack
4356 [ D.fillSep
4357 ["I","was","expecting","to","see","a","closing","square","bracket","before","this,"
4358 ,"so","try","adding","a",D.dullyellow "]","and","see","if","that","helps?"
4360 , D.toSimpleNote $
4361 "When I get stuck like this, it usually means that there is a missing parenthesis\
4362 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
4366 ListExpr expr row col ->
4367 case expr of
4368 Start r c ->
4369 let
4370 surroundings = A.Region (A.Position startRow startCol) (A.Position r c)
4371 region = toRegion r c
4372 in
4373 Report.Report "UNFINISHED LIST" region [] $
4374 Code.toSnippet source surroundings (Just region)
4376 D.reflow $
4377 "I was expecting to see another list entry after that last comma:"
4379 D.stack
4380 [ D.reflow $
4381 "Trailing commas are not allowed in lists, so the fix may be to delete the comma?"
4382 , D.toSimpleNote
4383 "I recommend using the following format for lists that span multiple lines:"
4384 , D.indent 4 $ D.vcat $
4385 [ "[ \"Alice\""
4386 , ", \"Bob\""
4387 , ", \"Chuck\""
4388 , "]"
4390 , D.reflow $
4391 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
4392 \ This style can be jarring for people coming from C-like syntax, but folks generally\
4393 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
4397 _ ->
4398 toExprReport source (InNode NList startRow startCol context) expr row col
4400 ListEnd row col ->
4401 let
4402 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4403 region = toRegion row col
4404 in
4405 Report.Report "UNFINISHED LIST" region [] $
4406 Code.toSnippet source surroundings (Just region)
4408 D.reflow $
4409 "I am partway through parsing a list, but I got stuck here:"
4411 D.stack
4412 [ D.fillSep
4413 ["I","was","expecting","to","see","a","closing","square","bracket","before","this,"
4414 ,"so","try","adding","a",D.dullyellow "]","and","see","if","that","helps?"
4416 , D.toSimpleNote $
4417 "When I get stuck like this, it usually means that there is a missing parenthesis\
4418 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
4422 ListIndentOpen row col ->
4423 let
4424 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4425 region = toRegion row col
4426 in
4427 Report.Report "UNFINISHED LIST" region [] $
4428 Code.toSnippet source surroundings (Just region)
4430 D.reflow $
4431 "I cannot find the end of this list:"
4433 D.stack
4434 [ D.fillSep $
4435 ["You","could","change","it","to","something","like"
4436 ,D.dullyellow "[3,4,5]"
4437 ,"or","even","just"
4438 ,D.dullyellow "[]" <> "."
4439 ,"Anything","where","there","is","an","open","and","close","square","brace,"
4440 ,"and","where","the","elements","of","the","list","are","separated","by","commas."
4442 , D.toSimpleNote
4443 "I may be confused by indentation. For example, if you are trying to define\
4444 \ a list across multiple lines, I recommend using this format:"
4445 , D.indent 4 $ D.vcat $
4446 [ "[ \"Alice\""
4447 , ", \"Bob\""
4448 , ", \"Chuck\""
4449 , "]"
4451 , D.reflow $
4452 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
4453 \ This style can be jarring for people coming from C-like syntax, but folks generally\
4454 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
4458 ListIndentEnd row col ->
4459 let
4460 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4461 region = toRegion row col
4462 in
4463 Report.Report "UNFINISHED LIST" region [] $
4464 Code.toSnippet source surroundings (Just region)
4466 D.reflow $
4467 "I cannot find the end of this list:"
4469 D.stack
4470 [ D.fillSep $
4471 ["You","can","just","add","a","closing",D.dullyellow "]"
4472 ,"right","here,","and","I","will","be","all","set!"
4474 , D.toSimpleNote
4475 "I may be confused by indentation. For example, if you are trying to define\
4476 \ a list across multiple lines, I recommend using this format:"
4477 , D.indent 4 $ D.vcat $
4478 [ "[ \"Alice\""
4479 , ", \"Bob\""
4480 , ", \"Chuck\""
4481 , "]"
4483 , D.reflow $
4484 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
4485 \ This style can be jarring for people coming from C-like syntax, but folks generally\
4486 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
4490 ListIndentExpr row col ->
4491 let
4492 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4493 region = toRegion row col
4494 in
4495 Report.Report "UNFINISHED LIST" region [] $
4496 Code.toSnippet source surroundings (Just region)
4498 D.reflow $
4499 "I was expecting to see another list entry after this comma:"
4501 D.stack
4502 [ D.reflow $
4503 "Trailing commas are not allowed in lists, so the fix may be to delete the comma?"
4504 , D.toSimpleNote
4505 "I recommend using the following format for lists that span multiple lines:"
4506 , D.indent 4 $ D.vcat $
4507 [ "[ \"Alice\""
4508 , ", \"Bob\""
4509 , ", \"Chuck\""
4510 , "]"
4512 , D.reflow $
4513 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
4514 \ This style can be jarring for people coming from C-like syntax, but folks generally\
4515 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
4520toFuncReport :: Code.Source -> Context -> Func -> Row -> Col -> Report.Report
4521toFuncReport source context func startRow startCol =
4522 case func of
4523 FuncSpace space row col ->
4524 toSpaceReport source space row col
4526 FuncArg pattern row col ->
4527 toPatternReport source PArg pattern row col
4529 FuncBody expr row col ->
4530 toExprReport source (InNode NFunc startRow startCol context) expr row col
4532 FuncArrow row col ->
4533 case Code.whatIsNext source row col of
4534 Code.Keyword keyword ->
4535 let
4536 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4537 region = toKeywordRegion row col keyword
4538 in
4539 Report.Report "RESERVED WORD" region [] $
4540 Code.toSnippet source surroundings (Just region)
4542 D.reflow $
4543 "I was parsing an anonymous function, but I got stuck here:"
4545 D.reflow $
4546 "It looks like you are trying to use `" ++ keyword ++ "` as an argument, but\
4547 \ it is a reserved word in this language. Try using a different argument name!"
4550 _ ->
4551 let
4552 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4553 region = toRegion row col
4554 in
4555 Report.Report "UNFINISHED ANONYMOUS FUNCTION" region [] $
4556 Code.toSnippet source surroundings (Just region)
4558 D.reflow $
4559 "I just saw the beginning of an anonymous function, so I was expecting to see an arrow next:"
4561 D.fillSep $
4562 ["The","syntax","for","anonymous","functions","is"
4563 ,D.dullyellow "(\\x -> x + 1)"
4564 ,"so","I","am","missing","the","arrow","and","the","body","of","the","function."
4568 FuncIndentArg row col ->
4569 let
4570 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4571 region = toRegion row col
4572 in
4573 Report.Report "MISSING ARGUMENT" region [] $
4574 Code.toSnippet source surroundings (Just region)
4576 D.reflow $
4577 "I just saw the beginning of an anonymous function, so I was expecting to see an argument next:"
4579 D.stack
4580 [ D.fillSep
4581 ["Something","like",D.dullyellow"x","or",D.dullyellow "name" <> "."
4582 ,"Anything","that","starts","with","a","lower","case","letter!"
4584 , D.toSimpleNote $
4585 "The syntax for anonymous functions is (\\x -> x + 1) where the backslash\
4586 \ is meant to look a bit like a lambda if you squint. This visual pun seemed\
4587 \ like a better idea at the time!"
4591 FuncIndentArrow row col ->
4592 let
4593 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4594 region = toRegion row col
4595 in
4596 Report.Report "UNFINISHED ANONYMOUS FUNCTION" region [] $
4597 Code.toSnippet source surroundings (Just region)
4599 D.reflow $
4600 "I just saw the beginning of an anonymous function, so I was expecting to see an arrow next:"
4602 D.stack
4603 [ D.fillSep $
4604 ["The","syntax","for","anonymous","functions","is"
4605 ,D.dullyellow "(\\x -> x + 1)"
4606 ,"so","I","am","missing","the","arrow","and","the","body","of","the","function."
4608 , D.toSimpleNote $
4609 "It is possible that I am confused about indetation! I generally recommend\
4610 \ switching to named functions if the definition cannot fit inline nicely, so\
4611 \ either (1) try to fit the whole anonymous function on one line or (2) break\
4612 \ the whole thing out into a named function. Things tend to be clearer that way!"
4616 FuncIndentBody row col ->
4617 let
4618 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4619 region = toRegion row col
4620 in
4621 Report.Report "UNFINISHED ANONYMOUS FUNCTION" region [] $
4622 Code.toSnippet source surroundings (Just region)
4624 D.reflow $
4625 "I was expecting to see the body of your anonymous function next:"
4627 D.stack
4628 [ D.fillSep $
4629 ["The","syntax","for","anonymous","functions","is"
4630 ,D.dullyellow "(\\x -> x + 1)"
4631 ,"so","I","am","missing","all","the","stuff","after","the","arrow!"
4633 , D.toSimpleNote $
4634 "It is possible that I am confused about indetation! I generally recommend\
4635 \ switching to named functions if the definition cannot fit inline nicely, so\
4636 \ either (1) try to fit the whole anonymous function on one line or (2) break\
4637 \ the whole thing out into a named function. Things tend to be clearer that way!"
4643-- PATTERN
4646data PContext
4647 = PCase
4648 | PArg
4649 | PLet
4652toPatternReport :: Code.Source -> PContext -> Pattern -> Row -> Col -> Report.Report
4653toPatternReport source context pattern startRow startCol =
4654 case pattern of
4655 PRecord record row col ->
4656 toPRecordReport source record row col
4658 PTuple tuple row col ->
4659 toPTupleReport source context tuple row col
4661 PList list row col ->
4662 toPListReport source context list row col
4664 PStart row col ->
4665 case Code.whatIsNext source row col of
4666 Code.Keyword keyword ->
4667 let
4668 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4669 region = toKeywordRegion row col keyword
4670 inThisThing =
4671 case context of
4672 PArg -> "as an argument"
4673 PCase -> "in this pattern"
4674 PLet -> "in this pattern"
4675 in
4676 Report.Report "RESERVED WORD" region [] $
4677 Code.toSnippet source surroundings (Just region)
4679 D.reflow $
4680 "It looks like you are trying to use `" ++ keyword ++ "` " ++ inThisThing ++ ":"
4682 D.reflow $
4683 "This is a reserved word! Try using some other name?"
4686 Code.Operator "-" ->
4687 let
4688 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4689 region = toRegion row col
4690 in
4691 Report.Report "UNEXPECTED SYMBOL" region [] $
4692 Code.toSnippet source surroundings (Just region)
4694 D.reflow $
4695 "I ran into a minus sign unexpectedly in this pattern:"
4697 D.reflow $
4698 "It is not possible to pattern match on negative numbers at this\
4699 \ time. Try using an `if` expression for that sort of thing for now."
4702 _ ->
4703 let
4704 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4705 region = toRegion row col
4706 in
4707 Report.Report "PROBLEM IN PATTERN" region [] $
4708 Code.toSnippet source surroundings (Just region)
4710 D.reflow $
4711 "I wanted to parse a pattern next, but I got stuck here:"
4713 D.fillSep $
4714 ["I","am","not","sure","why","I","am","getting","stuck","exactly."
4715 ,"I","just","know","that","I","want","a","pattern","next."
4716 ,"Something","as","simple","as"
4717 ,D.dullyellow "maybeHeight","or",D.dullyellow "result"
4718 ,"would","work!"
4722 PChar char row col ->
4723 toCharReport source char row col
4725 PString string row col ->
4726 toStringReport source string row col
4728 PNumber number row col ->
4729 toNumberReport source number row col
4731 PFloat width row col ->
4732 let
4733 region = toWiderRegion row col width
4734 in
4735 Report.Report "UNEXPECTED PATTERN" region [] $
4736 Code.toSnippet source region Nothing
4738 D.reflow $
4739 "I cannot pattern match with floating point numbers:"
4741 D.fillSep $
4742 ["Equality","on","floats","can","be","unreliable,","so","you","usually","want"
4743 ,"to","check","that","they","are","nearby","with","some","sort","of"
4744 ,D.dullyellow "(abs (actual - expected) < 0.001)","check."
4748 PAlias row col ->
4749 let
4750 region = toRegion row col
4751 in
4752 Report.Report "UNFINISHED PATTERN" region [] $
4753 Code.toSnippet source region Nothing $
4755 D.reflow $
4756 "I was expecting to see a variable name after the `as` keyword:"
4758 D.stack
4759 [ D.fillSep $
4760 ["The","`as`","keyword","lets","you","write","patterns","like"
4761 ,"((" <> D.dullyellow "x" <> "," <> D.dullyellow "y" <> ") " <> D.cyan "as" <> D.dullyellow " point" <> ")"
4762 ,"so","you","can","refer","to","individual","parts","of","the","tuple","with"
4763 ,D.dullyellow "x","and",D.dullyellow "y","or","you","refer","to","the","whole"
4764 ,"thing","with",D.dullyellow "point" <> "."
4766 , D.reflow $
4767 "So I was expecting to see a variable name after the `as` keyword here. Sometimes\
4768 \ people just want to use `as` as a variable name though. Try using a different name\
4769 \ in that case!"
4773 PWildcardNotVar name width row col ->
4774 let
4775 region = toWiderRegion row col (fromIntegral width)
4776 examples =
4777 case dropWhile (=='_') (Name.toChars name) of
4778 [] -> [D.dullyellow "x","or",D.dullyellow "age"]
4779 c:cs -> [D.dullyellow (D.fromChars (Char.toLower c : cs))]
4780 in
4781 Report.Report "UNEXPECTED NAME" region [] $
4782 Code.toSnippet source region Nothing $
4784 D.reflow $
4785 "Variable names cannot start with underscores like this:"
4787 D.fillSep $
4788 ["You","can","either","have","an","underscore","like",D.dullyellow "_","to"
4789 ,"ignore","the","value,","or","you","can","have","a","name","like"
4790 ] ++ examples ++ ["to","use","the","matched","value." ]
4793 PSpace space row col ->
4794 toSpaceReport source space row col
4796 PIndentStart row col ->
4797 let
4798 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4799 region = toRegion row col
4800 in
4801 Report.Report "UNFINISHED PATTERN" region [] $
4802 Code.toSnippet source surroundings (Just region)
4804 D.reflow $
4805 "I wanted to parse a pattern next, but I got stuck here:"
4807 D.stack
4808 [ D.fillSep $
4809 ["I","am","not","sure","why","I","am","getting","stuck","exactly."
4810 ,"I","just","know","that","I","want","a","pattern","next."
4811 ,"Something","as","simple","as"
4812 ,D.dullyellow "maybeHeight","or",D.dullyellow "result"
4813 ,"would","work!"
4815 , D.toSimpleNote $
4816 "I can get confused by indentation. If you think there is a pattern next, maybe\
4817 \ it needs to be indented a bit more?"
4821 PIndentAlias row col ->
4822 let
4823 region = toRegion row col
4824 in
4825 Report.Report "UNFINISHED PATTERN" region [] $
4826 Code.toSnippet source region Nothing $
4828 D.reflow $
4829 "I was expecting to see a variable name after the `as` keyword:"
4831 D.stack
4832 [ D.fillSep $
4833 ["The","`as`","keyword","lets","you","write","patterns","like"
4834 ,"((" <> D.dullyellow "x" <> "," <> D.dullyellow "y" <> ") " <> D.cyan "as" <> D.dullyellow " point" <> ")"
4835 ,"so","you","can","refer","to","individual","parts","of","the","tuple","with"
4836 ,D.dullyellow "x","and",D.dullyellow "y","or","you","refer","to","the","whole"
4837 ,"thing","with",D.dullyellow "point."
4839 , D.reflow $
4840 "So I was expecting to see a variable name after the `as` keyword here. Sometimes\
4841 \ people just want to use `as` as a variable name though. Try using a different name\
4842 \ in that case!"
4847toPRecordReport :: Code.Source -> PRecord -> Row -> Col -> Report.Report
4848toPRecordReport source record startRow startCol =
4849 case record of
4850 PRecordOpen row col ->
4851 toUnfinishRecordPatternReport source row col startRow startCol $
4852 D.reflow "I was expecting to see a field name next."
4854 PRecordEnd row col ->
4855 toUnfinishRecordPatternReport source row col startRow startCol $
4856 D.fillSep
4857 ["I","was","expecting","to","see","a","closing","curly","brace","next."
4858 ,"Try","adding","a",D.dullyellow "}","here?"
4861 PRecordField row col ->
4862 case Code.whatIsNext source row col of
4863 Code.Keyword keyword ->
4864 let
4865 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4866 region = toKeywordRegion row col keyword
4867 in
4868 Report.Report "RESERVED WORD" region [] $
4869 Code.toSnippet source surroundings (Just region)
4871 D.reflow $
4872 "I was not expecting to see `" ++ keyword ++ "` as a record field name:"
4874 D.reflow $
4875 "This is a reserved word, not available for variable names. Try another name!"
4878 _ ->
4879 toUnfinishRecordPatternReport source row col startRow startCol $
4880 D.reflow "I was expecting to see a field name next."
4882 PRecordSpace space row col ->
4883 toSpaceReport source space row col
4885 PRecordIndentOpen row col ->
4886 toUnfinishRecordPatternReport source row col startRow startCol $
4887 D.reflow "I was expecting to see a field name next."
4889 PRecordIndentEnd row col ->
4890 toUnfinishRecordPatternReport source row col startRow startCol $
4891 D.fillSep
4892 ["I","was","expecting","to","see","a","closing","curly","brace","next."
4893 ,"Try","adding","a",D.dullyellow "}","here?"
4896 PRecordIndentField row col ->
4897 toUnfinishRecordPatternReport source row col startRow startCol $
4898 D.reflow "I was expecting to see a field name next."
4901toUnfinishRecordPatternReport :: Code.Source -> Row -> Col -> Row -> Col -> D.Doc -> Report.Report
4902toUnfinishRecordPatternReport source row col startRow startCol message =
4903 let
4904 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4905 region = toRegion row col
4906 in
4907 Report.Report "UNFINISHED RECORD PATTERN" region [] $
4908 Code.toSnippet source surroundings (Just region)
4910 D.reflow $
4911 "I was partway through parsing a record pattern, but I got stuck here:"
4913 D.stack
4914 [ message
4915 , D.toFancyHint $
4916 ["A","record","pattern","looks","like",D.dullyellow "{x,y}","or",D.dullyellow "{name,age}"
4917 ,"where","you","list","the","field","names","you","want","to","access."
4924toPTupleReport :: Code.Source -> PContext -> PTuple -> Row -> Col -> Report.Report
4925toPTupleReport source context tuple startRow startCol =
4926 case tuple of
4927 PTupleOpen row col ->
4928 case Code.whatIsNext source row col of
4929 Code.Keyword keyword ->
4930 let
4931 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4932 region = toKeywordRegion row col keyword
4933 in
4934 Report.Report "RESERVED WORD" region [] $
4935 Code.toSnippet source surroundings (Just region)
4937 D.reflow $
4938 "It looks like you are trying to use `" ++ keyword ++ "` as a variable name:"
4940 D.reflow $
4941 "This is a reserved word! Try using some other name?"
4944 _ ->
4945 let
4946 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4947 region = toRegion row col
4948 in
4949 Report.Report "UNFINISHED PARENTHESES" region [] $
4950 Code.toSnippet source surroundings (Just region)
4952 D.reflow $
4953 "I just saw an open parenthesis, but I got stuck here:"
4955 D.fillSep
4956 ["I","was","expecting","to","see","a","pattern","next."
4957 ,"Maybe","it","will","end","up","being","something"
4958 ,"like",D.dullyellow "(x,y)","or",D.dullyellow "(name, _)" <> "?"
4962 PTupleEnd row col ->
4963 case Code.whatIsNext source row col of
4964 Code.Keyword keyword ->
4965 let
4966 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4967 region = toKeywordRegion row col keyword
4968 in
4969 Report.Report "RESERVED WORD" region [] $
4970 Code.toSnippet source surroundings (Just region) $
4972 D.reflow $
4973 "I ran into a reserved word in this pattern:"
4975 D.reflow $
4976 "The `" ++ keyword ++ "` keyword is reserved. Try using a different name instead!"
4979 Code.Operator op ->
4980 let
4981 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4982 region = toKeywordRegion row col op
4983 in
4984 Report.Report "UNEXPECTED SYMBOL" region [] $
4985 Code.toSnippet source surroundings (Just region) $
4987 D.reflow $
4988 "I ran into the " ++ op ++ " symbol unexpectedly in this pattern:"
4990 D.reflow $
4991 "Only the :: symbol that works in patterns. It is useful if you\
4992 \ are pattern matching on lists, trying to get the first element\
4993 \ off the front. Did you want that instead?"
4996 Code.Close term bracket ->
4997 let
4998 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4999 region = toRegion row col
5000 in
5001 Report.Report ("STRAY " ++ map Char.toUpper term) region [] $
5002 Code.toSnippet source surroundings (Just region) $
5004 D.reflow $
5005 "I ran into a an unexpected " ++ term ++ " in this pattern:"
5007 D.reflow $
5008 "This " ++ bracket : " does not match up with an earlier open " ++ term ++ ". Try deleting it?"
5011 _ ->
5012 let
5013 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5014 region = toRegion row col
5015 in
5016 Report.Report "UNFINISHED PARENTHESES" region [] $
5017 Code.toSnippet source surroundings (Just region) $
5019 D.reflow $
5020 "I was partway through parsing a pattern, but I got stuck here:"
5022 D.fillSep
5023 ["I","was","expecting","a","closing","parenthesis","next,","so"
5024 ,"try","adding","a",D.dullyellow ")","to","see","if","that","helps?"
5028 PTupleExpr pattern row col ->
5029 toPatternReport source context pattern row col
5031 PTupleSpace space row col ->
5032 toSpaceReport source space row col
5034 PTupleIndentEnd row col ->
5035 let
5036 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5037 region = toRegion row col
5038 in
5039 Report.Report "UNFINISHED PARENTHESES" region [] $
5040 Code.toSnippet source surroundings (Just region) $
5042 D.reflow $
5043 "I was expecting a closing parenthesis next:"
5045 D.stack
5046 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps?"]
5047 , D.toSimpleNote $
5048 "I can get confused by indentation in cases like this, so\
5049 \ maybe you have a closing parenthesis but it is not indented enough?"
5053 PTupleIndentExpr1 row col ->
5054 let
5055 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5056 region = toRegion row col
5057 in
5058 Report.Report "UNFINISHED PARENTHESES" region [] $
5059 Code.toSnippet source surroundings (Just region) $
5061 D.reflow $
5062 "I just saw an open parenthesis, but then I got stuck here:"
5064 D.fillSep
5065 ["I","was","expecting","to","see","a","pattern","next."
5066 ,"Maybe","it","will","end","up","being","something"
5067 ,"like",D.dullyellow "(x,y)","or",D.dullyellow "(name, _)" <> "?"
5071 PTupleIndentExprN row col ->
5072 let
5073 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5074 region = toRegion row col
5075 in
5076 Report.Report "UNFINISHED TUPLE PATTERN" region [] $
5077 Code.toSnippet source surroundings (Just region) $
5079 D.reflow $
5080 "I am partway through parsing a tuple pattern, but I got stuck here:"
5082 D.stack
5083 [ D.fillSep
5084 ["I","was","expecting","to","see","a","pattern","next."
5085 ,"I","am","expecting","the","final","result","to","be","something"
5086 ,"like",D.dullyellow "(x,y)","or",D.dullyellow "(name, _)" <> "."
5088 , D.toSimpleNote $
5089 "I can get confused by indentation in cases like this, so the problem\
5090 \ may be that the next part is not indented enough?"
5095toPListReport :: Code.Source -> PContext -> PList -> Row -> Col -> Report.Report
5096toPListReport source context list startRow startCol =
5097 case list of
5098 PListOpen row col ->
5099 case Code.whatIsNext source row col of
5100 Code.Keyword keyword ->
5101 let
5102 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5103 region = toKeywordRegion row col keyword
5104 in
5105 Report.Report "RESERVED WORD" region [] $
5106 Code.toSnippet source surroundings (Just region)
5108 D.reflow $
5109 "It looks like you are trying to use `" ++ keyword ++ "` to name an element of a list:"
5111 D.reflow $
5112 "This is a reserved word though! Try using some other name?"
5115 _ ->
5116 let
5117 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5118 region = toRegion row col
5119 in
5120 Report.Report "UNFINISHED LIST PATTERN" region [] $
5121 Code.toSnippet source surroundings (Just region) $
5123 D.reflow $
5124 "I just saw an open square bracket, but then I got stuck here:"
5126 D.fillSep ["Try","adding","a",D.dullyellow "]","to","see","if","that","helps?"]
5129 PListEnd row col ->
5130 let
5131 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5132 region = toRegion row col
5133 in
5134 Report.Report "UNFINISHED LIST PATTERN" region [] $
5135 Code.toSnippet source surroundings (Just region) $
5137 D.reflow $
5138 "I was expecting a closing square bracket to end this list pattern:"
5140 D.fillSep ["Try","adding","a",D.dullyellow "]","to","see","if","that","helps?"]
5143 PListExpr pattern row col ->
5144 toPatternReport source context pattern row col
5146 PListSpace space row col ->
5147 toSpaceReport source space row col
5149 PListIndentOpen row col ->
5150 let
5151 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5152 region = toRegion row col
5153 in
5154 Report.Report "UNFINISHED LIST PATTERN" region [] $
5155 Code.toSnippet source surroundings (Just region) $
5157 D.reflow $
5158 "I just saw an open square bracket, but then I got stuck here:"
5160 D.stack
5161 [ D.fillSep ["Try","adding","a",D.dullyellow "]","to","see","if","that","helps?"]
5162 , D.toSimpleNote $
5163 "I can get confused by indentation in cases like this, so\
5164 \ maybe there is something next, but it is not indented enough?"
5168 PListIndentEnd row col ->
5169 let
5170 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5171 region = toRegion row col
5172 in
5173 Report.Report "UNFINISHED LIST PATTERN" region [] $
5174 Code.toSnippet source surroundings (Just region) $
5176 D.reflow $
5177 "I was expecting a closing square bracket to end this list pattern:"
5179 D.stack
5180 [ D.fillSep ["Try","adding","a",D.dullyellow "]","to","see","if","that","helps?"]
5181 , D.toSimpleNote $
5182 "I can get confused by indentation in cases like this, so\
5183 \ maybe you have a closing square bracket but it is not indented enough?"
5187 PListIndentExpr row col ->
5188 let
5189 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5190 region = toRegion row col
5191 in
5192 Report.Report "UNFINISHED LIST PATTERN" region [] $
5193 Code.toSnippet source surroundings (Just region) $
5195 D.reflow $
5196 "I am partway through parsing a list pattern, but I got stuck here:"
5198 D.stack
5199 [ D.reflow $
5200 "I was expecting to see another pattern next. Maybe a variable name."
5201 , D.toSimpleNote $
5202 "I can get confused by indentation in cases like this, so\
5203 \ maybe there is more to this pattern but it is not indented enough?"
5209-- TYPES
5212data TContext
5213 = TC_Annotation Name.Name
5214 | TC_CustomType
5215 | TC_TypeAlias
5216 | TC_Port
5219toTypeReport :: Code.Source -> TContext -> Type -> Row -> Col -> Report.Report
5220toTypeReport source context tipe startRow startCol =
5221 case tipe of
5222 TRecord record row col ->
5223 toTRecordReport source context record row col
5225 TTuple tuple row col ->
5226 toTTupleReport source context tuple row col
5228 TStart row col ->
5229 case Code.whatIsNext source row col of
5230 Code.Keyword keyword ->
5231 let
5232 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5233 region = toKeywordRegion row col keyword
5234 in
5235 Report.Report "RESERVED WORD" region [] $
5236 Code.toSnippet source surroundings (Just region)
5238 D.reflow $
5239 "I was expecting to see a type next, but I got stuck on this reserved word:"
5241 D.reflow $
5242 "It looks like you are trying to use `" ++ keyword ++ "` as a type variable, but \
5243 \ it is a reserved word. Try using a different name!"
5246 _ ->
5247 let
5248 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5249 region = toRegion row col
5251 thing =
5252 case context of
5253 TC_Annotation _ -> "type annotation"
5254 TC_CustomType -> "custom type"
5255 TC_TypeAlias -> "type alias"
5256 TC_Port -> "port"
5258 something =
5259 case context of
5260 TC_Annotation name -> "the `" ++ Name.toChars name ++ "` type annotation"
5261 TC_CustomType -> "a custom type"
5262 TC_TypeAlias -> "a type alias"
5263 TC_Port -> "a port"
5264 in
5265 Report.Report ("PROBLEM IN " ++ map Char.toUpper thing) region [] $
5266 Code.toSnippet source surroundings (Just region)
5268 D.reflow $
5269 "I was partway through parsing " ++ something ++ ", but I got stuck here:"
5271 D.fillSep $
5272 ["I","was","expecting","to","see","a","type","next."
5273 ,"Try","putting",D.dullyellow "Int","or",D.dullyellow "String","for","now?"
5277 TSpace space row col ->
5278 toSpaceReport source space row col
5280 TIndentStart row col ->
5281 let
5282 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5283 region = toRegion row col
5285 thing =
5286 case context of
5287 TC_Annotation _ -> "type annotation"
5288 TC_CustomType -> "custom type"
5289 TC_TypeAlias -> "type alias"
5290 TC_Port -> "port"
5291 in
5292 Report.Report ("UNFINISHED " ++ map Char.toUpper thing) region [] $
5293 Code.toSnippet source surroundings (Just region)
5295 D.reflow $
5296 "I was partway through parsing a " ++ thing ++ ", but I got stuck here:"
5298 D.stack
5299 [ D.fillSep $
5300 ["I","was","expecting","to","see","a","type","next."
5301 ,"Try","putting",D.dullyellow "Int","or",D.dullyellow "String","for","now?"
5303 , D.toSimpleNote $
5304 "I can get confused by indentation. If you think there is already a type\
5305 \ next, maybe it is not indented enough?"
5310toTRecordReport :: Code.Source -> TContext -> TRecord -> Row -> Col -> Report.Report
5311toTRecordReport source context record startRow startCol =
5312 case record of
5313 TRecordOpen row col ->
5314 case Code.whatIsNext source row col of
5315 Code.Keyword keyword ->
5316 let
5317 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5318 region = toKeywordRegion row col keyword
5319 in
5320 Report.Report "RESERVED WORD" region [] $
5321 Code.toSnippet source surroundings (Just region)
5323 D.reflow $
5324 "I just started parsing a record type, but I got stuck on this field name:"
5326 D.reflow $
5327 "It looks like you are trying to use `" ++ keyword ++ "` as a field name, but \
5328 \ that is a reserved word. Try using a different name!"
5331 _ ->
5332 let
5333 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5334 region = toRegion row col
5335 in
5336 Report.Report "UNFINISHED RECORD TYPE" region [] $
5337 Code.toSnippet source surroundings (Just region)
5339 D.reflow $
5340 "I just started parsing a record type, but I got stuck here:"
5342 D.fillSep
5343 ["Record","types","look","like",D.dullyellow "{ name : String, age : Int },"
5344 ,"so","I","was","expecting","to","see","a","field","name","next."
5348 TRecordEnd row col ->
5349 let
5350 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5351 region = toRegion row col
5352 in
5353 Report.Report "UNFINISHED RECORD TYPE" region [] $
5354 Code.toSnippet source surroundings (Just region)
5356 D.reflow $
5357 "I am partway through parsing a record type, but I got stuck here:"
5359 D.stack
5360 [ D.fillSep
5361 ["I","was","expecting","to","see","a","closing","curly","brace","before","this,"
5362 ,"so","try","adding","a",D.dullyellow "}","and","see","if","that","helps?"
5364 , D.toSimpleNote $
5365 "When I get stuck like this, it usually means that there is a missing parenthesis\
5366 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
5370 TRecordField row col ->
5371 case Code.whatIsNext source row col of
5372 Code.Keyword keyword ->
5373 let
5374 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5375 region = toKeywordRegion row col keyword
5376 in
5377 Report.Report "RESERVED WORD" region [] $
5378 Code.toSnippet source surroundings (Just region)
5380 D.reflow $
5381 "I am partway through parsing a record type, but I got stuck on this field name:"
5383 D.reflow $
5384 "It looks like you are trying to use `" ++ keyword ++ "` as a field name, but \
5385 \ that is a reserved word. Try using a different name!"
5388 Code.Other (Just ',') ->
5389 let
5390 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5391 region = toRegion row col
5392 in
5393 Report.Report "EXTRA COMMA" region [] $
5394 Code.toSnippet source surroundings (Just region)
5396 D.reflow $
5397 "I am partway through parsing a record type, but I got stuck here:"
5399 D.stack
5400 [ D.reflow $
5401 "I am seeing two commas in a row. This is the second one!"
5402 , D.reflow $
5403 "Just delete one of the commas and you should be all set!"
5404 , noteForRecordTypeError
5408 Code.Close _ '}' ->
5409 let
5410 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5411 region = toRegion row col
5412 in
5413 Report.Report "EXTRA COMMA" region [] $
5414 Code.toSnippet source surroundings (Just region)
5416 D.reflow $
5417 "I am partway through parsing a record type, but I got stuck here:"
5419 D.stack
5420 [ D.reflow $
5421 "Trailing commas are not allowed in record types. Try deleting the comma that\
5422 \ appears before this closing curly brace."
5423 , noteForRecordTypeError
5427 _ ->
5428 let
5429 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5430 region = toRegion row col
5431 in
5432 Report.Report "PROBLEM IN RECORD TYPE" region [] $
5433 Code.toSnippet source surroundings (Just region)
5435 D.reflow $
5436 "I am partway through parsing a record type, but I got stuck here:"
5438 D.stack
5439 [ D.fillSep
5440 ["I","was","expecting","to","see","another","record","field","defined","next,"
5441 ,"so","I","am","looking","for","a","name","like"
5442 ,D.dullyellow "userName","or",D.dullyellow "plantHeight" <> "."
5444 , noteForRecordTypeError
5448 TRecordColon row col ->
5449 let
5450 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5451 region = toRegion row col
5452 in
5453 Report.Report "UNFINISHED RECORD TYPE" region [] $
5454 Code.toSnippet source surroundings (Just region)
5456 D.reflow $
5457 "I am partway through parsing a record type, but I got stuck here:"
5459 D.stack
5460 [ D.fillSep $
5461 ["I","just","saw","a","field","name,","so","I","was","expecting","to","see"
5462 ,"a","colon","next.","So","try","putting","an",D.green ":","sign","here?"
5464 , noteForRecordTypeError
5468 TRecordType tipe row col ->
5469 toTypeReport source context tipe row col
5471 TRecordSpace space row col ->
5472 toSpaceReport source space row col
5474 TRecordIndentOpen row col ->
5475 let
5476 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5477 region = toRegion row col
5478 in
5479 Report.Report "UNFINISHED RECORD TYPE" region [] $
5480 Code.toSnippet source surroundings (Just region)
5482 D.reflow $
5483 "I just saw the opening curly brace of a record type, but then I got stuck here:"
5485 D.stack
5486 [ D.fillSep $
5487 ["I","am","expecting","a","record","like",D.dullyellow "{ name : String, age : Int }","here."
5488 ,"Try","defining","some","fields","of","your","own?"
5490 , noteForRecordTypeIndentError
5494 TRecordIndentEnd row col ->
5495 case Code.nextLineStartsWithCloseCurly source row of
5496 Just (curlyRow, curlyCol) ->
5497 let
5498 surroundings = A.Region (A.Position startRow startCol) (A.Position curlyRow curlyCol)
5499 region = toRegion curlyRow curlyCol
5500 in
5501 Report.Report "NEED MORE INDENTATION" region [] $
5502 Code.toSnippet source surroundings (Just region)
5504 D.reflow $
5505 "I was partway through parsing a record type, but I got stuck here:"
5507 D.stack
5508 [ D.reflow $
5509 "I need this curly brace to be indented more. Try adding some spaces before it!"
5510 , noteForRecordTypeError
5514 Nothing ->
5515 let
5516 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5517 region = toRegion row col
5518 in
5519 Report.Report "UNFINISHED RECORD TYPE" region [] $
5520 Code.toSnippet source surroundings (Just region)
5522 D.reflow $
5523 "I was partway through parsing a record type, but I got stuck here:"
5525 D.stack
5526 [ D.fillSep $
5527 ["I","was","expecting","to","see","a","closing","curly","brace","next."
5528 ,"Try","putting","a",D.green "}","next","and","see","if","that","helps?"
5530 , noteForRecordTypeIndentError
5534 TRecordIndentField row col ->
5535 let
5536 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5537 region = toRegion row col
5538 in
5539 Report.Report "UNFINISHED RECORD TYPE" region [] $
5540 Code.toSnippet source surroundings (Just region)
5542 D.reflow $
5543 "I am partway through parsing a record type, but I got stuck after that last comma:"
5545 D.stack
5546 [ D.reflow $
5547 "Trailing commas are not allowed in record types, so the fix may be to\
5548 \ delete that last comma? Or maybe you were in the middle of defining\
5549 \ an additional field?"
5550 , noteForRecordTypeIndentError
5554 TRecordIndentColon row col ->
5555 let
5556 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5557 region = toRegion row col
5558 in
5559 Report.Report "UNFINISHED RECORD TYPE" region [] $
5560 Code.toSnippet source surroundings (Just region)
5562 D.reflow $
5563 "I am partway through parsing a record type. I just saw a record\
5564 \ field, so I was expecting to see a colon next:"
5566 D.stack
5567 [ D.fillSep $
5568 ["Try","putting","an",D.green ":","followed","by","a","type?"
5570 , noteForRecordTypeIndentError
5574 TRecordIndentType row col ->
5575 let
5576 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5577 region = toRegion row col
5578 in
5579 Report.Report "UNFINISHED RECORD TYPE" region [] $
5580 Code.toSnippet source surroundings (Just region)
5582 D.reflow $
5583 "I am partway through parsing a record type, and I was expecting to run into a type next:"
5585 D.stack
5586 [ D.fillSep $
5587 ["Try","putting","something","like"
5588 ,D.dullyellow "Int","or",D.dullyellow "String","for","now?"
5590 , noteForRecordTypeIndentError
5595noteForRecordTypeError :: D.Doc
5596noteForRecordTypeError =
5597 D.stack $
5598 [ D.toSimpleNote
5599 "If you are trying to define a record type across multiple lines, I recommend using this format:"
5600 , D.indent 4 $ D.vcat $
5601 [ "{ name : String"
5602 , ", age : Int"
5603 , ", height : Float"
5604 , "}"
5606 , D.reflow $
5607 "Notice that each line starts with some indentation. Usually two or four spaces. I\
5608 \ know this style can be jarring for people coming from C-like syntax, but folks generally\
5609 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
5613noteForRecordTypeIndentError :: D.Doc
5614noteForRecordTypeIndentError =
5615 D.stack $
5616 [ D.toSimpleNote
5617 "I may be confused by indentation. For example, if you are trying to define\
5618 \ a record type across multiple lines, I recommend using this format:"
5619 , D.indent 4 $ D.vcat $
5620 [ "{ name : String"
5621 , ", age : Int"
5622 , ", height : Float"
5623 , "}"
5625 , D.reflow $
5626 "Notice that each line starts with some indentation. Usually two or four spaces. I\
5627 \ know this style can be jarring for people coming from C-like syntax, but folks generally\
5628 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
5632toTTupleReport :: Code.Source -> TContext -> TTuple -> Row -> Col -> Report.Report
5633toTTupleReport source context tuple startRow startCol =
5634 case tuple of
5635 TTupleOpen row col ->
5636 case Code.whatIsNext source row col of
5637 Code.Keyword keyword ->
5638 let
5639 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5640 region = toKeywordRegion row col keyword
5641 in
5642 Report.Report "RESERVED WORD" region [] $
5643 Code.toSnippet source surroundings (Just region)
5645 D.reflow $
5646 "I ran into a reserved word unexpectedly:"
5648 D.reflow $
5649 "It looks like you are trying to use `" ++ keyword ++ "` as a variable name, but \
5650 \ it is a reserved word. Try using a different name!"
5653 _ ->
5654 let
5655 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5656 region = toRegion row col
5657 in
5658 Report.Report "UNFINISHED PARENTHESES" region [] $
5659 Code.toSnippet source surroundings (Just region)
5661 D.reflow $
5662 "I just saw an open parenthesis, so I was expecting to see a type next."
5664 D.fillSep $
5665 ["Something","like",D.dullyellow "(Maybe Int)","or"
5666 ,D.dullyellow "(List Person)" <> "."
5667 ,"Anything","where","you","are","putting","parentheses","around","normal","types."
5671 TTupleEnd row col ->
5672 let
5673 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5674 region = toRegion row col
5675 in
5676 Report.Report "UNFINISHED PARENTHESES" region [] $
5677 Code.toSnippet source surroundings (Just region)
5679 D.reflow $
5680 "I was expecting to see a closing parenthesis next, but I got stuck here:"
5682 D.stack
5683 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps?"]
5684 , D.toSimpleNote $
5685 "I can get stuck when I run into keywords, operators, parentheses, or brackets\
5686 \ unexpectedly. So there may be some earlier syntax trouble (like extra parenthesis\
5687 \ or missing brackets) that is confusing me."
5691 TTupleType tipe row col ->
5692 toTypeReport source context tipe row col
5694 TTupleSpace space row col ->
5695 toSpaceReport source space row col
5697 TTupleIndentType1 row col ->
5698 let
5699 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5700 region = toRegion row col
5701 in
5702 Report.Report "UNFINISHED PARENTHESES" region [] $
5703 Code.toSnippet source surroundings (Just region)
5705 D.reflow $
5706 "I just saw an open parenthesis, so I was expecting to see a type next."
5708 D.stack
5709 [ D.fillSep $
5710 ["Something","like",D.dullyellow "(Maybe Int)","or"
5711 ,D.dullyellow "(List Person)" <> "."
5712 ,"Anything","where","you","are","putting","parentheses","around","normal","types."
5714 , D.toSimpleNote $
5715 "I can get confused by indentation in cases like this, so\
5716 \ maybe you have a type but it is not indented enough?"
5720 TTupleIndentTypeN row col ->
5721 let
5722 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5723 region = toRegion row col
5724 in
5725 Report.Report "UNFINISHED TUPLE TYPE" region [] $
5726 Code.toSnippet source surroundings (Just region)
5728 D.reflow $
5729 "I think I am in the middle of parsing a tuple type. I just saw a comma, so I was expecting to see a type next."
5731 D.stack
5732 [ D.fillSep $
5733 ["A","tuple","type","looks","like",D.dullyellow "(Float,Float)","or"
5734 ,D.dullyellow "(String,Int)" <> ","
5735 ,"so","I","think","there","is","a","type","missing","here?"
5737 , D.toSimpleNote $
5738 "I can get confused by indentation in cases like this, so\
5739 \ maybe you have an expression but it is not indented enough?"
5743 TTupleIndentEnd row col ->
5744 let
5745 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5746 region = toRegion row col
5747 in
5748 Report.Report "UNFINISHED PARENTHESES" region [] $
5749 Code.toSnippet source surroundings (Just region)
5751 D.reflow $
5752 "I was expecting to see a closing parenthesis next:"
5754 D.stack
5755 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps!"]
5756 , D.toSimpleNote $
5757 "I can get confused by indentation in cases like this, so\
5758 \ maybe you have a closing parenthesis but it is not indented enough?"