1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
3module Reporting.Error.Syntax
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
68 = ModuleNameUnspecified ModuleName.Raw
69 | ModuleNameMismatch ModuleName.Raw (A.Located ModuleName.Raw)
70 | UnexpectedPort A.Region
80 = ModuleSpace Space Row Col
81 | ModuleBadEnd Row Col
83 | ModuleProblem Row Col
85 | ModuleExposing Exposing Row Col
87 | PortModuleProblem Row Col
88 | PortModuleName Row Col
89 | PortModuleExposing Exposing Row Col
99 | ImportExposing Row Col
100 | ImportExposingList Exposing Row Col
101 | ImportEnd Row Col -- different based on col=1 or if greater
103 | ImportIndentName Row Col
104 | ImportIndentAlias Row Col
105 | ImportIndentExposingList Row Col
109 | Declarations Decl Row Col
113 = ExposingSpace Space Row Col
114 | ExposingStart Row Col
115 | ExposingValue Row Col
116 | ExposingOperator Row Col
117 | ExposingOperatorReserved BadOperator Row Col
118 | ExposingOperatorRightParen Row Col
119 | ExposingTypePrivacy Row Col
120 | ExposingEnd Row Col
122 | ExposingIndentEnd Row Col
123 | ExposingIndentValue Row Col
132 | DeclSpace Space Row Col
135 | DeclType DeclType Row Col
136 | DeclDef Name.Name DeclDef Row Col
138 | DeclFreshLineAfterDocComment Row Col
142 = DeclDefSpace Space Row Col
143 | DeclDefEquals Row Col
144 | DeclDefType Type Row Col
145 | DeclDefArg Pattern Row Col
146 | DeclDefBody Expr Row Col
147 | DeclDefNameRepeat Row Col
148 | DeclDefNameMatch Name.Name Row Col
150 | DeclDefIndentType Row Col
151 | DeclDefIndentEquals Row Col
152 | DeclDefIndentBody Row Col
156 = PortSpace Space Row Col
159 | PortType Type Row Col
160 | PortIndentName Row Col
161 | PortIndentColon Row Col
162 | PortIndentType Row Col
170 = DT_Space Space Row Col
172 | DT_Alias TypeAlias Row Col
173 | DT_Union CustomType Row Col
175 | DT_IndentName Row Col
179 = AliasSpace Space Row Col
181 | AliasEquals Row Col
182 | AliasBody Type Row Col
184 | AliasIndentEquals Row Col
185 | AliasIndentBody Row Col
189 = CT_Space Space Row Col
194 | CT_VariantArg Type Row Col
196 | CT_IndentEquals Row Col
197 | CT_IndentBar Row Col
198 | CT_IndentAfterBar Row Col
199 | CT_IndentAfterEquals Row Col
211 | Record Record Row Col
212 | Tuple Tuple Row Col
217 | OperatorRight Name.Name Row Col
218 | OperatorReserved BadOperator Row Col
222 | String String Row Col
223 | Number Number Row Col
224 | Space Space Row Col
225 | EndlessShader Row Col
226 | ShaderProblem [Char.Char] Row Col
227 | IndentOperatorRight Name.Name Row Col
233 | RecordField Row Col
234 | RecordEquals Row Col
235 | RecordExpr Expr Row Col
236 | RecordSpace Space Row Col
238 | RecordIndentOpen Row Col
239 | RecordIndentEnd Row Col
240 | RecordIndentField Row Col
241 | RecordIndentEquals Row Col
242 | RecordIndentExpr Row Col
246 = TupleExpr Expr Row Col
247 | TupleSpace Space Row Col
249 | TupleOperatorClose Row Col
250 | TupleOperatorReserved BadOperator Row Col
252 | TupleIndentExpr1 Row Col
253 | TupleIndentExprN Row Col
254 | TupleIndentEnd Row Col
258 = ListSpace Space Row Col
260 | ListExpr Expr Row Col
263 | ListIndentOpen Row Col
264 | ListIndentEnd Row Col
265 | ListIndentExpr Row Col
269 = FuncSpace Space Row Col
270 | FuncArg Pattern Row Col
271 | FuncBody Expr Row Col
274 | FuncIndentArg Row Col
275 | FuncIndentArrow Row Col
276 | FuncIndentBody Row Col
280 = CaseSpace Space Row Col
282 | CasePattern Pattern Row Col
284 | CaseExpr Expr Row Col
285 | CaseBranch Expr Row Col
287 | CaseIndentOf Row Col
288 | CaseIndentExpr Row Col
289 | CaseIndentPattern Row Col
290 | CaseIndentArrow Row Col
291 | CaseIndentBranch Row Col
292 | CasePatternAlignment Word16 Row Col
296 = IfSpace Space Row Col
299 | IfElseBranchStart Row Col
301 | IfCondition Expr Row Col
302 | IfThenBranch Expr Row Col
303 | IfElseBranch Expr Row Col
305 | IfIndentCondition Row Col
306 | IfIndentThen Row Col
307 | IfIndentThenBranch Row Col
308 | IfIndentElseBranch Row Col
309 | IfIndentElse Row Col
313 = LetSpace Space Row Col
315 | LetDefAlignment Word16 Row Col
317 | LetDef Name.Name Def Row Col
318 | LetDestruct Destruct Row Col
319 | LetBody Expr Row Col
320 | LetIndentDef Row Col
321 | LetIndentIn Row Col
322 | LetIndentBody Row Col
326 = DefSpace Space Row Col
327 | DefType Type Row Col
328 | DefNameRepeat Row Col
329 | DefNameMatch Name.Name Row Col
330 | DefArg Pattern Row Col
332 | DefBody Expr Row Col
333 | DefIndentEquals Row Col
334 | DefIndentType Row Col
335 | DefIndentBody Row Col
336 | DefAlignment Word16 Row Col
340 = DestructSpace Space Row Col
341 | DestructPattern Pattern Row Col
342 | DestructEquals Row Col
343 | DestructBody Expr Row Col
344 | DestructIndentEquals Row Col
345 | DestructIndentBody Row Col
353 = PRecord PRecord Row Col
354 | PTuple PTuple Row Col
355 | PList PList Row Col
359 | PString String Row Col
360 | PNumber Number Row Col
361 | PFloat Word16 Row Col
363 | PWildcardNotVar Name.Name Int Row Col
364 | PSpace Space Row Col
366 | PIndentStart Row Col
367 | PIndentAlias Row Col
371 = PRecordOpen Row Col
373 | PRecordField Row Col
374 | PRecordSpace Space Row Col
376 | PRecordIndentOpen Row Col
377 | PRecordIndentEnd Row Col
378 | PRecordIndentField Row Col
384 | PTupleExpr Pattern Row Col
385 | PTupleSpace Space Row Col
387 | PTupleIndentEnd Row Col
388 | PTupleIndentExpr1 Row Col
389 | PTupleIndentExprN Row Col
395 | PListExpr Pattern Row Col
396 | PListSpace Space Row Col
398 | PListIndentOpen Row Col
399 | PListIndentEnd Row Col
400 | PListIndentExpr Row Col
408 = TRecord TRecord Row Col
409 | TTuple TTuple Row Col
412 | TSpace Space Row Col
414 | TIndentStart Row Col
418 = TRecordOpen Row Col
421 | TRecordField Row Col
422 | TRecordColon Row Col
423 | TRecordType Type Row Col
425 | TRecordSpace Space Row Col
427 | TRecordIndentOpen Row Col
428 | TRecordIndentField Row Col
429 | TRecordIndentColon Row Col
430 | TRecordIndentType Row Col
431 | TRecordIndentEnd Row Col
437 | TTupleType Type Row Col
438 | TTupleSpace Space Row Col
440 | TTupleIndentType1 Row Col
441 | TTupleIndentTypeN Row Col
442 | TTupleIndentEnd Row Col
452 | CharNotString Word16
456 = StringEndless_Single
457 | StringEndless_Multi
458 | StringEscape Escape
463 | BadUnicodeFormat Word16
464 | BadUnicodeCode Word16
465 | BadUnicodeLength Word16 Int Int
472 | NumberNoLeadingZero
481 | EndlessMultiComment
488toReport :: Code.Source -> Error -> Report.Report
491 ModuleNameUnspecified name ->
493 region = toRegion 1 1
495 Report.Report "MODULE NAME MISSING" region [] $
498 "I need the module name to be declared at the top of this file, like this:"
499 , D.indent 4 $ D.fillSep $
500 [ D.cyan "module", D.fromName name, D.cyan "exposing", "(..)" ]
502 "Try adding that as the first line of your file!"
504 "It is best to replace (..) with an explicit list of types and\
505 \ functions you want to expose. When you know a value is only used\
506 \ within this module, you can refactor without worrying about uses\
507 \ elsewhere. Limiting exposed values can also speed up compilation\
508 \ because I can skip a bunch of work if I see that the exposed API\
512 ModuleNameMismatch expectedName (A.At region actualName) ->
513 Report.Report "MODULE NAME MISMATCH" region [ModuleName.toChars expectedName] $
514 Code.toSnippet source region Nothing
516 "It looks like this module name is out of sync:"
520 "I need it to match the file path, so I was expecting to see `"
521 ++ ModuleName.toChars expectedName
522 ++ "` here. Make the following change, and you should be all set!"
524 D.dullyellow (D.fromName actualName) <> " -> " <> D.green (D.fromName expectedName)
526 "I require that module names correspond to file paths. This makes it much\
527 \ easier to explore unfamiliar codebases! So if you want to keep the current\
528 \ module name, try renaming the file instead."
532 UnexpectedPort region ->
533 Report.Report "UNEXPECTED PORTS" region [] $
534 Code.toSnippet source region Nothing
537 "You are declaring ports in a normal module."
541 ["Switch","this","to","say",D.cyan "port module","instead,"
542 ,"marking","that","this","module","contains","port","declarations."
545 "Ports are not a traditional FFI for calling JS functions directly. They need a different mindset! Read"
547 "to learn the syntax and how to use it effectively."
552 Report.Report "NO PORTS" region [] $
553 Code.toSnippet source region Nothing
556 "This module does not declare any ports, but it says it will:"
559 ["Switch","this","to",D.cyan "module"
560 ,"and","you","should","be","all","set!"
565 toParseErrorReport source modul
568toParseErrorReport :: Code.Source -> Module -> Report.Report
569toParseErrorReport source modul =
571 ModuleSpace space row col ->
572 toSpaceReport source space row col
574 ModuleBadEnd row col ->
575 case Code.whatIsNext source row col of
576 Code.Keyword keyword ->
578 region = toKeywordRegion row col keyword
580 Report.Report "RESERVED WORD" region [] $
581 Code.toSnippet source region Nothing
584 "I got stuck on this reserved word:"
587 "The name `" ++ keyword ++ "` is reserved, so try using a different name?"
592 region = toKeywordRegion row col op
594 Report.Report "UNEXPECTED SYMBOL" region [] $
595 Code.toSnippet source region Nothing
598 "I ran into an unexpected symbol:"
601 "I was not expecting to see a " ++ op ++ " here. Try deleting it? Maybe\
602 \ I can give a better hint from there?"
605 Code.Close term bracket ->
607 region = toRegion row col
609 Report.Report ("UNEXPECTED " ++ map Char.toUpper term) region [] $
610 Code.toSnippet source region Nothing
613 "I ran into an unexpected " ++ term ++ ":"
616 "This " ++ bracket : " does not match up with an earlier open " ++ term ++ ". Try deleting it?"
619 Code.Other maybeChar ->
621 region = toRegion row col
625 Report.Report "UNEXPECTED SEMICOLON" region [] $
626 Code.toSnippet source region Nothing
629 "I got stuck on this semicolon:"
632 [ D.reflow $ "Try removing it?"
634 "Some languages require semicolons at the end of each statement. These are\
635 \ often called C-like languages, and they usually share a lot of language design\
636 \ choices. (E.g. side-effects, for loops, etc.) Elm manages effects with commands\
637 \ and subscriptions instead, so there is no special syntax for \"statements\" and\
638 \ therefore no need to use semicolons to separate them. I think this will make\
639 \ more sense as you work through <https://guide.elm-lang.org> though!"
644 Report.Report "UNEXPECTED COMMA" region [] $
645 Code.toSnippet source region Nothing
648 "I got stuck on this comma:"
652 "I do not think I am parsing a list or tuple right now. Try deleting the comma?"
654 "If this is supposed to be part of a list, the problem may be a bit earlier.\
655 \ Perhaps the opening [ is missing? Or perhaps some value in the list has an extra\
656 \ closing ] that is making me think the list ended earlier? The same kinds of\
657 \ things could be going wrong if this is supposed to be a tuple."
662 Report.Report "UNEXPECTED CHARACTER" region [] $
663 Code.toSnippet source region Nothing
666 "I got stuck on this character:"
670 "It is not used for anything in Elm syntax. It is used for multi-line strings in\
671 \ some languages though, so if you want a string that spans multiple lines, you\
672 \ can use Elm's multi-line string syntax like this:"
674 [ D.fillSep [D.green "markdown","=",D.dullyellow "\"\"\""]
676 , D.dullyellow "# Multi-line Strings"
678 , D.dullyellow "- start with triple double quotes"
679 , D.dullyellow "- write whatever you want"
680 , D.dullyellow "- no need to escape newlines or double quotes"
681 , D.dullyellow "- end with triple double quotes"
683 , D.dullyellow "\"\"\""
686 "Otherwise I do not know what is going on! Try removing the character?"
691 Report.Report "UNEXPECTED SYMBOL" region [] $
692 Code.toSnippet source region Nothing
695 "I got stuck on this dollar sign:"
698 "It is not used for anything in Elm syntax. Are you coming from a language where\
699 \ dollar signs can be used in variable names? If so, try a name that (1) starts\
700 \ with a letter and (2) only contains letters, numbers, and underscores."
703 Just c | elem c ['#','@','!','%','~'] ->
704 Report.Report "UNEXPECTED SYMBOL" region [] $
705 Code.toSnippet source region Nothing
708 "I got stuck on this symbol:"
711 "It is not used for anything in Elm syntax. Try removing it?"
715 Report.Report "SYNTAX PROBLEM" region [] $
716 Code.toSnippet source region Nothing
722 "Whatever I am running into is confusing me a lot! Normally I can give fairly\
723 \ specific hints, but something is really tripping me up this time."
726 ModuleProblem row col ->
728 region = toRegion row col
730 Report.Report "UNFINISHED MODULE DECLARATION" region [] $
731 Code.toSnippet source region Nothing
734 "I am parsing an `module` declaration, but I got stuck here:"
738 "Here are some examples of valid `module` declarations:"
739 , D.indent 4 $ D.vcat $
740 [ D.fillSep [D.cyan "module","Main",D.cyan "exposing","(..)"]
741 , D.fillSep [D.cyan "module","Dict",D.cyan "exposing","(Dict, empty, get)"]
744 "I generally recommend using an explicit exposing list. I can skip compiling a bunch\
745 \ of files when the public interface of a module stays the same, so exposing fewer\
746 \ values can help improve compile times!"
750 ModuleName row col ->
752 region = toRegion row col
754 Report.Report "EXPECTING MODULE NAME" region [] $
755 Code.toSnippet source region Nothing
758 "I was parsing an `module` declaration until I got stuck here:"
762 "I was expecting to see the module name next, like in these examples:"
763 , D.indent 4 $ D.vcat $
764 [ D.fillSep [D.cyan "module","Dict",D.cyan "exposing","(..)"]
765 , D.fillSep [D.cyan "module","Maybe",D.cyan "exposing","(..)"]
766 , D.fillSep [D.cyan "module","Html.Attributes",D.cyan "exposing","(..)"]
767 , D.fillSep [D.cyan "module","Json.Decode",D.cyan "exposing","(..)"]
770 "Notice that the module names all start with capital letters. That is required!"
774 ModuleExposing exposing row col ->
775 toExposingReport source exposing row col
777 PortModuleProblem row col ->
779 region = toRegion row col
781 Report.Report "UNFINISHED PORT MODULE DECLARATION" region [] $
782 Code.toSnippet source region Nothing
785 "I am parsing an `port module` declaration, but I got stuck here:"
789 "Here are some examples of valid `port module` declarations:"
790 , D.indent 4 $ D.vcat $
791 [ D.fillSep [D.cyan "port",D.cyan "module","WebSockets",D.cyan "exposing","(send, listen, keepAlive)"]
792 , D.fillSep [D.cyan "port",D.cyan "module","Maps",D.cyan "exposing","(Location, goto)"]
794 , D.link "Note" "Read" "ports" "for more help."
798 PortModuleName row col ->
800 region = toRegion row col
802 Report.Report "EXPECTING MODULE NAME" region [] $
803 Code.toSnippet source region Nothing
806 "I was parsing an `module` declaration until I got stuck here:"
810 "I was expecting to see the module name next, like in these examples:"
811 , D.indent 4 $ D.vcat $
812 [ D.fillSep [D.cyan "port",D.cyan "module","WebSockets",D.cyan "exposing","(send, listen, keepAlive)"]
813 , D.fillSep [D.cyan "port",D.cyan "module","Maps",D.cyan "exposing","(Location, goto)"]
816 "Notice that the module names start with capital letters. That is required!"
820 PortModuleExposing exposing row col ->
821 toExposingReport source exposing row col
825 region = toRegion row col
827 Report.Report "BAD MODULE DECLARATION" region [] $
828 Code.toSnippet source region Nothing
831 "I cannot parse this module declaration:"
834 "This type of module is reserved for the @elm organization. It is used to\
835 \ define certain effects, avoiding building them into the compiler."
840 region = toRegion row col
842 toBadFirstLineReport keyword =
843 Report.Report "TOO MUCH INDENTATION" region [] $
844 Code.toSnippet source region Nothing
847 "This `" ++ keyword ++ "` should not have any spaces before it:"
850 "Delete the spaces before `" ++ keyword ++ "` until there are none left!"
854 case Code.whatIsNext source row col of
855 Code.Keyword "module" -> toBadFirstLineReport "module"
856 Code.Keyword "import" -> toBadFirstLineReport "import"
857 Code.Keyword "type" -> toBadFirstLineReport "type"
858 Code.Keyword "port" -> toBadFirstLineReport "port"
860 Report.Report "SYNTAX PROBLEM" region [] $
861 Code.toSnippet source region Nothing
868 "I am not sure what is going on, but I recommend starting an Elm\
869 \ file with the following lines:"
871 [ D.fillSep [D.cyan "import","Html"]
873 , D.fillSep [D.green "main","="]
874 , D.indent 2 $ D.fillSep [D.cyan "Html" <> ".text",D.dullyellow "\"Hello!\""]
877 "You should be able to copy those lines directly into your file. Check out the\
878 \ examples at <https://elm-lang.org/examples> for more help getting started!"
880 "This can also happen when something is indented too much!"
884 ImportStart row col ->
885 toImportReport source row col
887 ImportName row col ->
889 region = toRegion row col
891 Report.Report "EXPECTING IMPORT NAME" region [] $
892 Code.toSnippet source region Nothing
895 "I was parsing an `import` until I got stuck here:"
899 "I was expecting to see a module name next, like in these examples:"
900 , D.indent 4 $ D.vcat $
901 [ D.fillSep [D.cyan "import","Dict"]
902 , D.fillSep [D.cyan "import","Maybe"]
903 , D.fillSep [D.cyan "import","Html.Attributes"]
904 , D.fillSep [D.cyan "import","Json.Decode"]
907 "Notice that the module names all start with capital letters. That is required!"
912 toImportReport source row col
914 ImportAlias row col ->
916 region = toRegion row col
918 Report.Report "EXPECTING IMPORT ALIAS" region [] $
919 Code.toSnippet source region Nothing
922 "I was parsing an `import` until I got stuck here:"
926 "I was expecting to see an alias next, like in these examples:"
927 , D.indent 4 $ D.vcat $
928 [ D.fillSep [D.cyan "import","Html.Attributes",D.cyan "as","Attr"]
929 , D.fillSep [D.cyan "import","WebGL.Texture",D.cyan "as","Texture"]
930 , D.fillSep [D.cyan "import","Json.Decode",D.cyan "as","D"]
933 "Notice that the alias always starts with a capital letter. That is required!"
937 ImportExposing row col ->
938 toImportReport source row col
940 ImportExposingList exposing row col ->
941 toExposingReport source exposing row col
944 toImportReport source row col
946 ImportIndentName row col ->
947 toImportReport source row col
949 ImportIndentAlias row col ->
950 toImportReport source row col
952 ImportIndentExposingList row col ->
954 region = toRegion row col
956 Report.Report "UNFINISHED IMPORT" region [] $
957 Code.toSnippet source region Nothing
960 "I was parsing an `import` until I got stuck here:"
964 "I was expecting to see the list of exposed values next. For example, here\
965 \ are two ways to expose values from the `Html` module:"
966 , D.indent 4 $ D.vcat $
967 [ D.fillSep [D.cyan "import","Html",D.cyan "exposing","(..)"]
968 , D.fillSep [D.cyan "import","Html",D.cyan "exposing","(Html, div, text)"]
971 "I generally recommend the second style. It is more explicit, making it\
972 \ much easier to figure out where values are coming from in large projects!"
978 region = toRegion row col
980 Report.Report "BAD INFIX" region [] $
981 Code.toSnippet source region Nothing
984 "Something went wrong in this infix operator declaration:"
987 "This feature is used by the @elm organization to define the\
988 \ languages built-in operators."
991 Declarations decl _ _ ->
992 toDeclarationsReport source decl
999toImportReport :: Code.Source -> Row -> Col -> Report.Report
1000toImportReport source row col =
1002 region = toRegion row col
1004 Report.Report "UNFINISHED IMPORT" region [] $
1005 Code.toSnippet source region Nothing
1008 "I am partway through parsing an import, but I got stuck here:"
1012 "Here are some examples of valid `import` declarations:"
1013 , D.indent 4 $ D.vcat $
1014 [ D.fillSep [D.cyan "import","Html"]
1015 , D.fillSep [D.cyan "import","Html",D.cyan "as","H"]
1016 , D.fillSep [D.cyan "import","Html",D.cyan "as","H",D.cyan "exposing","(..)"]
1017 , D.fillSep [D.cyan "import","Html",D.cyan "exposing","(Html, div, text)"]
1020 "You are probably trying to import a different module, but try to make it look like one of these examples!"
1029toExposingReport :: Code.Source -> Exposing -> Row -> Col -> Report.Report
1030toExposingReport source exposing startRow startCol =
1032 ExposingSpace space row col ->
1033 toSpaceReport source space row col
1035 ExposingStart row col ->
1037 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1038 region = toRegion row col
1040 Report.Report "PROBLEM IN EXPOSING" region [] $
1041 Code.toSnippet source surroundings (Just region)
1044 "I want to parse exposed values, but I am getting stuck here:"
1048 ["Exposed","values","are","always","surrounded","by","parentheses."
1049 ,"So","try","adding","a",D.green "(","here?"
1051 , D.toSimpleNote "Here are some valid examples of `exposing` for reference:"
1052 , D.indent 4 $ D.vcat $
1053 [ D.fillSep [D.cyan "import","Html",D.cyan "exposing","(..)"]
1054 , D.fillSep [D.cyan "import","Html",D.cyan "exposing","(Html, div, text)"]
1057 "If you are getting tripped up, you can just expose everything for now. It should\
1058 \ get easier to make an explicit exposing list as you see more examples in the wild."
1062 ExposingValue row col ->
1063 case Code.whatIsNext source row col of
1064 Code.Keyword keyword ->
1066 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1067 region = toKeywordRegion row col keyword
1069 Report.Report "RESERVED WORD" region [] $
1070 Code.toSnippet source surroundings (Just region)
1073 "I got stuck on this reserved word:"
1076 "It looks like you are trying to expose `" ++ keyword ++ "` but that is a reserved word. Is there a typo?"
1081 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1082 region = toKeywordRegion row col op
1084 Report.Report "UNEXPECTED SYMBOL" region [] $
1085 Code.toSnippet source surroundings (Just region)
1088 "I got stuck on this symbol:"
1092 "If you are trying to expose an operator, add parentheses around it like this:"
1093 , D.indent 4 $ D.dullyellow (D.fromChars op) <> " -> " <> D.green ("(" <> D.fromChars op <> ")")
1099 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1100 region = toRegion row col
1102 Report.Report "PROBLEM IN EXPOSING" region [] $
1103 Code.toSnippet source surroundings (Just region)
1106 "I got stuck while parsing these exposed values:"
1110 "I do not have an exact recommendation, so here are some valid examples\
1111 \ of `exposing` for reference:"
1112 , D.indent 4 $ D.vcat $
1113 [ D.fillSep [D.cyan "import","Html",D.cyan "exposing","(..)"]
1114 , D.fillSep [D.cyan "import","Basics",D.cyan "exposing","(Int, Float, Bool(..), (+), not, sqrt)"]
1117 "These examples show how to expose types, variants, operators, and functions. Everything\
1118 \ should be some permutation of these examples, just with different names."
1122 ExposingOperator row col ->
1124 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1125 region = toRegion row col
1127 Report.Report "PROBLEM IN EXPOSING" region [] $
1128 Code.toSnippet source surroundings (Just region)
1131 "I just saw an open parenthesis, so I was expecting an operator next:"
1134 ["It","is","possible","to","expose","operators,","so","I","was","expecting"
1135 ,"to","see","something","like",D.dullyellow "(+)","or",D.dullyellow "(|=)"
1136 ,"or",D.dullyellow "(||)","after","I","saw","that","open","parenthesis."
1140 ExposingOperatorReserved op row col ->
1142 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1143 region = toRegion row col
1145 Report.Report "RESERVED SYMBOL" region [] $
1146 Code.toSnippet source surroundings (Just region)
1149 "I cannot expose this as an operator:"
1152 BadDot -> D.reflow "Try getting rid of this entry? Maybe I can give you a better hint after that?"
1153 BadPipe -> D.fillSep ["Maybe","you","want",D.dullyellow "(||)","instead?"]
1154 BadArrow -> D.reflow "Try getting rid of this entry? Maybe I can give you a better hint after that?"
1155 BadEquals -> D.fillSep ["Maybe","you","want",D.dullyellow "(==)","instead?"]
1156 BadHasType -> D.fillSep ["Maybe","you","want",D.dullyellow "(::)","instead?"]
1159 ExposingOperatorRightParen row col ->
1161 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1162 region = toRegion row col
1164 Report.Report "PROBLEM IN EXPOSING" region [] $
1165 Code.toSnippet source surroundings (Just region)
1168 "It looks like you are exposing an operator, but I got stuck here:"
1171 ["I","was","expecting","to","see","the","closing","parenthesis","immediately"
1172 ,"after","the","operator.","Try","adding","a",D.green ")","right","here?"
1176 ExposingEnd row col ->
1178 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1179 region = toRegion row col
1181 Report.Report "UNFINISHED EXPOSING" region [] $
1182 Code.toSnippet source surroundings (Just region)
1185 "I was partway through parsing exposed values, but I got stuck here:"
1188 "Maybe there is a comma missing before this?"
1191 ExposingTypePrivacy row col ->
1193 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1194 region = toRegion row col
1196 Report.Report "PROBLEM EXPOSING CUSTOM TYPE VARIANTS" region [] $
1197 Code.toSnippet source surroundings (Just region)
1200 "It looks like you are trying to expose the variants of a custom type:"
1204 ["You","need","to","write","something","like"
1205 ,D.dullyellow "Status(..)","or",D.dullyellow "Entity(..)"
1206 ,"though.","It","is","all","or","nothing,","otherwise","`case`"
1207 ,"expressions","could","miss","a","variant","and","crash!"
1210 "It is often best to keep the variants hidden! If someone pattern matches on\
1211 \ the variants, it is a MAJOR change if any new variants are added. Suddenly\
1212 \ their `case` expressions do not cover all variants! So if you do not need\
1213 \ people to pattern match, keep the variants hidden and expose functions to\
1214 \ construct values of this type. This way you can add new variants as a MINOR change!"
1218 ExposingIndentEnd row col ->
1220 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1221 region = toRegion row col
1223 Report.Report "UNFINISHED EXPOSING" region [] $
1224 Code.toSnippet source surroundings (Just region)
1227 "I was partway through parsing exposed values, but I got stuck here:"
1231 ["I","was","expecting","a","closing","parenthesis."
1232 ,"Try","adding","a",D.green ")","right","here?"
1235 "I can get confused when there is not enough indentation, so if you already\
1236 \ have a closing parenthesis, it probably just needs some spaces in front of it."
1240 ExposingIndentValue row col ->
1242 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1243 region = toRegion row col
1245 Report.Report "UNFINISHED EXPOSING" region [] $
1246 Code.toSnippet source surroundings (Just region)
1249 "I was partway through parsing exposed values, but I got stuck here:"
1252 "I was expecting another value to expose."
1260toSpaceReport :: Code.Source -> Space -> Row -> Col -> Report.Report
1261toSpaceReport source space row col =
1265 region = toRegion row col
1267 Report.Report "NO TABS" region [] $
1268 Code.toSnippet source region Nothing
1271 "I ran into a tab, but tabs are not allowed in Elm files."
1274 "Replace the tab with spaces."
1277 EndlessMultiComment ->
1279 region = toWiderRegion row col 2
1281 Report.Report "ENDLESS COMMENT" region [] $
1282 Code.toSnippet source region Nothing
1285 "I cannot find the end of this multi-line comment:"
1288 [ D.reflow "Add a -} somewhere after this to end the comment."
1290 "Multi-line comments can be nested in Elm, so {- {- -} -} is a comment\
1291 \ that happens to contain another comment. Like parentheses and curly braces,\
1292 \ the start and end markers must always be balanced. Maybe that is the problem?"
1301toRegion :: Row -> Col -> A.Region
1304 pos = A.Position row col
1309toWiderRegion :: Row -> Col -> Word16 -> A.Region
1310toWiderRegion row col extra =
1312 (A.Position row col)
1313 (A.Position row (col + extra))
1316toKeywordRegion :: Row -> Col -> [Char.Char] -> A.Region
1317toKeywordRegion row col keyword =
1319 (A.Position row col)
1320 (A.Position row (col + fromIntegral (length keyword)))
1323toDeclarationsReport :: Code.Source -> Decl -> Report.Report
1324toDeclarationsReport source decl =
1326 DeclStart row col ->
1327 case Code.whatIsNext source row col of
1328 Code.Close term bracket ->
1330 region = toRegion row col
1332 Report.Report ("STRAY " ++ map Char.toUpper term) region [] $
1333 Code.toSnippet source region Nothing
1336 "I was not expecting to see a " ++ term ++ " here:"
1338 "This " ++ bracket : " does not match up with an earlier open " ++ term ++ ". Try deleting it?"
1341 Code.Keyword keyword ->
1343 region = toKeywordRegion row col keyword
1345 Report.Report "RESERVED WORD" region [] $
1346 Code.toSnippet source region Nothing
1349 "I was not expecting to run into the `" ++ keyword ++ "` keyword here:"
1354 "It is reserved for declaring imports at the top of your module. If you want\
1355 \ another import, try moving it up top with the other imports. If you want to\
1356 \ define a value or function, try changing the name to something else!"
1361 "It is reserved for writing `case` expressions. Try using a different name?"
1363 "If you are trying to write a `case` expression, it needs to be part of a\
1364 \ definition. So you could write something like this instead:"
1366 [ D.indent 0 $ D.fillSep [D.green "getWidth","maybeWidth","="]
1367 , D.indent 2 $ D.fillSep [D.cyan "case","maybeWidth",D.cyan "of"]
1368 , D.indent 4 $ D.fillSep [D.blue "Just","width","->"]
1369 , D.indent 6 $ D.fillSep ["width","+",D.dullyellow "200"]
1371 , D.indent 4 $ D.fillSep [D.blue "Nothing","->"]
1372 , D.indent 6 $ D.fillSep [D.dullyellow "400"]
1375 "This defines a `getWidth` function that we can use elsewhere in our program."
1381 "It is reserved for writing `if` expressions. Try using a different name?"
1383 "If you are trying to write an `if` expression, it needs to be part of a\
1384 \ definition. So you could write something like this instead:"
1386 [ D.indent 0 $ D.fillSep [D.green "reviewPowerLevel","powerLevel","="]
1387 , D.indent 2 $ D.fillSep $
1388 [D.cyan "if","powerLevel",">",D.dullyellow "9000"
1389 ,D.cyan "then",D.dullyellow "\"OVER 9000!!!\""
1390 ,D.cyan "else",D.dullyellow "\"not bad\""
1394 "This defines a `reviewPowerLevel` function that we can use elsewhere in our program."
1399 "It is a reserved word. Try changing the name to something else?"
1404 region = toRegion row col
1406 Report.Report "SYNTAX PROBLEM" region [] $
1407 Code.toSnippet source region Nothing
1410 "I was expecting to see a new declaration here:"
1414 "I am not sure what is going wrong exactly, but here are a couple valid\
1415 \ declarations for reference:"
1417 [ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
1418 , D.fillSep [D.green "add","x","y","="]
1419 , D.fillSep [" ","x","+","y"]
1421 , D.fillSep [D.cyan "type",D.green "User","=","Anonymous","|","LoggedIn String"]
1423 "Note that all declarations start with lower-case letters in Elm. Capitalization\
1424 \ makes a difference, so be conscious of that if you are working from examples!"
1428 DeclSpace space row col ->
1429 toSpaceReport source space row col
1431 Port port_ row col ->
1432 toPortReport source port_ row col
1434 DeclType declType row col ->
1435 toDeclTypeReport source declType row col
1437 DeclDef name declDef row col ->
1438 toDeclDefReport source name declDef row col
1440 DeclFreshLineAfterDocComment row col ->
1442 region = toRegion row col
1444 Report.Report "EXPECTING DECLARATION" region [] $
1445 Code.toSnippet source region Nothing
1448 "I just saw a doc comment, but then I got stuck here:"
1451 "I was expecting to see the corresponding declaration next, starting on a fresh\
1452 \ line with no indentation."
1460toPortReport :: Code.Source -> Port -> Row -> Col -> Report.Report
1461toPortReport source port_ startRow startCol =
1463 PortSpace space row col ->
1464 toSpaceReport source space row col
1467 case Code.whatIsNext source row col of
1468 Code.Keyword keyword ->
1470 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1471 region = toKeywordRegion row col keyword
1473 Report.Report "RESERVED WORD" region [] $
1474 Code.toSnippet source surroundings (Just region)
1477 "I cannot handle ports with names like this:"
1480 "You are trying to make a port named `" ++ keyword
1481 ++ "` but that is a reserved word. Try using some other name?"
1486 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1487 region = toRegion row col
1489 Report.Report "PORT PROBLEM" region [] $
1490 Code.toSnippet source surroundings (Just region)
1493 "I just saw the start of a `port` declaration, but then I got stuck here:"
1497 ["I","was","expecting","to","see","a","name","like"
1498 ,D.dullyellow "send","or",D.dullyellow "receive","next."
1499 ,"Something","that","starts","with","a","lower-case","letter."
1505 PortColon row col ->
1507 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1508 region = toRegion row col
1510 Report.Report "PORT PROBLEM" region [] $
1511 Code.toSnippet source surroundings (Just region)
1514 "I just saw the start of a `port` declaration, but then I got stuck here:"
1518 "I was expecting to see a colon next. And then a type that tells me\
1519 \ what type of values are going to flow through."
1524 PortType tipe row col ->
1525 toTypeReport source TC_Port tipe row col
1527 PortIndentName row col ->
1529 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1530 region = toRegion row col
1532 Report.Report "UNFINISHED PORT" region [] $
1533 Code.toSnippet source surroundings (Just region)
1536 "I just saw the start of a `port` declaration, but then I got stuck here:"
1540 ["I","was","expecting","to","see","a","name","like"
1541 ,D.dullyellow "send","or",D.dullyellow "receive","next."
1542 ,"Something","that","starts","with","a","lower-case","letter."
1548 PortIndentColon row col ->
1550 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1551 region = toRegion row col
1553 Report.Report "UNFINISHED PORT" region [] $
1554 Code.toSnippet source surroundings (Just region)
1557 "I just saw the start of a `port` declaration, but then I got stuck here:"
1561 "I was expecting to see a colon next. And then a type that tells me\
1562 \ what type of values are going to flow through."
1567 PortIndentType row col ->
1569 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1570 region = toRegion row col
1572 Report.Report "UNFINISHED PORT" region [] $
1573 Code.toSnippet source surroundings (Just region)
1576 "I just saw the start of a `port` declaration, but then I got stuck here:"
1580 "I was expecting to see a type next. Here are examples of outgoing and\
1581 \ incoming ports for reference:"
1583 [ D.fillSep [D.cyan "port","send",":","String -> Cmd msg"]
1584 , D.fillSep [D.cyan "port","receive",":","(String -> msg) -> Sub msg"]
1587 "The first line defines a `send` port so you can send strings out to JavaScript.\
1588 \ Maybe you send them on a WebSocket or put them into IndexedDB. The second line\
1589 \ defines a `receive` port so you can receive strings from JavaScript. Maybe you\
1590 \ get receive messages when new WebSocket messages come in or when an entry in\
1591 \ IndexedDB changes for some external reason."
1600 "Here are some example `port` declarations for reference:"
1602 [ D.fillSep [D.cyan "port","send",":","String -> Cmd msg"]
1603 , D.fillSep [D.cyan "port","receive",":","(String -> msg) -> Sub msg"]
1606 "The first line defines a `send` port so you can send strings out to JavaScript.\
1607 \ Maybe you send them on a WebSocket or put them into IndexedDB. The second line\
1608 \ defines a `receive` port so you can receive strings from JavaScript. Maybe you\
1609 \ get receive messages when new WebSocket messages come in or when the IndexedDB\
1610 \ is changed for some external reason."
1618toDeclTypeReport :: Code.Source -> DeclType -> Row -> Col -> Report.Report
1619toDeclTypeReport source declType startRow startCol =
1621 DT_Space space row col ->
1622 toSpaceReport source space row col
1626 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1627 region = toRegion row col
1629 Report.Report "EXPECTING TYPE NAME" region [] $
1630 Code.toSnippet source surroundings (Just region)
1633 "I think I am parsing a type declaration, but I got stuck here:"
1637 ["I","was","expecting","a","name","like",D.dullyellow "Status","or",D.dullyellow "Style"
1638 ,"next.","Just","make","sure","it","is","a","name","that","starts","with","a","capital","letter!"
1644 DT_Alias typeAlias row col ->
1645 toTypeAliasReport source typeAlias row col
1647 DT_Union customType row col ->
1648 toCustomTypeReport source customType row col
1650 DT_IndentName row col ->
1652 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1653 region = toRegion row col
1655 Report.Report "EXPECTING TYPE NAME" region [] $
1656 Code.toSnippet source surroundings (Just region)
1659 "I think I am parsing a type declaration, but I got stuck here:"
1663 ["I","was","expecting","a","name","like",D.dullyellow "Status","or",D.dullyellow "Style"
1664 ,"next.","Just","make","sure","it","is","a","name","that","starts","with","a","capital","letter!"
1671toTypeAliasReport :: Code.Source -> TypeAlias -> Row -> Col -> Report.Report
1672toTypeAliasReport source typeAlias startRow startCol =
1674 AliasSpace space row col ->
1675 toSpaceReport source space row col
1677 AliasName row col ->
1679 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1680 region = toRegion row col
1682 Report.Report "EXPECTING TYPE ALIAS NAME" region [] $
1683 Code.toSnippet source surroundings (Just region)
1686 "I am partway through parsing a type alias, but I got stuck here:"
1690 ["I","was","expecting","a","name","like",D.dullyellow "Person","or",D.dullyellow "Point"
1691 ,"next.","Just","make","sure","it","is","a","name","that","starts","with","a","capital","letter!"
1697 AliasEquals row col ->
1698 case Code.whatIsNext source row col of
1699 Code.Keyword keyword ->
1701 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1702 region = toKeywordRegion row col keyword
1704 Report.Report "RESERVED WORD" region [] $
1705 Code.toSnippet source surroundings (Just region)
1708 "I ran into a reserved word unexpectedly while parsing this type alias:"
1712 "It looks like you are trying use `" ++ keyword
1713 ++ "` as a type variable, but it is a reserved word. Try using a different name?"
1720 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1721 region = toRegion row col
1723 Report.Report "PROBLEM IN TYPE ALIAS" region [] $
1724 Code.toSnippet source surroundings (Just region)
1727 "I am partway through parsing a type alias, but I got stuck here:"
1731 "I was expecting to see a type variable or an equals sign next."
1736 AliasBody tipe row col ->
1737 toTypeReport source TC_TypeAlias tipe row col
1739 AliasIndentEquals row col ->
1741 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1742 region = toRegion row col
1744 Report.Report "UNFINISHED TYPE ALIAS" region [] $
1745 Code.toSnippet source surroundings (Just region)
1748 "I am partway through parsing a type alias, but I got stuck here:"
1752 "I was expecting to see a type variable or an equals sign next."
1757 AliasIndentBody row col ->
1759 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1760 region = toRegion row col
1762 Report.Report "UNFINISHED TYPE ALIAS" region [] $
1763 Code.toSnippet source surroundings (Just region)
1766 "I am partway through parsing a type alias, but I got stuck here:"
1770 ["I","was","expecting","to","see","a","type","next.","Something","as","simple"
1771 ,"as",D.dullyellow "Int","or",D.dullyellow "Float","would","work!"
1778typeAliasNote :: D.Doc
1782 "Here is an example of a valid `type alias` for reference:"
1784 [ D.indent 0 $ D.fillSep [D.cyan "type",D.cyan "alias",D.green "Person","="]
1785 , D.indent 2 $ D.vcat $
1793 "This would let us use `Person` as a shorthand for that record type. Using this\
1794 \ shorthand makes type annotations much easier to read, and makes changing code\
1795 \ easier if you decide later that there is more to a person than age and height!"
1799toCustomTypeReport :: Code.Source -> CustomType -> Row -> Col -> Report.Report
1800toCustomTypeReport source customType startRow startCol =
1802 CT_Space space row col ->
1803 toSpaceReport source space row col
1807 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1808 region = toRegion row col
1810 Report.Report "EXPECTING TYPE NAME" region [] $
1811 Code.toSnippet source surroundings (Just region)
1814 "I think I am parsing a type declaration, but I got stuck here:"
1818 ["I","was","expecting","a","name","like",D.dullyellow "Status","or",D.dullyellow "Style"
1819 ,"next.","Just","make","sure","it","is","a","name","that","starts","with","a","capital","letter!"
1825 CT_Equals row col ->
1826 case Code.whatIsNext source row col of
1827 Code.Keyword keyword ->
1829 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1830 region = toKeywordRegion row col keyword
1832 Report.Report "RESERVED WORD" region [] $
1833 Code.toSnippet source surroundings (Just region)
1836 "I ran into a reserved word unexpectedly while parsing this custom type:"
1840 "It looks like you are trying use `" ++ keyword
1841 ++ "` as a type variable, but it is a reserved word. Try using a different name?"
1848 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1849 region = toRegion row col
1851 Report.Report "PROBLEM IN CUSTOM TYPE" region [] $
1852 Code.toSnippet source surroundings (Just region)
1855 "I am partway through parsing a custom type, but I got stuck here:"
1859 "I was expecting to see a type variable or an equals sign next."
1866 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1867 region = toRegion row col
1869 Report.Report "PROBLEM IN CUSTOM TYPE" region [] $
1870 Code.toSnippet source surroundings (Just region)
1873 "I am partway through parsing a custom type, but I got stuck here:"
1877 "I was expecting to see a vertical bar like | next."
1882 CT_Variant row col ->
1884 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1885 region = toRegion row col
1887 Report.Report "PROBLEM IN CUSTOM TYPE" region [] $
1888 Code.toSnippet source surroundings (Just region)
1891 "I am partway through parsing a custom type, but I got stuck here:"
1895 ["I","was","expecting","to","see","a","variant","name","next."
1896 ,"Something","like",D.dullyellow "Success","or",D.dullyellow "Sandwich" <> "."
1897 ,"Any","name","that","starts","with","a","capital","letter","really!"
1903 CT_VariantArg tipe row col ->
1904 toTypeReport source TC_CustomType tipe row col
1906 CT_IndentEquals row col ->
1908 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1909 region = toRegion row col
1911 Report.Report "UNFINISHED CUSTOM TYPE" region [] $
1912 Code.toSnippet source surroundings (Just region)
1915 "I am partway through parsing a custom type, but I got stuck here:"
1919 "I was expecting to see a type variable or an equals sign next."
1924 CT_IndentBar row col ->
1926 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1927 region = toRegion row col
1929 Report.Report "UNFINISHED CUSTOM TYPE" region [] $
1930 Code.toSnippet source surroundings (Just region)
1933 "I am partway through parsing a custom type, but I got stuck here:"
1937 "I was expecting to see a vertical bar like | next."
1942 CT_IndentAfterBar row col ->
1944 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1945 region = toRegion row col
1947 Report.Report "UNFINISHED CUSTOM TYPE" region [] $
1948 Code.toSnippet source surroundings (Just region)
1951 "I am partway through parsing a custom type, but I got stuck here:"
1955 "I just saw a vertical bar, so I was expecting to see another variant defined next."
1960 CT_IndentAfterEquals row col ->
1962 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1963 region = toRegion row col
1965 Report.Report "UNFINISHED CUSTOM TYPE" region [] $
1966 Code.toSnippet source surroundings (Just region)
1969 "I am partway through parsing a custom type, but I got stuck here:"
1973 "I just saw an equals sign, so I was expecting to see the first variant defined next."
1979customTypeNote :: D.Doc
1983 "Here is an example of a valid `type` declaration for reference:"
1985 [ D.indent 0 $ D.fillSep [D.cyan "type",D.green "Status"]
1986 , D.indent 2 $ D.fillSep ["=","Failure"]
1987 , D.indent 2 $ D.fillSep ["|","Waiting"]
1988 , D.indent 2 $ D.fillSep ["|","Success","String"]
1991 "This defines a new `Status` type with three variants. This could be useful if\
1992 \ we are waiting for an HTTP request. Maybe we start with `Waiting` and then\
1993 \ switch to `Failure` or `Success \"message from server\"` depending on how\
1994 \ things go. Notice that the Success variant has some associated data, allowing\
1995 \ us to store a String if the request goes well!"
2003toDeclDefReport :: Code.Source -> Name.Name -> DeclDef -> Row -> Col -> Report.Report
2004toDeclDefReport source name declDef startRow startCol =
2006 DeclDefSpace space row col ->
2007 toSpaceReport source space row col
2009 DeclDefEquals row col ->
2010 case Code.whatIsNext source row col of
2011 Code.Keyword keyword ->
2013 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2014 region = toKeywordRegion row col keyword
2016 Report.Report "RESERVED WORD" region [] $
2017 Code.toSnippet source surroundings (Just region)
2021 ,"`" <> D.cyan (D.fromChars keyword) <> "`"
2022 ,"is","reserved","in","Elm,","so","it","cannot"
2023 ,"be","used","as","an","argument","here:"
2028 "Try renaming it to something else."
2032 ["This","keyword","is","reserved","for","pattern","matches","like"
2033 ,"((x,y)",D.cyan "as","point)","where","you","want","to","name","a","tuple","and"
2034 ,"the","values","it","contains."
2039 "The `" ++ keyword ++ "` keyword has a special meaning in Elm, so it can only be used in certain situations."
2043 Code.Operator "->" ->
2045 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2046 region = toWiderRegion row col 2
2048 Report.Report "MISSING COLON?" region [] $
2049 Code.toSnippet source surroundings (Just region)
2052 "I was not expecting to see an arrow here:"
2056 ["This","usually","means","a",D.green ":","is","missing","a","bit","earlier","in"
2057 ,"a","type","annotation.","It","could","be","something","else","though,","so"
2058 ,"here","is","a","valid","definition","for","reference:"
2061 [ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
2062 , D.fillSep [D.green "add","x","y","="]
2063 , D.fillSep [" ","x","+","y"]
2066 "Try to use that format with your `" ++ Name.toChars name ++ "` definition!"
2072 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2073 region = toKeywordRegion row col op
2075 Report.Report "UNEXPECTED SYMBOL" region [] $
2076 Code.toSnippet source surroundings (Just region)
2079 "I was not expecting to see this symbol here:"
2083 "I am not sure what is going wrong exactly, so here is a valid\
2084 \ definition (with an optional type annotation) for reference:"
2086 [ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
2087 , D.fillSep [D.green "add","x","y","="]
2088 , D.fillSep [" ","x","+","y"]
2091 "Try to use that format with your `" ++ Name.toChars name ++ "` definition!"
2097 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2098 region = toRegion row col
2100 Report.Report "PROBLEM IN DEFINITION" region [] $
2101 Code.toSnippet source surroundings (Just region)
2104 "I got stuck while parsing the `" ++ Name.toChars name ++ "` definition:"
2108 "I am not sure what is going wrong exactly, so here is a valid\
2109 \ definition (with an optional type annotation) for reference:"
2111 [ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
2112 , D.fillSep [D.green "add","x","y","="]
2113 , D.fillSep [" ","x","+","y"]
2116 "Try to use that format!"
2120 DeclDefType tipe row col ->
2121 toTypeReport source (TC_Annotation name) tipe row col
2123 DeclDefArg pattern row col ->
2124 toPatternReport source PArg pattern row col
2126 DeclDefBody expr row col ->
2127 toExprReport source (InDef name startRow startCol) expr row col
2129 DeclDefNameRepeat row col ->
2131 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2132 region = toRegion row col
2134 Report.Report "EXPECTING DEFINITION" region [] $
2135 Code.toSnippet source surroundings (Just region)
2138 "I just saw the type annotation for `" ++ Name.toChars name
2139 ++ "` so I was expecting to see its definition here:"
2143 "Type annotations always appear directly above the relevant\
2144 \ definition, without anything else in between. (Not even doc comments!)"
2149 DeclDefNameMatch defName row col ->
2151 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2152 region = toRegion row col
2154 Report.Report "NAME MISMATCH" region [] $
2155 Code.toSnippet source surroundings (Just region)
2158 "I just saw a type annotation for `" ++ Name.toChars name ++ "`, but it is followed by a definition for `" ++ Name.toChars defName ++ "`:"
2162 "These names do not match! Is there a typo?"
2163 , D.indent 4 $ D.fillSep $
2164 [D.dullyellow (D.fromName defName),"->",D.green (D.fromName name)]
2168 DeclDefIndentType row col ->
2170 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2171 region = toRegion row col
2173 Report.Report "UNFINISHED DEFINITION" region [] $
2174 Code.toSnippet source surroundings (Just region)
2177 "I got stuck while parsing the `" ++ Name.toChars name ++ "` type annotation:"
2181 "I just saw a colon, so I am expecting to see a type next."
2186 DeclDefIndentEquals row col ->
2188 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2189 region = toRegion row col
2191 Report.Report "UNFINISHED DEFINITION" region [] $
2192 Code.toSnippet source surroundings (Just region)
2195 "I got stuck while parsing the `" ++ Name.toChars name ++ "` definition:"
2199 "I was expecting to see an argument or an equals sign next."
2204 DeclDefIndentBody row col ->
2206 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2207 region = toRegion row col
2209 Report.Report "UNFINISHED DEFINITION" region [] $
2210 Code.toSnippet source surroundings (Just region)
2213 "I got stuck while parsing the `" ++ Name.toChars name ++ "` definition:"
2217 "I was expecting to see an expression next. What is it equal to?"
2227 "Here is a valid definition (with a type annotation) for reference:"
2229 [ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
2230 , D.fillSep [D.green "add","x","y","="]
2231 , D.fillSep [" ","x","+","y"]
2234 "The top line (called a \"type annotation\") is optional. You can leave it off\
2235 \ if you want. As you get more comfortable with Elm and as your project grows,\
2236 \ it becomes more and more valuable to add them though! They work great as\
2237 \ compiler-verified documentation, and they often improve error messages!"
2246 = InNode Node Row Col Context
2247 | InDef Name.Name Row Col
2248 | InDestruct Row Col
2264getDefName :: Context -> Maybe Name.Name
2267 InDestruct _ _ -> Nothing
2268 InDef name _ _ -> Just name
2269 InNode _ _ _ c -> getDefName c
2272isWithin :: Node -> Context -> Bool
2273isWithin desiredNode context =
2275 InDestruct _ _ -> False
2276 InDef _ _ _ -> False
2277 InNode actualNode _ _ _ -> desiredNode == actualNode
2284toExprReport :: Code.Source -> Context -> Expr -> Row -> Col -> Report.Report
2285toExprReport source context expr startRow startCol =
2288 toLetReport source context let_ row col
2290 Case case_ row col ->
2291 toCaseReport source context case_ row col
2294 toIfReport source context if_ row col
2296 List list row col ->
2297 toListReport source context list row col
2299 Record record row col ->
2300 toRecordReport source context record row col
2302 Tuple tuple row col ->
2303 toTupleReport source context tuple row col
2305 Func func row col ->
2306 toFuncReport source context func row col
2309 let region = toRegion row col in
2310 Report.Report "EXPECTING RECORD ACCESSOR" region [] $
2311 Code.toSnippet source region Nothing
2314 "I was expecting to see a record accessor here:"
2317 ["Something","like",D.dullyellow".name","or",D.dullyellow".price"
2318 ,"that","accesses","a","value","from","a","record."
2323 let region = toRegion row col in
2324 Report.Report "EXPECTING RECORD ACCESSOR" region [] $
2325 Code.toSnippet source region Nothing
2328 "I am trying to parse a record accessor here:"
2333 ["Something","like",D.dullyellow".name","or",D.dullyellow".price"
2334 ,"that","accesses","a","value","from","a","record."
2338 "Record field names must start with a lower case letter!"
2342 OperatorRight op row col ->
2344 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2345 region = toRegion row col
2346 isMath = elem op ["-","+","*","/","^"]
2348 Report.Report "MISSING EXPRESSION" region [] $
2349 Code.toSnippet source surroundings (Just region)
2352 "I just saw a " ++ Name.toChars op ++ " "
2353 ++ (if isMath then "sign" else "operator")
2354 ++ ", so I am getting stuck here:"
2358 ["I","was","expecting","to","see","an","expression","next."
2359 ,"Something","like",D.dullyellow "42","or",D.dullyellow "1000"
2360 ,"that","makes","sense","with","a",D.fromName op,"sign."
2362 else if op == "&&" || op == "||" then
2364 ["I","was","expecting","to","see","an","expression","next."
2365 ,"Something","like",D.dullyellow "True","or",D.dullyellow "False"
2366 ,"that","makes","sense","with","boolean","logic."
2368 else if op == "|>" then
2370 "I was expecting to see a function next."
2371 else if op == "<|" then
2373 "I was expecting to see an argument next."
2376 "I was expecting to see an expression next."
2379 OperatorReserved operator row col ->
2380 toOperatorReport source context operator row col
2384 (contextRow, contextCol, aThing) =
2386 InDestruct r c -> (r, c, "a definition")
2387 InDef name r c -> (r, c, "the `" ++ Name.toChars name ++ "` definition")
2388 InNode NRecord r c _ -> (r, c, "a record")
2389 InNode NParens r c _ -> (r, c, "some parentheses")
2390 InNode NList r c _ -> (r, c, "a list")
2391 InNode NFunc r c _ -> (r, c, "an anonymous function")
2392 InNode NCond r c _ -> (r, c, "an `if` expression")
2393 InNode NThen r c _ -> (r, c, "an `if` expression")
2394 InNode NElse r c _ -> (r, c, "an `if` expression")
2395 InNode NCase r c _ -> (r, c, "a `case` expression")
2396 InNode NBranch r c _ -> (r, c, "a `case` expression")
2398 surroundings = A.Region (A.Position contextRow contextCol) (A.Position row col)
2399 region = toRegion row col
2401 Report.Report "MISSING EXPRESSION" region [] $
2402 Code.toSnippet source surroundings (Just region)
2405 "I am partway through parsing " ++ aThing ++ ", but I got stuck here:"
2409 ["I","was","expecting","to","see","an","expression","like"
2410 ,D.dullyellow "42","or",D.dullyellow"\"hello\"" <> "."
2411 ,"Once","there","is","something","there,","I","can","probably"
2412 ,"give","a","more","specific","hint!"
2415 "This can also happen if run into reserved words like `let` or `as` unexpectedly.\
2416 \ Or if I run into operators in unexpected spots. Point is, there are a\
2417 \ couple ways I can get confused and give sort of weird advice!"
2421 Char char row col ->
2422 toCharReport source char row col
2424 String string row col ->
2425 toStringReport source string row col
2427 Number number row col ->
2428 toNumberReport source number row col
2430 Space space row col ->
2431 toSpaceReport source space row col
2433 EndlessShader row col ->
2435 region = toWiderRegion row col 6
2437 Report.Report "ENDLESS SHADER" region [] $
2438 Code.toSnippet source region Nothing
2440 D.reflow "I cannot find the end of this shader:"
2442 D.reflow "Add a |] somewhere after this to end the shader."
2445 ShaderProblem problem row col ->
2447 region = toRegion row col
2449 Report.Report "SHADER PROBLEM" region [] $
2450 Code.toSnippet source region Nothing
2453 "I ran into a problem while parsing this GLSL block."
2457 "I use a 3rd party GLSL parser for now, and I did my best to extract their error message:"
2458 , D.indent 4 $ D.vcat $
2459 map D.fromChars (filter (/="") (lines problem))
2463 IndentOperatorRight op row col ->
2465 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2466 region = toRegion row col
2468 Report.Report "MISSING EXPRESSION" region [] $
2469 Code.toSnippet source surroundings (Just region)
2472 "I was expecting to see an expression after this " ++ Name.toChars op ++ " operator:"
2477 ["You","can","just","put","anything","for","now,","like"
2478 ,D.dullyellow "42","or",D.dullyellow"\"hello\"" <> "."
2479 ,"Once","there","is","something","there,","I","can","probably"
2480 ,"give","a","more","specific","hint!"
2484 "I may be getting confused by your indentation? The easiest way to make sure\
2485 \ this is not an indentation problem is to put the expression on the right of\
2486 \ the " ++ Name.toChars op ++ " operator on the same line."
2495toCharReport :: Code.Source -> Char -> Row -> Col -> Report.Report
2496toCharReport source char row col =
2500 region = toRegion row col
2502 Report.Report "MISSING SINGLE QUOTE" region [] $
2503 Code.toSnippet source region Nothing
2506 "I thought I was parsing a character, but I got to the end of\
2507 \ the line without seeing the closing single quote:"
2510 "Add a closing single quote here!"
2513 CharEscape escape ->
2514 toEscapeReport source escape row col
2516 CharNotString width ->
2518 region = toWiderRegion row col width
2520 Report.Report "NEEDS DOUBLE QUOTES" region [] $
2521 Code.toSnippet source region Nothing
2523 "The following string uses single quotes:"
2526 [ "Please switch to double quotes instead:"
2528 D.dullyellow "'this'" <> " => " <> D.green "\"this\""
2530 "Elm uses double quotes for strings like \"hello\", whereas it uses single\
2531 \ quotes for individual characters like 'a' and 'ø'. This distinction helps with\
2532 \ code like (String.any (\\c -> c == 'X') \"90210\") where you are inspecting\
2533 \ individual characters."
2542toStringReport :: Code.Source -> String -> Row -> Col -> Report.Report
2543toStringReport source string row col =
2545 StringEndless_Single ->
2547 region = toRegion row col
2549 Report.Report "ENDLESS STRING" region [] $
2550 Code.toSnippet source region Nothing
2553 "I got to the end of the line without seeing the closing double quote:"
2557 ["Strings","look","like",D.green "\"this\"","with","double"
2558 ,"quotes","on","each","end.","Is","the","closing","double"
2559 ,"quote","missing","in","your","code?"
2562 "For a string that spans multiple lines, you can use the multi-line string\
2563 \ syntax like this:"
2565 [ D.fillSep [D.green "markdown","=",D.dullyellow "\"\"\""]
2567 , D.dullyellow "# Multi-line Strings"
2569 , D.dullyellow "- start with triple double quotes"
2570 , D.dullyellow "- write whatever you want"
2571 , D.dullyellow "- no need to escape newlines or double quotes"
2572 , D.dullyellow "- end with triple double quotes"
2574 , D.dullyellow "\"\"\""
2579 StringEndless_Multi ->
2581 region = toWiderRegion row col 3
2583 Report.Report "ENDLESS STRING" region [] $
2584 Code.toSnippet source region Nothing
2587 "I cannot find the end of this multi-line string:"
2590 [ D.reflow "Add a \"\"\" somewhere after this to end the string."
2592 "Here is a valid multi-line string for reference:"
2594 [ D.fillSep [D.green "markdown","=",D.dullyellow "\"\"\""]
2596 , D.dullyellow "# Multi-line Strings"
2598 , D.dullyellow "- start with triple double quotes"
2599 , D.dullyellow "- write whatever you want"
2600 , D.dullyellow "- no need to escape newlines or double quotes"
2601 , D.dullyellow "- end with triple double quotes"
2603 , D.dullyellow "\"\"\""
2608 StringEscape escape ->
2609 toEscapeReport source escape row col
2616toEscapeReport :: Code.Source -> Escape -> Row -> Col -> Report.Report
2617toEscapeReport source escape row col =
2621 region = toWiderRegion row col 2
2623 Report.Report "UNKNOWN ESCAPE" region [] $
2624 Code.toSnippet source region Nothing
2627 "Backslashes always start escaped characters, but I do not recognize this one:"
2631 "Valid escape characters include:"
2632 , D.dullyellow $ D.indent 4 $ D.vcat $
2642 "Do you want one of those instead? Maybe you need \\\\ to escape a backslash?"
2644 "The last style lets encode ANY character by its Unicode code\
2645 \ point. That means \\u{0009} and \\t are the same. You can use\
2646 \ that style for anything not covered by the other six escapes!"
2650 BadUnicodeFormat width ->
2652 region = toWiderRegion row col width
2654 Report.Report "BAD UNICODE ESCAPE" region [] $
2655 Code.toSnippet source region Nothing
2658 "I ran into an invalid Unicode escape:"
2662 "Here are some examples of valid Unicode escapes:"
2663 , D.dullyellow $ D.indent 4 $ D.vcat $
2670 "Notice that the code point is always surrounded by curly braces.\
2671 \ Maybe you are missing the opening or closing curly brace?"
2674 BadUnicodeCode width ->
2676 region = toWiderRegion row col width
2678 Report.Report "BAD UNICODE ESCAPE" region [] $
2679 Code.toSnippet source region Nothing
2682 "This is not a valid code point:"
2685 "The valid code points are between 0 and 10FFFF inclusive."
2688 BadUnicodeLength width numDigits badCode ->
2690 region = toWiderRegion row col width
2692 Report.Report "BAD UNICODE ESCAPE" region [] $
2693 Code.toSnippet source region Nothing $
2694 if numDigits < 4 then
2697 "Every code point needs at least four digits:"
2700 goodCode = replicate (4 - numDigits) '0' ++ map Char.toUpper (showHex badCode "")
2701 suggestion = "\\u{" <> D.fromChars goodCode <> "}"
2703 D.fillSep ["Try",D.green suggestion,"instead?"]
2709 "This code point has too many digits:"
2712 ["Valid","code","points","are","between"
2713 ,D.green "\\u{0000}","and",D.green "\\u{10FFFF}" <> ","
2714 ,"so","try","trimming","any","leading","zeros","until"
2715 ,"you","have","between","four","and","six","digits."
2724toNumberReport :: Code.Source -> Number -> Row -> Col -> Report.Report
2725toNumberReport source number row col =
2727 region = toRegion row col
2731 Report.Report "WEIRD NUMBER" region [] $
2732 Code.toSnippet source region Nothing
2735 "I thought I was reading a number, but I ran into some weird stuff here:"
2739 "I recognize numbers in the following formats:"
2740 , D.indent 4 $ D.vcat [ "42", "3.14", "6.022e23", "0x002B" ]
2742 "So is there a way to write it like one of those?"
2747 Report.Report "WEIRD NUMBER" region [] $
2748 Code.toSnippet source region Nothing
2751 "Numbers cannot end with a dot like this:"
2754 ["Switching","to",D.green (D.fromChars (show int))
2755 ,"or",D.green (D.fromChars (show int ++ ".0"))
2756 ,"will","work","though!"
2761 Report.Report "WEIRD HEXIDECIMAL" region [] $
2762 Code.toSnippet source region Nothing
2765 "I thought I was reading a hexidecimal number until I got here:"
2769 "Valid hexidecimal digits include 0123456789abcdefABCDEF, so I can\
2770 \ only recognize things like this:"
2771 , D.indent 4 $ D.vcat [ "0x2B", "0x002B", "0x00ffb3" ]
2775 NumberNoLeadingZero ->
2776 Report.Report "LEADING ZEROS" region [] $
2777 Code.toSnippet source region Nothing
2780 "I do not accept numbers with leading zeros:"
2784 "Just delete the leading zeros and it should work!"
2786 "Some languages let you to specify octal numbers by adding a leading zero.\
2787 \ So in C, writing 0111 is the same as writing 73. Some people are used to\
2788 \ that, but others probably want it to equal 111. Either path is going to\
2789 \ surprise people from certain backgrounds, so Elm tries to avoid this whole\
2799toOperatorReport :: Code.Source -> Context -> BadOperator -> Row -> Col -> Report.Report
2800toOperatorReport source context operator row col =
2804 region = toRegion row col
2806 Report.Report "UNEXPECTED SYMBOL" region [] $
2807 Code.toSnippet source region Nothing
2809 "I was not expecting this dot:"
2812 "Dots are for record access and decimal points, so\
2813 \ they cannot float around on their own. Maybe\
2814 \ there is some extra whitespace?"
2819 region = toRegion row col
2821 Report.Report "UNEXPECTED SYMBOL" region [] $
2822 Code.toSnippet source region Nothing
2825 "I was not expecting this vertical bar:"
2828 "Vertical bars should only appear in custom type declarations. Maybe you want || instead?"
2833 region = toWiderRegion row col 2
2835 Report.Report "UNEXPECTED ARROW" region [] $
2836 Code.toSnippet source region Nothing $
2837 if isWithin NCase context then
2840 "I am parsing a `case` expression right now, but this arrow is confusing me:"
2843 [ D.reflow "Maybe the `of` keyword is missing on a previous line?"
2848 else if isWithin NBranch context then
2851 "I am parsing a `case` expression right now, but this arrow is confusing me:"
2855 "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?"
2856 , noteForCaseIndentError
2863 "I was not expecting an arrow here:"
2866 "Arrows should only appear in `case` expressions and anonymous functions. Maybe\
2867 \ you want > or >= instead?"
2872 region = toRegion row col
2874 Report.Report "UNEXPECTED EQUALS" region [] $
2875 Code.toSnippet source region Nothing
2878 "I was not expecting to see this equals sign:"
2882 D.reflow "Maybe you want == instead? To check if two values are equal?"
2885 if isWithin NRecord context then
2886 "Records look like { x = 3, y = 4 } with the equals sign right\
2887 \ after the field name. So maybe you forgot a comma?"
2889 case getDefName context of
2891 "I may be getting confused by your indentation. I need all definitions to be indented\
2892 \ exactly the same amount, so if this is meant to be a new definition, it may have too\
2893 \ many spaces in front of it."
2896 "I may be getting confused by your indentation. I think I am still parsing the `"
2897 ++ Name.toChars name ++ "` definition. Is this supposed to be part of a definition\
2898 \ after that? If so, the problem may be a bit before the equals sign. I need all\
2899 \ definitions to be indented exactly the same amount, so the problem may be that\
2900 \ this new definition has too many spaces in front of it."
2906 region = toRegion row col
2908 Report.Report "UNEXPECTED SYMBOL" region [] $
2909 Code.toSnippet source region Nothing $
2912 "I was not expecting to run into the \"has type\" symbol here:"
2914 case getDefName context of
2917 ["Maybe","you","want",D.green "::","instead?"
2918 ,"To","put","something","on","the","front","of","a","list?"
2925 ["Maybe","you","want",D.green "::","instead?"
2926 ,"To","put","something","on","the","front","of","a","list?"
2929 "The single colon is reserved for type annotations and record types, but I think\
2930 \ I am parsing the definition of `" ++ Name.toChars name ++ "` right now."
2933 "I may be getting confused by your indentation. Is this supposed to be part of\
2934 \ a type annotation AFTER the `" ++ Name.toChars name ++ "` definition? If so,\
2935 \ the problem may be a bit before the \"has type\" symbol. I need all definitions to\
2936 \ be exactly aligned (with exactly the same indentation) so the problem may be that\
2937 \ this new definition is indented a bit too much."
2946toLetReport :: Code.Source -> Context -> Let -> Row -> Col -> Report.Report
2947toLetReport source context let_ startRow startCol =
2949 LetSpace space row col ->
2950 toSpaceReport source space row col
2954 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2955 region = toRegion row col
2957 Report.Report "LET PROBLEM" region [] $
2958 Code.toSnippet source surroundings (Just region)
2961 "I was partway through parsing a `let` expression, but I got stuck here:"
2965 ["Based","on","the","indentation,","I","was","expecting","to","see","the",D.cyan "in"
2966 ,"keyword","next.","Is","there","a","typo?"
2969 "This can also happen if you are trying to define another value within the `let` but\
2970 \ it is not indented enough. Make sure each definition has exactly the same amount of\
2971 \ spaces before it. They should line up exactly!"
2975 LetDefAlignment _ row col ->
2977 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2978 region = toRegion row col
2980 Report.Report "LET PROBLEM" region [] $
2981 Code.toSnippet source surroundings (Just region)
2984 "I was partway through parsing a `let` expression, but I got stuck here:"
2988 ["Based","on","the","indentation,","I","was","expecting","to","see","the",D.cyan "in"
2989 ,"keyword","next.","Is","there","a","typo?"
2992 "This can also happen if you are trying to define another value within the `let` but\
2993 \ it is not indented enough. Make sure each definition has exactly the same amount of\
2994 \ spaces before it. They should line up exactly!"
2998 LetDefName row col ->
2999 case Code.whatIsNext source row col of
3000 Code.Keyword keyword ->
3002 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3003 region = toKeywordRegion row col keyword
3005 Report.Report "RESERVED WORD" region [] $
3006 Code.toSnippet source surroundings (Just region)
3009 "I was partway through parsing a `let` expression, but I got stuck here:"
3012 "It looks like you are trying to use `" ++ keyword ++ "` as a variable name, but\
3013 \ it is a reserved word! Try using a different name instead."
3017 toUnfinishLetReport source row col startRow startCol $
3019 "I was expecting the name of a definition next."
3021 LetDef name def row col ->
3022 toLetDefReport source name def row col
3024 LetDestruct destruct row col ->
3025 toLetDestructReport source destruct row col
3027 LetBody expr row col ->
3028 toExprReport source context expr row col
3030 LetIndentDef row col ->
3031 toUnfinishLetReport source row col startRow startCol $
3033 "I was expecting a value to be defined here."
3035 LetIndentIn row col ->
3036 toUnfinishLetReport source row col startRow startCol $
3038 ["I","was","expecting","to","see","the",D.cyan "in","keyword","next."
3039 ,"Or","maybe","more","of","that","expression?"
3042 LetIndentBody row col ->
3043 toUnfinishLetReport source row col startRow startCol $
3045 "I was expecting an expression next. Tell me what should happen with the value you just defined!"
3048toUnfinishLetReport :: Code.Source -> Row -> Col -> Row -> Col -> D.Doc -> Report.Report
3049toUnfinishLetReport source row col startRow startCol message =
3051 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3052 region = toRegion row col
3054 Report.Report "UNFINISHED LET" region [] $
3055 Code.toSnippet source surroundings (Just region)
3058 "I was partway through parsing a `let` expression, but I got stuck here:"
3063 "Here is an example with a valid `let` expression for reference:"
3065 [ D.indent 0 $ D.fillSep [D.green "viewPerson","person","="]
3066 , D.indent 2 $ D.fillSep [D.cyan "let"]
3067 , D.indent 4 $ D.fillSep ["fullName","="]
3068 , D.indent 6 $ D.fillSep ["person.firstName","++",D.dullyellow "\" \"","++","person.lastName"]
3069 , D.indent 2 $ D.fillSep [D.cyan "in"]
3070 , D.indent 2 $ D.fillSep ["div","[]","[","text","fullName","]"]
3073 "Here we defined a `viewPerson` function that turns a person into some HTML. We use\
3074 \ a `let` expression to define the `fullName` we want to show. Notice the indentation! The\
3075 \ `fullName` is indented more than the `let` keyword, and the actual value of `fullName` is\
3076 \ indented a bit more than that. That is important!"
3081toLetDefReport :: Code.Source -> Name.Name -> Def -> Row -> Col -> Report.Report
3082toLetDefReport source name def startRow startCol =
3084 DefSpace space row col ->
3085 toSpaceReport source space row col
3087 DefType tipe row col ->
3088 toTypeReport source (TC_Annotation name) tipe row col
3090 DefNameRepeat row col ->
3092 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3093 region = toRegion row col
3095 Report.Report "EXPECTING DEFINITION" region [] $
3096 Code.toSnippet source surroundings (Just region)
3099 "I just saw the type annotation for `" ++ Name.toChars name
3100 ++ "` so I was expecting to see its definition here:"
3104 "Type annotations always appear directly above the relevant\
3105 \ definition, without anything else in between."
3110 DefNameMatch defName row col ->
3112 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3113 region = toRegion row col
3115 Report.Report "NAME MISMATCH" region [] $
3116 Code.toSnippet source surroundings (Just region)
3119 "I just saw a type annotation for `" ++ Name.toChars name ++ "`, but it is followed by a definition for `" ++ Name.toChars defName ++ "`:"
3123 "These names do not match! Is there a typo?"
3124 , D.indent 4 $ D.fillSep $
3125 [D.dullyellow (D.fromName defName),"->",D.green (D.fromName name)]
3129 DefArg pattern row col ->
3130 toPatternReport source PArg pattern row col
3132 DefEquals row col ->
3133 case Code.whatIsNext source row col of
3134 Code.Keyword keyword ->
3136 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3137 region = toKeywordRegion row col keyword
3139 Report.Report "RESERVED WORD" region [] $
3140 Code.toSnippet source surroundings (Just region)
3144 ,"`" <> D.cyan (D.fromChars keyword) <> "`"
3145 ,"is","reserved","in","Elm,","so","it","cannot"
3146 ,"be","used","as","an","argument","here:"
3151 "Try renaming it to something else."
3155 ["This","keyword","is","reserved","for","pattern","matches","like"
3156 ,"((x,y)",D.cyan "as","point)","where","you","want","to","name","a","tuple","and"
3157 ,"the","values","it","contains."
3162 "The `" ++ keyword ++ "` keyword has a special meaning in Elm, so it can only be used in certain situations."
3166 Code.Operator "->" ->
3168 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3169 region = toWiderRegion row col 2
3171 Report.Report "MISSING COLON?" region [] $
3172 Code.toSnippet source surroundings (Just region)
3175 "I was not expecting to see an arrow here:"
3179 ["This","usually","means","a",D.green ":","is","missing","a","bit","earlier","in"
3180 ,"a","type","annotation.","It","could","be","something","else","though,","so"
3181 ,"here","is","a","valid","definition","for","reference:"
3184 [ D.indent 4 $ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
3185 , D.indent 4 $ D.fillSep [D.green "add","x","y","="]
3186 , D.indent 6 $ D.fillSep ["x","+","y"]
3189 "Try to use that format with your `" ++ Name.toChars name ++ "` definition!"
3195 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3196 region = toKeywordRegion row col op
3198 Report.Report "UNEXPECTED SYMBOL" region [] $
3199 Code.toSnippet source surroundings (Just region)
3202 "I was not expecting to see this symbol here:"
3206 "I am not sure what is going wrong exactly, so here is a valid\
3207 \ definition (with an optional type annotation) for reference:"
3209 [ D.indent 4 $ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
3210 , D.indent 4 $ D.fillSep [D.green "add","x","y","="]
3211 , D.indent 6 $ D.fillSep ["x","+","y"]
3214 "Try to use that format with your `" ++ Name.toChars name ++ "` definition!"
3220 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3221 region = toRegion row col
3223 Report.Report "PROBLEM IN DEFINITION" region [] $
3224 Code.toSnippet source surroundings (Just region)
3227 "I got stuck while parsing the `" ++ Name.toChars name ++ "` definition:"
3231 "I am not sure what is going wrong exactly, so here is a valid\
3232 \ definition (with an optional type annotation) for reference:"
3234 [ D.indent 4 $ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
3235 , D.indent 4 $ D.fillSep [D.green "add","x","y","="]
3236 , D.indent 4 $ D.fillSep ["x","+","y"]
3239 "Try to use that format!"
3243 DefBody expr row col ->
3244 toExprReport source (InDef name startRow startCol) expr row col
3246 DefIndentEquals row col ->
3248 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3249 region = toRegion row col
3251 Report.Report "UNFINISHED DEFINITION" region [] $
3252 Code.toSnippet source surroundings (Just region)
3255 "I got stuck while parsing the `" ++ Name.toChars name ++ "` definition:"
3259 "I was expecting to see an argument or an equals sign next."
3264 DefIndentType row col ->
3266 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3267 region = toRegion row col
3269 Report.Report "UNFINISHED DEFINITION" region [] $
3270 Code.toSnippet source surroundings (Just region)
3273 "I got stuck while parsing the `" ++ Name.toChars name ++ "` type annotation:"
3277 "I just saw a colon, so I am expecting to see a type next."
3282 DefIndentBody row col ->
3284 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3285 region = toRegion row col
3287 Report.Report "UNFINISHED DEFINITION" region [] $
3288 Code.toSnippet source surroundings (Just region)
3291 "I got stuck while parsing the `" ++ Name.toChars name ++ "` definition:"
3295 "I was expecting to see an expression next. What is it equal to?"
3300 DefAlignment indent row col ->
3302 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3303 region = toRegion row col
3304 offset = indent - col
3306 Report.Report "PROBLEM IN DEFINITION" region [] $
3307 Code.toSnippet source surroundings (Just region)
3310 "I got stuck while parsing the `" ++ Name.toChars name ++ "` definition:"
3313 "I just saw a type annotation indented " ++ show indent ++ " spaces, so I was\
3314 \ expecting to see the corresponding definition next with the exact same amount\
3315 \ of indentation. It looks like this line needs "
3316 ++ show offset ++ " more " ++ (if offset == 1 then "space" else "spaces") ++ "?"
3325 "Here is a valid definition (with a type annotation) for reference:"
3327 [ D.indent 4 $ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
3328 , D.indent 4 $ D.fillSep [D.green "add","x","y","="]
3329 , D.indent 6 $ D.fillSep ["x","+","y"]
3332 "The top line (called a \"type annotation\") is optional. You can leave it off\
3333 \ if you want. As you get more comfortable with Elm and as your project grows,\
3334 \ it becomes more and more valuable to add them though! They work great as\
3335 \ compiler-verified documentation, and they often improve error messages!"
3339toLetDestructReport :: Code.Source -> Destruct -> Row -> Col -> Report.Report
3340toLetDestructReport source destruct startRow startCol =
3342 DestructSpace space row col ->
3343 toSpaceReport source space row col
3345 DestructPattern pattern row col ->
3346 toPatternReport source PLet pattern row col
3348 DestructEquals row col ->
3350 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3351 region = toRegion row col
3353 Report.Report "PROBLEM IN DEFINITION" region [] $
3354 Code.toSnippet source surroundings (Just region)
3357 "I got stuck trying to parse this definition:"
3359 case Code.whatIsNext source row col of
3360 Code.Operator ":" ->
3363 "I was expecting to see an equals sign next, followed by an expression\
3364 \ telling me what to compute."
3366 "It looks like you may be trying to write a type annotation? It is not\
3367 \ possible to add type annotations on destructuring definitions like this.\
3368 \ You can assign a name to the overall structure, put a type annotation on\
3369 \ that, and then destructure separately though."
3374 "I was expecting to see an equals sign next, followed by an expression\
3375 \ telling me what to compute."
3378 DestructBody expr row col ->
3379 toExprReport source (InDestruct startRow startCol) expr row col
3381 DestructIndentEquals row col ->
3383 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3384 region = toRegion row col
3386 Report.Report "UNFINISHED DEFINITION" region [] $
3387 Code.toSnippet source surroundings (Just region)
3390 "I got stuck trying to parse this definition:"
3393 "I was expecting to see an equals sign next, followed by an expression\
3394 \ telling me what to compute."
3397 DestructIndentBody row col ->
3399 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3400 region = toRegion row col
3402 Report.Report "UNFINISHED DEFINITION" region [] $
3403 Code.toSnippet source surroundings (Just region)
3406 "I got stuck while parsing this definition:"
3409 "I was expecting to see an expression next. What is it equal to?"
3417toCaseReport :: Code.Source -> Context -> Case -> Row -> Col -> Report.Report
3418toCaseReport source context case_ startRow startCol =
3420 CaseSpace space row col ->
3421 toSpaceReport source space row col
3424 toUnfinishCaseReport source row col startRow startCol $
3425 D.fillSep ["I","was","expecting","to","see","the",D.dullyellow "of","keyword","next."]
3427 CasePattern pattern row col ->
3428 toPatternReport source PCase pattern row col
3430 CaseArrow row col ->
3431 case Code.whatIsNext source row col of
3432 Code.Keyword keyword ->
3434 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3435 region = toKeywordRegion row col keyword
3437 Report.Report "RESERVED WORD" region [] $
3438 Code.toSnippet source surroundings (Just region)
3441 "I am partway through parsing a `case` expression, but I got stuck here:"
3444 "It looks like you are trying to use `" ++ keyword ++ "` in one of your\
3445 \ patterns, but it is a reserved word. Try using a different name?"
3448 Code.Operator ":" ->
3450 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3451 region = toRegion row col
3453 Report.Report "UNEXPECTED OPERATOR" region [] $
3454 Code.toSnippet source surroundings (Just region)
3457 "I am partway through parsing a `case` expression, but I got stuck here:"
3460 ["I","am","seeing",D.dullyellow ":","but","maybe","you","want",D.green "::","instead?"
3461 ,"For","pattern","matching","on","lists?"
3465 Code.Operator "=" ->
3467 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3468 region = toRegion row col
3470 Report.Report "UNEXPECTED OPERATOR" region [] $
3471 Code.toSnippet source surroundings (Just region)
3474 "I am partway through parsing a `case` expression, but I got stuck here:"
3477 ["I","am","seeing",D.dullyellow "=","but","maybe","you","want",D.green "->","instead?"
3483 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3484 region = toRegion row col
3486 Report.Report "MISSING ARROW" region [] $
3487 Code.toSnippet source surroundings (Just region)
3490 "I am partway through parsing a `case` expression, but I got stuck here:"
3493 [ D.reflow "I was expecting to see an arrow next."
3494 , noteForCaseIndentError
3498 CaseExpr expr row col ->
3499 toExprReport source (InNode NCase startRow startCol context) expr row col
3501 CaseBranch expr row col ->
3502 toExprReport source (InNode NBranch startRow startCol context) expr row col
3504 CaseIndentOf row col ->
3505 toUnfinishCaseReport source row col startRow startCol $
3506 D.fillSep ["I","was","expecting","to","see","the",D.dullyellow "of","keyword","next."]
3508 CaseIndentExpr row col ->
3509 toUnfinishCaseReport source row col startRow startCol $
3510 D.reflow "I was expecting to see a expression next."
3512 CaseIndentPattern row col ->
3513 toUnfinishCaseReport source row col startRow startCol $
3514 D.reflow "I was expecting to see a pattern next."
3516 CaseIndentArrow row col ->
3517 toUnfinishCaseReport source row col startRow startCol $
3519 ["I","just","saw","a","pattern,","so","I","was","expecting"
3520 ,"to","see","a",D.dullyellow "->","next."
3523 CaseIndentBranch row col ->
3524 toUnfinishCaseReport source row col startRow startCol $
3526 "I was expecting to see an expression next. What should I do when\
3527 \ I run into this particular pattern?"
3529 CasePatternAlignment indent row col ->
3530 toUnfinishCaseReport source row col startRow startCol $
3532 "I suspect this is a pattern that is not indented far enough? (" ++ show indent ++ " spaces)"
3535toUnfinishCaseReport :: Code.Source -> Row -> Col -> Row -> Col -> D.Doc -> Report.Report
3536toUnfinishCaseReport source row col startRow startCol message =
3538 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3539 region = toRegion row col
3541 Report.Report "UNFINISHED CASE" region [] $
3542 Code.toSnippet source surroundings (Just region)
3545 "I was partway through parsing a `case` expression, but I got stuck here:"
3554noteForCaseError :: D.Doc
3558 "Here is an example of a valid `case` expression for reference."
3560 [ D.indent 4 $ D.fillSep [D.cyan "case","maybeWidth",D.cyan "of"]
3561 , D.indent 6 $ D.fillSep [D.blue "Just","width","->"]
3562 , D.indent 8 $ D.fillSep ["width","+",D.dullyellow "200"]
3564 , D.indent 6 $ D.fillSep [D.blue "Nothing","->"]
3565 , D.indent 8 $ D.fillSep [D.dullyellow "400"]
3568 "Notice the indentation. Each pattern is aligned, and each branch is indented\
3569 \ a bit more than the corresponding pattern. That is important!"
3573noteForCaseIndentError :: D.Doc
3574noteForCaseIndentError =
3577 "Sometimes I get confused by indentation, so try to make your `case` look\
3578 \ something like this:"
3580 [ D.indent 4 $ D.fillSep [D.cyan "case","maybeWidth",D.cyan "of"]
3581 , D.indent 6 $ D.fillSep [D.blue "Just","width","->"]
3582 , D.indent 8 $ D.fillSep ["width","+",D.dullyellow "200"]
3584 , D.indent 6 $ D.fillSep [D.blue "Nothing","->"]
3585 , D.indent 8 $ D.fillSep [D.dullyellow "400"]
3588 "Notice the indentation! Patterns are aligned with each other. Same indentation.\
3589 \ The expressions after each arrow are all indented a bit more than the patterns.\
3590 \ That is important!"
3598toIfReport :: Code.Source -> Context -> If -> Row -> Col -> Report.Report
3599toIfReport source context if_ startRow startCol =
3601 IfSpace space row col ->
3602 toSpaceReport source space row col
3606 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3607 region = toRegion row col
3609 Report.Report "UNFINISHED IF" region [] $
3610 Code.toSnippet source surroundings (Just region)
3613 "I was expecting to see more of this `if` expression, but I got stuck here:"
3616 ["I","was","expecting","to","see","the",D.cyan "then","keyword","next."
3622 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3623 region = toRegion row col
3625 Report.Report "UNFINISHED IF" region [] $
3626 Code.toSnippet source surroundings (Just region)
3629 "I was expecting to see more of this `if` expression, but I got stuck here:"
3632 ["I","was","expecting","to","see","the",D.cyan "else","keyword","next."
3636 IfElseBranchStart row col ->
3638 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3639 region = toRegion row col
3641 Report.Report "UNFINISHED IF" region [] $
3642 Code.toSnippet source surroundings (Just region)
3645 "I just saw the start of an `else` branch, but then I got stuck here:"
3648 "I was expecting to see an expression next. Maybe it is not filled in yet?"
3651 IfCondition expr row col ->
3652 toExprReport source (InNode NCond startRow startCol context) expr row col
3654 IfThenBranch expr row col ->
3655 toExprReport source (InNode NThen startRow startCol context) expr row col
3657 IfElseBranch expr row col ->
3658 toExprReport source (InNode NElse startRow startCol context) expr row col
3660 IfIndentCondition row col ->
3662 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3663 region = toRegion row col
3665 Report.Report "UNFINISHED IF" region [] $
3666 Code.toSnippet source surroundings (Just region)
3669 "I was expecting to see more of this `if` expression, but I got stuck here:"
3673 ["I","was","expecting","to","see","an","expression","like",D.dullyellow "x < 0"
3674 ,"that","evaluates","to","True","or","False."
3677 "I can be confused by indentation. Maybe something is not indented enough?"
3681 IfIndentThen row col ->
3683 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3684 region = toRegion row col
3686 Report.Report "UNFINISHED IF" region [] $
3687 Code.toSnippet source surroundings (Just region)
3690 "I was expecting to see more of this `if` expression, but I got stuck here:"
3694 ["I","was","expecting","to","see","the",D.cyan "then","keyword","next."
3697 "I can be confused by indentation. Maybe something is not indented enough?"
3701 IfIndentThenBranch row col ->
3703 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3704 region = toRegion row col
3706 Report.Report "UNFINISHED IF" region [] $
3707 Code.toSnippet source surroundings (Just region)
3710 "I got stuck after the start of this `then` branch:"
3714 "I was expecting to see an expression next. Maybe it is not filled in yet?"
3716 "I can be confused by indentation, so if the `then` branch is already\
3717 \ present, it may not be indented enough for me to recognize it."
3721 IfIndentElseBranch row col ->
3723 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3724 region = toRegion row col
3726 Report.Report "UNFINISHED IF" region [] $
3727 Code.toSnippet source surroundings (Just region)
3730 "I got stuck after the start of this `else` branch:"
3734 "I was expecting to see an expression next. Maybe it is not filled in yet?"
3736 "I can be confused by indentation, so if the `else` branch is already\
3737 \ present, it may not be indented enough for me to recognize it."
3741 IfIndentElse row col ->
3743 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3744 region = toRegion row col
3746 Report.Report "UNFINISHED IF" region [] $
3747 Code.toSnippet source surroundings (Just region)
3750 "I was expecting to see an `else` branch after this:"
3754 "I know what to do when the condition is `True`, but not when it is `False`."
3756 ["Add","an",D.cyan "else","branch","to","handle","that","scenario!"]
3765toRecordReport :: Code.Source -> Context -> Record -> Row -> Col -> Report.Report
3766toRecordReport source context record startRow startCol =
3768 RecordOpen row col ->
3769 case Code.whatIsNext source row col of
3770 Code.Keyword keyword ->
3772 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3773 region = toKeywordRegion row col keyword
3775 Report.Report "RESERVED WORD" region [] $
3776 Code.toSnippet source surroundings (Just region)
3779 "I just started parsing a record, but I got stuck on this field name:"
3782 "It looks like you are trying to use `" ++ keyword ++ "` as a field name, but \
3783 \ that is a reserved word. Try using a different name!"
3788 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3789 region = toRegion row col
3791 Report.Report "UNFINISHED RECORD" region [] $
3792 Code.toSnippet source surroundings (Just region)
3795 "I just started parsing a record, but I got stuck here:"
3798 ["Records","look","like",D.dullyellow "{ x = 3, y = 4 },"
3799 ,"so","I","was","expecting","to","see","a","field","name","next."
3803 RecordEnd row col ->
3805 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3806 region = toRegion row col
3808 Report.Report "UNFINISHED RECORD" region [] $
3809 Code.toSnippet source surroundings (Just region)
3812 "I am partway through parsing a record, but I got stuck here:"
3816 ["I","was","expecting","to","see","a","closing","curly","brace","before","this,"
3817 ,"so","try","adding","a",D.dullyellow "}","and","see","if","that","helps?"
3820 "When I get stuck like this, it usually means that there is a missing parenthesis\
3821 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
3825 RecordField row col ->
3826 case Code.whatIsNext source row col of
3827 Code.Keyword keyword ->
3829 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3830 region = toKeywordRegion row col keyword
3832 Report.Report "RESERVED WORD" region [] $
3833 Code.toSnippet source surroundings (Just region)
3836 "I am partway through parsing a record, but I got stuck on this field name:"
3839 "It looks like you are trying to use `" ++ keyword ++ "` as a field name, but \
3840 \ that is a reserved word. Try using a different name!"
3845 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3846 region = toRegion row col
3848 Report.Report "UNFINISHED RECORD" region [] $
3849 Code.toSnippet source surroundings (Just region)
3852 "I am partway through parsing a record, but I got stuck after that last comma:"
3854 addNoteForRecordError $
3856 "Trailing commas are not allowed in records, so I was expecting to see another\
3857 \ record field defined next. If you are done defining the record, the fix may\
3858 \ be to delete that last comma?"
3861 RecordEquals row col ->
3863 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3864 region = toRegion row col
3866 Report.Report "UNFINISHED RECORD" region [] $
3867 Code.toSnippet source surroundings (Just region)
3870 "I am partway through parsing a record, but I got stuck here:"
3872 addNoteForRecordError $
3874 ["I","just","saw","a","field","name,","so","I","was","expecting","to","see"
3875 ,"an","equals","sign","next.","So","try","putting","an",D.green "=","sign","here?"
3879 RecordExpr expr row col ->
3880 toExprReport source (InNode NRecord startRow startCol context) expr row col
3882 RecordSpace space row col ->
3883 toSpaceReport source space row col
3885 RecordIndentOpen row col ->
3887 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3888 region = toRegion row col
3890 Report.Report "UNFINISHED RECORD" region [] $
3891 Code.toSnippet source surroundings (Just region)
3894 "I just saw the opening curly brace of a record, but then I got stuck here:"
3896 addNoteForRecordIndentError $
3898 ["I","am","expecting","a","record","like",D.dullyellow "{ x = 3, y = 4 }","here."
3899 ,"Try","defining","some","fields","of","your","own?"
3903 RecordIndentEnd row col ->
3905 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3906 region = toRegion row col
3908 Report.Report "UNFINISHED RECORD" region [] $
3909 Code.toSnippet source surroundings (Just region)
3912 "I was expecting to see a closing curly brace next:"
3914 addNoteForRecordIndentError $
3916 ["Try","putting","an",D.green "}","and","see","if","that","helps?"
3920 RecordIndentField row col ->
3922 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3923 region = toRegion row col
3925 Report.Report "UNFINISHED RECORD" region [] $
3926 Code.toSnippet source surroundings (Just region)
3929 "I am partway through parsing a record, but I got stuck after that last comma:"
3931 addNoteForRecordError $
3933 "Trailing commas are not allowed in records, so the fix may be to\
3934 \ delete that last comma? Or maybe you were in the middle of defining\
3935 \ an additional field?"
3938 RecordIndentEquals row col ->
3940 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3941 region = toRegion row col
3943 Report.Report "UNFINISHED RECORD" region [] $
3944 Code.toSnippet source surroundings (Just region)
3947 "I am partway through parsing a record. I just saw a record\
3948 \ field, so I was expecting to see an equals sign next:"
3950 addNoteForRecordIndentError $
3952 ["Try","putting","an",D.green "=","followed","by","an","expression?"
3956 RecordIndentExpr row col ->
3958 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3959 region = toRegion row col
3961 Report.Report "UNFINISHED RECORD" region [] $
3962 Code.toSnippet source surroundings (Just region)
3965 "I am partway through parsing a record, and I was expecting to run into an expression next:"
3967 addNoteForRecordIndentError $
3969 ["Try","putting","something","like"
3970 ,D.dullyellow "42","or",D.dullyellow"\"hello\"","for","now?"
3975addNoteForRecordError :: D.Doc -> D.Doc
3976addNoteForRecordError normalRecommendation =
3978 normalRecommendation
3981 "If you are trying to define a record across multiple lines, I recommend using this format:"
3982 , D.indent 4 $ D.vcat $
3983 [ "{ name = \"Alice\""
3989 "Notice that each line starts with some indentation. Usually two or four spaces. I\
3990 \ know this style can be jarring for people coming from C-like syntax, but folks generally\
3991 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
3995addNoteForRecordIndentError :: D.Doc -> D.Doc
3996addNoteForRecordIndentError normalRecommendation =
3998 normalRecommendation
4001 "I may be confused by indentation. For example, if you are trying to define\
4002 \ a record across multiple lines, I recommend using this format:"
4003 , D.indent 4 $ D.vcat $
4004 [ "{ name = \"Alice\""
4010 "Notice that each line starts with some indentation. Usually two or four spaces. I\
4011 \ know this style can be jarring for people coming from C-like syntax, but folks generally\
4012 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
4020toTupleReport :: Code.Source -> Context -> Tuple -> Row -> Col -> Report.Report
4021toTupleReport source context tuple startRow startCol =
4023 TupleExpr expr row col ->
4024 toExprReport source (InNode NParens startRow startCol context) expr row col
4026 TupleSpace space row col ->
4027 toSpaceReport source space row col
4031 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4032 region = toRegion row col
4034 Report.Report "UNFINISHED PARENTHESES" region [] $
4035 Code.toSnippet source surroundings (Just region)
4038 "I was expecting to see a closing parentheses next, but I got stuck here:"
4041 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps?"]
4043 "I can get stuck when I run into keywords, operators, parentheses, or brackets\
4044 \ unexpectedly. So there may be some earlier syntax trouble (like extra parenthesis\
4045 \ or missing brackets) that is confusing me."
4049 TupleOperatorClose row col ->
4051 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4052 region = toRegion row col
4054 Report.Report "UNFINISHED OPERATOR FUNCTION" region [] $
4055 Code.toSnippet source surroundings (Just region)
4057 D.reflow "I was expecting a closing parenthesis here:"
4060 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps!"]
4062 "I think I am parsing an operator function right now, so I am expecting to see\
4063 \ something like (+) or (&&) where an operator is surrounded by parentheses with\
4068 TupleOperatorReserved operator row col ->
4070 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4071 region = toRegion row col
4073 Report.Report "UNEXPECTED SYMBOL" region [] $
4074 Code.toSnippet source surroundings (Just region)
4077 "I ran into an unexpected symbol here:"
4081 BadDot -> ["Maybe","you","wanted","a","record","accessor","like",D.dullyellow ".x","or",D.dullyellow ".name","instead?"]
4082 BadPipe -> ["Try",D.dullyellow "(||)","instead?","To","turn","boolean","OR","into","a","function?"]
4083 BadArrow -> ["Maybe","you","wanted",D.dullyellow "(>)","or",D.dullyellow "(>=)","instead?"]
4084 BadEquals -> ["Try",D.dullyellow "(==)","instead?","To","make","a","function","that","checks","equality?"]
4085 BadHasType -> ["Try",D.dullyellow "(::)","instead?","To","add","values","to","the","front","of","lists?"]
4088 TupleIndentExpr1 row col ->
4090 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4091 region = toRegion row col
4093 Report.Report "UNFINISHED PARENTHESES" region [] $
4094 Code.toSnippet source surroundings (Just region)
4097 "I just saw an open parenthesis, so I was expecting to see an expression next."
4101 ["Something","like",D.dullyellow "(4 + 5)","or"
4102 ,D.dullyellow "(String.reverse \"desserts\")" <> "."
4103 ,"Anything","where","you","are","putting","parentheses","around","normal","expressions."
4106 "I can get confused by indentation in cases like this, so\
4107 \ maybe you have an expression but it is not indented enough?"
4111 TupleIndentExprN row col ->
4113 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4114 region = toRegion row col
4116 Report.Report "UNFINISHED TUPLE" region [] $
4117 Code.toSnippet source surroundings (Just region)
4120 "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."
4124 ["A","tuple","looks","like",D.dullyellow "(3,4)","or"
4125 ,D.dullyellow "(\"Tom\",42)" <> ","
4126 ,"so","I","think","there","is","an","expression","missing","here?"
4129 "I can get confused by indentation in cases like this, so\
4130 \ maybe you have an expression but it is not indented enough?"
4134 TupleIndentEnd row col ->
4136 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4137 region = toRegion row col
4139 Report.Report "UNFINISHED PARENTHESES" region [] $
4140 Code.toSnippet source surroundings (Just region)
4143 "I was expecting to see a closing parenthesis next:"
4146 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps!"]
4148 "I can get confused by indentation in cases like this, so\
4149 \ maybe you have a closing parenthesis but it is not indented enough?"
4154toListReport :: Code.Source -> Context -> List -> Row -> Col -> Report.Report
4155toListReport source context list startRow startCol =
4157 ListSpace space row col ->
4158 toSpaceReport source space row col
4162 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4163 region = toRegion row col
4165 Report.Report "UNFINISHED LIST" region [] $
4166 Code.toSnippet source surroundings (Just region)
4169 "I am partway through parsing a list, but I got stuck here:"
4173 ["I","was","expecting","to","see","a","closing","square","bracket","before","this,"
4174 ,"so","try","adding","a",D.dullyellow "]","and","see","if","that","helps?"
4177 "When I get stuck like this, it usually means that there is a missing parenthesis\
4178 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
4182 ListExpr expr row col ->
4186 surroundings = A.Region (A.Position startRow startCol) (A.Position r c)
4187 region = toRegion r c
4189 Report.Report "UNFINISHED LIST" region [] $
4190 Code.toSnippet source surroundings (Just region)
4193 "I was expecting to see another list entry after that last comma:"
4197 "Trailing commas are not allowed in lists, so the fix may be to delete the comma?"
4199 "I recommend using the following format for lists that span multiple lines:"
4200 , D.indent 4 $ D.vcat $
4207 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
4208 \ This style can be jarring for people coming from C-like syntax, but folks generally\
4209 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
4214 toExprReport source (InNode NList startRow startCol context) expr row col
4218 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4219 region = toRegion row col
4221 Report.Report "UNFINISHED LIST" region [] $
4222 Code.toSnippet source surroundings (Just region)
4225 "I am partway through parsing a list, but I got stuck here:"
4229 ["I","was","expecting","to","see","a","closing","square","bracket","before","this,"
4230 ,"so","try","adding","a",D.dullyellow "]","and","see","if","that","helps?"
4233 "When I get stuck like this, it usually means that there is a missing parenthesis\
4234 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
4238 ListIndentOpen row col ->
4240 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4241 region = toRegion row col
4243 Report.Report "UNFINISHED LIST" region [] $
4244 Code.toSnippet source surroundings (Just region)
4247 "I cannot find the end of this list:"
4251 ["You","could","change","it","to","something","like"
4252 ,D.dullyellow "[3,4,5]"
4254 ,D.dullyellow "[]" <> "."
4255 ,"Anything","where","there","is","an","open","and","close","square","brace,"
4256 ,"and","where","the","elements","of","the","list","are","separated","by","commas."
4259 "I may be confused by indentation. For example, if you are trying to define\
4260 \ a list across multiple lines, I recommend using this format:"
4261 , D.indent 4 $ D.vcat $
4268 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
4269 \ This style can be jarring for people coming from C-like syntax, but folks generally\
4270 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
4274 ListIndentEnd row col ->
4276 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4277 region = toRegion row col
4279 Report.Report "UNFINISHED LIST" region [] $
4280 Code.toSnippet source surroundings (Just region)
4283 "I cannot find the end of this list:"
4287 ["You","can","just","add","a","closing",D.dullyellow "]"
4288 ,"right","here,","and","I","will","be","all","set!"
4291 "I may be confused by indentation. For example, if you are trying to define\
4292 \ a list across multiple lines, I recommend using this format:"
4293 , D.indent 4 $ D.vcat $
4300 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
4301 \ This style can be jarring for people coming from C-like syntax, but folks generally\
4302 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
4306 ListIndentExpr row col ->
4308 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4309 region = toRegion row col
4311 Report.Report "UNFINISHED LIST" region [] $
4312 Code.toSnippet source surroundings (Just region)
4315 "I was expecting to see another list entry after this comma:"
4319 "Trailing commas are not allowed in lists, so the fix may be to delete the comma?"
4321 "I recommend using the following format for lists that span multiple lines:"
4322 , D.indent 4 $ D.vcat $
4329 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
4330 \ This style can be jarring for people coming from C-like syntax, but folks generally\
4331 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
4336toFuncReport :: Code.Source -> Context -> Func -> Row -> Col -> Report.Report
4337toFuncReport source context func startRow startCol =
4339 FuncSpace space row col ->
4340 toSpaceReport source space row col
4342 FuncArg pattern row col ->
4343 toPatternReport source PArg pattern row col
4345 FuncBody expr row col ->
4346 toExprReport source (InNode NFunc startRow startCol context) expr row col
4348 FuncArrow row col ->
4349 case Code.whatIsNext source row col of
4350 Code.Keyword keyword ->
4352 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4353 region = toKeywordRegion row col keyword
4355 Report.Report "RESERVED WORD" region [] $
4356 Code.toSnippet source surroundings (Just region)
4359 "I was parsing an anonymous function, but I got stuck here:"
4362 "It looks like you are trying to use `" ++ keyword ++ "` as an argument, but\
4363 \ it is a reserved word in this language. Try using a different argument name!"
4368 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4369 region = toRegion row col
4371 Report.Report "UNFINISHED ANONYMOUS FUNCTION" region [] $
4372 Code.toSnippet source surroundings (Just region)
4375 "I just saw the beginning of an anonymous function, so I was expecting to see an arrow next:"
4378 ["The","syntax","for","anonymous","functions","is"
4379 ,D.dullyellow "(\\x -> x + 1)"
4380 ,"so","I","am","missing","the","arrow","and","the","body","of","the","function."
4384 FuncIndentArg row col ->
4386 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4387 region = toRegion row col
4389 Report.Report "MISSING ARGUMENT" region [] $
4390 Code.toSnippet source surroundings (Just region)
4393 "I just saw the beginning of an anonymous function, so I was expecting to see an argument next:"
4397 ["Something","like",D.dullyellow"x","or",D.dullyellow "name" <> "."
4398 ,"Anything","that","starts","with","a","lower","case","letter!"
4401 "The syntax for anonymous functions is (\\x -> x + 1) where the backslash\
4402 \ is meant to look a bit like a lambda if you squint. This visual pun seemed\
4403 \ like a better idea at the time!"
4407 FuncIndentArrow row col ->
4409 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4410 region = toRegion row col
4412 Report.Report "UNFINISHED ANONYMOUS FUNCTION" region [] $
4413 Code.toSnippet source surroundings (Just region)
4416 "I just saw the beginning of an anonymous function, so I was expecting to see an arrow next:"
4420 ["The","syntax","for","anonymous","functions","is"
4421 ,D.dullyellow "(\\x -> x + 1)"
4422 ,"so","I","am","missing","the","arrow","and","the","body","of","the","function."
4425 "It is possible that I am confused about indetation! I generally recommend\
4426 \ switching to named functions if the definition cannot fit inline nicely, so\
4427 \ either (1) try to fit the whole anonymous function on one line or (2) break\
4428 \ the whole thing out into a named function. Things tend to be clearer that way!"
4432 FuncIndentBody row col ->
4434 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4435 region = toRegion row col
4437 Report.Report "UNFINISHED ANONYMOUS FUNCTION" region [] $
4438 Code.toSnippet source surroundings (Just region)
4441 "I was expecting to see the body of your anonymous function next:"
4445 ["The","syntax","for","anonymous","functions","is"
4446 ,D.dullyellow "(\\x -> x + 1)"
4447 ,"so","I","am","missing","all","the","stuff","after","the","arrow!"
4450 "It is possible that I am confused about indetation! I generally recommend\
4451 \ switching to named functions if the definition cannot fit inline nicely, so\
4452 \ either (1) try to fit the whole anonymous function on one line or (2) break\
4453 \ the whole thing out into a named function. Things tend to be clearer that way!"
4468toPatternReport :: Code.Source -> PContext -> Pattern -> Row -> Col -> Report.Report
4469toPatternReport source context pattern startRow startCol =
4471 PRecord record row col ->
4472 toPRecordReport source record row col
4474 PTuple tuple row col ->
4475 toPTupleReport source context tuple row col
4477 PList list row col ->
4478 toPListReport source context list row col
4481 case Code.whatIsNext source row col of
4482 Code.Keyword keyword ->
4484 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4485 region = toKeywordRegion row col keyword
4488 PArg -> "as an argument"
4489 PCase -> "in this pattern"
4490 PLet -> "in this pattern"
4492 Report.Report "RESERVED WORD" region [] $
4493 Code.toSnippet source surroundings (Just region)
4496 "It looks like you are trying to use `" ++ keyword ++ "` " ++ inThisThing ++ ":"
4499 "This is a reserved word! Try using some other name?"
4502 Code.Operator "-" ->
4504 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4505 region = toRegion row col
4507 Report.Report "UNEXPECTED SYMBOL" region [] $
4508 Code.toSnippet source surroundings (Just region)
4511 "I ran into a minus sign unexpectedly in this pattern:"
4514 "It is not possible to pattern match on negative numbers at this\
4515 \ time. Try using an `if` expression for that sort of thing for now."
4520 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4521 region = toRegion row col
4523 Report.Report "PROBLEM IN PATTERN" region [] $
4524 Code.toSnippet source surroundings (Just region)
4527 "I wanted to parse a pattern next, but I got stuck here:"
4530 ["I","am","not","sure","why","I","am","getting","stuck","exactly."
4531 ,"I","just","know","that","I","want","a","pattern","next."
4532 ,"Something","as","simple","as"
4533 ,D.dullyellow "maybeHeight","or",D.dullyellow "result"
4538 PChar char row col ->
4539 toCharReport source char row col
4541 PString string row col ->
4542 toStringReport source string row col
4544 PNumber number row col ->
4545 toNumberReport source number row col
4547 PFloat width row col ->
4549 region = toWiderRegion row col width
4551 Report.Report "UNEXPECTED PATTERN" region [] $
4552 Code.toSnippet source region Nothing
4555 "I cannot pattern match with floating point numbers:"
4558 ["Equality","on","floats","can","be","unreliable,","so","you","usually","want"
4559 ,"to","check","that","they","are","nearby","with","some","sort","of"
4560 ,D.dullyellow "(abs (actual - expected) < 0.001)","check."
4566 region = toRegion row col
4568 Report.Report "UNFINISHED PATTERN" region [] $
4569 Code.toSnippet source region Nothing $
4572 "I was expecting to see a variable name after the `as` keyword:"
4576 ["The","`as`","keyword","lets","you","write","patterns","like"
4577 ,"((" <> D.dullyellow "x" <> "," <> D.dullyellow "y" <> ") " <> D.cyan "as" <> D.dullyellow " point" <> ")"
4578 ,"so","you","can","refer","to","individual","parts","of","the","tuple","with"
4579 ,D.dullyellow "x","and",D.dullyellow "y","or","you","refer","to","the","whole"
4580 ,"thing","with",D.dullyellow "point" <> "."
4583 "So I was expecting to see a variable name after the `as` keyword here. Sometimes\
4584 \ people just want to use `as` as a variable name though. Try using a different name\
4589 PWildcardNotVar name width row col ->
4591 region = toWiderRegion row col (fromIntegral width)
4593 case dropWhile (=='_') (Name.toChars name) of
4594 [] -> [D.dullyellow "x","or",D.dullyellow "age"]
4595 c:cs -> [D.dullyellow (D.fromChars (Char.toLower c : cs))]
4597 Report.Report "UNEXPECTED NAME" region [] $
4598 Code.toSnippet source region Nothing $
4601 "Variable names cannot start with underscores like this:"
4604 ["You","can","either","have","an","underscore","like",D.dullyellow "_","to"
4605 ,"ignore","the","value,","or","you","can","have","a","name","like"
4606 ] ++ examples ++ ["to","use","the","matched","value." ]
4609 PSpace space row col ->
4610 toSpaceReport source space row col
4612 PIndentStart row col ->
4614 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4615 region = toRegion row col
4617 Report.Report "UNFINISHED PATTERN" region [] $
4618 Code.toSnippet source surroundings (Just region)
4621 "I wanted to parse a pattern next, but I got stuck here:"
4625 ["I","am","not","sure","why","I","am","getting","stuck","exactly."
4626 ,"I","just","know","that","I","want","a","pattern","next."
4627 ,"Something","as","simple","as"
4628 ,D.dullyellow "maybeHeight","or",D.dullyellow "result"
4632 "I can get confused by indentation. If you think there is a pattern next, maybe\
4633 \ it needs to be indented a bit more?"
4637 PIndentAlias row col ->
4639 region = toRegion row col
4641 Report.Report "UNFINISHED PATTERN" region [] $
4642 Code.toSnippet source region Nothing $
4645 "I was expecting to see a variable name after the `as` keyword:"
4649 ["The","`as`","keyword","lets","you","write","patterns","like"
4650 ,"((" <> D.dullyellow "x" <> "," <> D.dullyellow "y" <> ") " <> D.cyan "as" <> D.dullyellow " point" <> ")"
4651 ,"so","you","can","refer","to","individual","parts","of","the","tuple","with"
4652 ,D.dullyellow "x","and",D.dullyellow "y","or","you","refer","to","the","whole"
4653 ,"thing","with",D.dullyellow "point."
4656 "So I was expecting to see a variable name after the `as` keyword here. Sometimes\
4657 \ people just want to use `as` as a variable name though. Try using a different name\
4663toPRecordReport :: Code.Source -> PRecord -> Row -> Col -> Report.Report
4664toPRecordReport source record startRow startCol =
4666 PRecordOpen row col ->
4667 toUnfinishRecordPatternReport source row col startRow startCol $
4668 D.reflow "I was expecting to see a field name next."
4670 PRecordEnd row col ->
4671 toUnfinishRecordPatternReport source row col startRow startCol $
4673 ["I","was","expecting","to","see","a","closing","curly","brace","next."
4674 ,"Try","adding","a",D.dullyellow "}","here?"
4677 PRecordField row col ->
4678 case Code.whatIsNext source row col of
4679 Code.Keyword keyword ->
4681 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4682 region = toKeywordRegion row col keyword
4684 Report.Report "RESERVED WORD" region [] $
4685 Code.toSnippet source surroundings (Just region)
4688 "I was not expecting to see `" ++ keyword ++ "` as a record field name:"
4691 "This is a reserved word, not available for variable names. Try another name!"
4695 toUnfinishRecordPatternReport source row col startRow startCol $
4696 D.reflow "I was expecting to see a field name next."
4698 PRecordSpace space row col ->
4699 toSpaceReport source space row col
4701 PRecordIndentOpen row col ->
4702 toUnfinishRecordPatternReport source row col startRow startCol $
4703 D.reflow "I was expecting to see a field name next."
4705 PRecordIndentEnd row col ->
4706 toUnfinishRecordPatternReport source row col startRow startCol $
4708 ["I","was","expecting","to","see","a","closing","curly","brace","next."
4709 ,"Try","adding","a",D.dullyellow "}","here?"
4712 PRecordIndentField row col ->
4713 toUnfinishRecordPatternReport source row col startRow startCol $
4714 D.reflow "I was expecting to see a field name next."
4717toUnfinishRecordPatternReport :: Code.Source -> Row -> Col -> Row -> Col -> D.Doc -> Report.Report
4718toUnfinishRecordPatternReport source row col startRow startCol message =
4720 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4721 region = toRegion row col
4723 Report.Report "UNFINISHED RECORD PATTERN" region [] $
4724 Code.toSnippet source surroundings (Just region)
4727 "I was partway through parsing a record pattern, but I got stuck here:"
4732 ["A","record","pattern","looks","like",D.dullyellow "{x,y}","or",D.dullyellow "{name,age}"
4733 ,"where","you","list","the","field","names","you","want","to","access."
4740toPTupleReport :: Code.Source -> PContext -> PTuple -> Row -> Col -> Report.Report
4741toPTupleReport source context tuple startRow startCol =
4743 PTupleOpen row col ->
4744 case Code.whatIsNext source row col of
4745 Code.Keyword keyword ->
4747 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4748 region = toKeywordRegion row col keyword
4750 Report.Report "RESERVED WORD" region [] $
4751 Code.toSnippet source surroundings (Just region)
4754 "It looks like you are trying to use `" ++ keyword ++ "` as a variable name:"
4757 "This is a reserved word! Try using some other name?"
4762 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4763 region = toRegion row col
4765 Report.Report "UNFINISHED PARENTHESES" region [] $
4766 Code.toSnippet source surroundings (Just region)
4769 "I just saw an open parenthesis, but I got stuck here:"
4772 ["I","was","expecting","to","see","a","pattern","next."
4773 ,"Maybe","it","will","end","up","being","something"
4774 ,"like",D.dullyellow "(x,y)","or",D.dullyellow "(name, _)" <> "?"
4778 PTupleEnd row col ->
4779 case Code.whatIsNext source row col of
4780 Code.Keyword keyword ->
4782 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4783 region = toKeywordRegion row col keyword
4785 Report.Report "RESERVED WORD" region [] $
4786 Code.toSnippet source surroundings (Just region) $
4789 "I ran into a reserved word in this pattern:"
4792 "The `" ++ keyword ++ "` keyword is reserved. Try using a different name instead!"
4797 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4798 region = toKeywordRegion row col op
4800 Report.Report "UNEXPECTED SYMBOL" region [] $
4801 Code.toSnippet source surroundings (Just region) $
4804 "I ran into the " ++ op ++ " symbol unexpectedly in this pattern:"
4807 "Only the :: symbol that works in patterns. It is useful if you\
4808 \ are pattern matching on lists, trying to get the first element\
4809 \ off the front. Did you want that instead?"
4812 Code.Close term bracket ->
4814 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4815 region = toRegion row col
4817 Report.Report ("STRAY " ++ map Char.toUpper term) region [] $
4818 Code.toSnippet source surroundings (Just region) $
4821 "I ran into a an unexpected " ++ term ++ " in this pattern:"
4824 "This " ++ bracket : " does not match up with an earlier open " ++ term ++ ". Try deleting it?"
4829 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4830 region = toRegion row col
4832 Report.Report "UNFINISHED PARENTHESES" region [] $
4833 Code.toSnippet source surroundings (Just region) $
4836 "I was partway through parsing a pattern, but I got stuck here:"
4839 ["I","was","expecting","a","closing","parenthesis","next,","so"
4840 ,"try","adding","a",D.dullyellow ")","to","see","if","that","helps?"
4844 PTupleExpr pattern row col ->
4845 toPatternReport source context pattern row col
4847 PTupleSpace space row col ->
4848 toSpaceReport source space row col
4850 PTupleIndentEnd row col ->
4852 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4853 region = toRegion row col
4855 Report.Report "UNFINISHED PARENTHESES" region [] $
4856 Code.toSnippet source surroundings (Just region) $
4859 "I was expecting a closing parenthesis next:"
4862 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps?"]
4864 "I can get confused by indentation in cases like this, so\
4865 \ maybe you have a closing parenthesis but it is not indented enough?"
4869 PTupleIndentExpr1 row col ->
4871 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4872 region = toRegion row col
4874 Report.Report "UNFINISHED PARENTHESES" region [] $
4875 Code.toSnippet source surroundings (Just region) $
4878 "I just saw an open parenthesis, but then I got stuck here:"
4881 ["I","was","expecting","to","see","a","pattern","next."
4882 ,"Maybe","it","will","end","up","being","something"
4883 ,"like",D.dullyellow "(x,y)","or",D.dullyellow "(name, _)" <> "?"
4887 PTupleIndentExprN row col ->
4889 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4890 region = toRegion row col
4892 Report.Report "UNFINISHED TUPLE PATTERN" region [] $
4893 Code.toSnippet source surroundings (Just region) $
4896 "I am partway through parsing a tuple pattern, but I got stuck here:"
4900 ["I","was","expecting","to","see","a","pattern","next."
4901 ,"I","am","expecting","the","final","result","to","be","something"
4902 ,"like",D.dullyellow "(x,y)","or",D.dullyellow "(name, _)" <> "."
4905 "I can get confused by indentation in cases like this, so the problem\
4906 \ may be that the next part is not indented enough?"
4911toPListReport :: Code.Source -> PContext -> PList -> Row -> Col -> Report.Report
4912toPListReport source context list startRow startCol =
4914 PListOpen row col ->
4915 case Code.whatIsNext source row col of
4916 Code.Keyword keyword ->
4918 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4919 region = toKeywordRegion row col keyword
4921 Report.Report "RESERVED WORD" region [] $
4922 Code.toSnippet source surroundings (Just region)
4925 "It looks like you are trying to use `" ++ keyword ++ "` to name an element of a list:"
4928 "This is a reserved word though! Try using some other name?"
4933 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4934 region = toRegion row col
4936 Report.Report "UNFINISHED LIST PATTERN" region [] $
4937 Code.toSnippet source surroundings (Just region) $
4940 "I just saw an open square bracket, but then I got stuck here:"
4942 D.fillSep ["Try","adding","a",D.dullyellow "]","to","see","if","that","helps?"]
4947 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4948 region = toRegion row col
4950 Report.Report "UNFINISHED LIST PATTERN" region [] $
4951 Code.toSnippet source surroundings (Just region) $
4954 "I was expecting a closing square bracket to end this list pattern:"
4956 D.fillSep ["Try","adding","a",D.dullyellow "]","to","see","if","that","helps?"]
4959 PListExpr pattern row col ->
4960 toPatternReport source context pattern row col
4962 PListSpace space row col ->
4963 toSpaceReport source space row col
4965 PListIndentOpen row col ->
4967 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4968 region = toRegion row col
4970 Report.Report "UNFINISHED LIST PATTERN" region [] $
4971 Code.toSnippet source surroundings (Just region) $
4974 "I just saw an open square bracket, but then I got stuck here:"
4977 [ D.fillSep ["Try","adding","a",D.dullyellow "]","to","see","if","that","helps?"]
4979 "I can get confused by indentation in cases like this, so\
4980 \ maybe there is something next, but it is not indented enough?"
4984 PListIndentEnd row col ->
4986 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4987 region = toRegion row col
4989 Report.Report "UNFINISHED LIST PATTERN" region [] $
4990 Code.toSnippet source surroundings (Just region) $
4993 "I was expecting a closing square bracket to end this list pattern:"
4996 [ D.fillSep ["Try","adding","a",D.dullyellow "]","to","see","if","that","helps?"]
4998 "I can get confused by indentation in cases like this, so\
4999 \ maybe you have a closing square bracket but it is not indented enough?"
5003 PListIndentExpr row col ->
5005 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5006 region = toRegion row col
5008 Report.Report "UNFINISHED LIST PATTERN" region [] $
5009 Code.toSnippet source surroundings (Just region) $
5012 "I am partway through parsing a list pattern, but I got stuck here:"
5016 "I was expecting to see another pattern next. Maybe a variable name."
5018 "I can get confused by indentation in cases like this, so\
5019 \ maybe there is more to this pattern but it is not indented enough?"
5029 = TC_Annotation Name.Name
5035toTypeReport :: Code.Source -> TContext -> Type -> Row -> Col -> Report.Report
5036toTypeReport source context tipe startRow startCol =
5038 TRecord record row col ->
5039 toTRecordReport source context record row col
5041 TTuple tuple row col ->
5042 toTTupleReport source context tuple row col
5045 case Code.whatIsNext source row col of
5046 Code.Keyword keyword ->
5048 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5049 region = toKeywordRegion row col keyword
5051 Report.Report "RESERVED WORD" region [] $
5052 Code.toSnippet source surroundings (Just region)
5055 "I was expecting to see a type next, but I got stuck on this reserved word:"
5058 "It looks like you are trying to use `" ++ keyword ++ "` as a type variable, but \
5059 \ it is a reserved word. Try using a different name!"
5064 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5065 region = toRegion row col
5069 TC_Annotation _ -> "type annotation"
5070 TC_CustomType -> "custom type"
5071 TC_TypeAlias -> "type alias"
5076 TC_Annotation name -> "the `" ++ Name.toChars name ++ "` type annotation"
5077 TC_CustomType -> "a custom type"
5078 TC_TypeAlias -> "a type alias"
5081 Report.Report ("PROBLEM IN " ++ map Char.toUpper thing) region [] $
5082 Code.toSnippet source surroundings (Just region)
5085 "I was partway through parsing " ++ something ++ ", but I got stuck here:"
5088 ["I","was","expecting","to","see","a","type","next."
5089 ,"Try","putting",D.dullyellow "Int","or",D.dullyellow "String","for","now?"
5093 TSpace space row col ->
5094 toSpaceReport source space row col
5096 TIndentStart row col ->
5098 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5099 region = toRegion row col
5103 TC_Annotation _ -> "type annotation"
5104 TC_CustomType -> "custom type"
5105 TC_TypeAlias -> "type alias"
5108 Report.Report ("UNFINISHED " ++ map Char.toUpper thing) region [] $
5109 Code.toSnippet source surroundings (Just region)
5112 "I was partway through parsing a " ++ thing ++ ", but I got stuck here:"
5116 ["I","was","expecting","to","see","a","type","next."
5117 ,"Try","putting",D.dullyellow "Int","or",D.dullyellow "String","for","now?"
5120 "I can get confused by indentation. If you think there is already a type\
5121 \ next, maybe it is not indented enough?"
5126toTRecordReport :: Code.Source -> TContext -> TRecord -> Row -> Col -> Report.Report
5127toTRecordReport source context record startRow startCol =
5129 TRecordOpen row col ->
5130 case Code.whatIsNext source row col of
5131 Code.Keyword keyword ->
5133 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5134 region = toKeywordRegion row col keyword
5136 Report.Report "RESERVED WORD" region [] $
5137 Code.toSnippet source surroundings (Just region)
5140 "I just started parsing a record type, but I got stuck on this field name:"
5143 "It looks like you are trying to use `" ++ keyword ++ "` as a field name, but \
5144 \ that is a reserved word. Try using a different name!"
5149 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5150 region = toRegion row col
5152 Report.Report "UNFINISHED RECORD TYPE" region [] $
5153 Code.toSnippet source surroundings (Just region)
5156 "I just started parsing a record type, but I got stuck here:"
5159 ["Record","types","look","like",D.dullyellow "{ name : String, age : Int },"
5160 ,"so","I","was","expecting","to","see","a","field","name","next."
5164 TRecordEnd row col ->
5166 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5167 region = toRegion row col
5169 Report.Report "UNFINISHED RECORD TYPE" region [] $
5170 Code.toSnippet source surroundings (Just region)
5173 "I am partway through parsing a record type, but I got stuck here:"
5177 ["I","was","expecting","to","see","a","closing","curly","brace","before","this,"
5178 ,"so","try","adding","a",D.dullyellow "}","and","see","if","that","helps?"
5181 "When I get stuck like this, it usually means that there is a missing parenthesis\
5182 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
5186 TRecordField row col ->
5187 case Code.whatIsNext source row col of
5188 Code.Keyword keyword ->
5190 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5191 region = toKeywordRegion row col keyword
5193 Report.Report "RESERVED WORD" region [] $
5194 Code.toSnippet source surroundings (Just region)
5197 "I am partway through parsing a record type, but I got stuck on this field name:"
5200 "It looks like you are trying to use `" ++ keyword ++ "` as a field name, but \
5201 \ that is a reserved word. Try using a different name!"
5206 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5207 region = toRegion row col
5209 Report.Report "UNFINISHED RECORD TYPE" region [] $
5210 Code.toSnippet source surroundings (Just region)
5213 "I am partway through parsing a record type, but I got stuck after that last comma:"
5215 addNoteForRecordTypeError $
5217 "Trailing commas are not allowed in records, so I was expecting to see another\
5218 \ record field defined next. If you are done defining the record, the fix may\
5219 \ be to delete that last comma?"
5222 TRecordColon row col ->
5224 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5225 region = toRegion row col
5227 Report.Report "UNFINISHED RECORD TYPE" region [] $
5228 Code.toSnippet source surroundings (Just region)
5231 "I am partway through parsing a record type, but I got stuck here:"
5233 addNoteForRecordTypeError $
5235 ["I","just","saw","a","field","name,","so","I","was","expecting","to","see"
5236 ,"a","colon","next.","So","try","putting","an",D.green ":","sign","here?"
5240 TRecordType tipe row col ->
5241 toTypeReport source context tipe row col
5243 TRecordSpace space row col ->
5244 toSpaceReport source space row col
5246 TRecordIndentOpen row col ->
5248 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5249 region = toRegion row col
5251 Report.Report "UNFINISHED RECORD TYPE" region [] $
5252 Code.toSnippet source surroundings (Just region)
5255 "I just saw the opening curly brace of a record type, but then I got stuck here:"
5257 addNoteForRecordTypeIndentError $
5259 ["I","am","expecting","a","record","like",D.dullyellow "{ name : String, age : Int }","here."
5260 ,"Try","defining","some","fields","of","your","own?"
5264 TRecordIndentEnd row col ->
5266 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5267 region = toRegion row col
5269 Report.Report "UNFINISHED RECORD TYPE" region [] $
5270 Code.toSnippet source surroundings (Just region)
5273 "I was expecting to see a closing curly brace next:"
5275 addNoteForRecordTypeIndentError $
5277 ["Try","putting","an",D.green "}","and","see","if","that","helps?"
5281 TRecordIndentField row col ->
5283 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5284 region = toRegion row col
5286 Report.Report "UNFINISHED RECORD TYPE" region [] $
5287 Code.toSnippet source surroundings (Just region)
5290 "I am partway through parsing a record type, but I got stuck after that last comma:"
5292 addNoteForRecordTypeIndentError $
5294 "Trailing commas are not allowed in record types, so the fix may be to\
5295 \ delete that last comma? Or maybe you were in the middle of defining\
5296 \ an additional field?"
5299 TRecordIndentColon row col ->
5301 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5302 region = toRegion row col
5304 Report.Report "UNFINISHED RECORD TYPE" region [] $
5305 Code.toSnippet source surroundings (Just region)
5308 "I am partway through parsing a record type. I just saw a record\
5309 \ field, so I was expecting to see a colon next:"
5311 addNoteForRecordTypeIndentError $
5313 ["Try","putting","an",D.green ":","followed","by","a","type?"
5317 TRecordIndentType row col ->
5319 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5320 region = toRegion row col
5322 Report.Report "UNFINISHED RECORD TYPE" region [] $
5323 Code.toSnippet source surroundings (Just region)
5326 "I am partway through parsing a record type, and I was expecting to run into a type next:"
5328 addNoteForRecordTypeIndentError $
5330 ["Try","putting","something","like"
5331 ,D.dullyellow "Int","or",D.dullyellow "String","for","now?"
5336addNoteForRecordTypeError :: D.Doc -> D.Doc
5337addNoteForRecordTypeError normalRecommendation =
5339 normalRecommendation
5342 "If you are trying to define a record type across multiple lines, I recommend using this format:"
5343 , D.indent 4 $ D.vcat $
5346 , ", height : Float"
5350 "Notice that each line starts with some indentation. Usually two or four spaces. I\
5351 \ know this style can be jarring for people coming from C-like syntax, but folks generally\
5352 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
5356addNoteForRecordTypeIndentError :: D.Doc -> D.Doc
5357addNoteForRecordTypeIndentError normalRecommendation =
5359 normalRecommendation
5362 "I may be confused by indentation. For example, if you are trying to define\
5363 \ a record type across multiple lines, I recommend using this format:"
5364 , D.indent 4 $ D.vcat $
5367 , ", height : Float"
5371 "Notice that each line starts with some indentation. Usually two or four spaces. I\
5372 \ know this style can be jarring for people coming from C-like syntax, but folks generally\
5373 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
5377toTTupleReport :: Code.Source -> TContext -> TTuple -> Row -> Col -> Report.Report
5378toTTupleReport source context tuple startRow startCol =
5380 TTupleOpen row col ->
5381 case Code.whatIsNext source row col of
5382 Code.Keyword keyword ->
5384 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5385 region = toKeywordRegion row col keyword
5387 Report.Report "RESERVED WORD" region [] $
5388 Code.toSnippet source surroundings (Just region)
5391 "I ran into a reserved word unexpectedly:"
5394 "It looks like you are trying to use `" ++ keyword ++ "` as a variable name, but \
5395 \ it is a reserved word. Try using a different name!"
5400 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5401 region = toRegion row col
5403 Report.Report "UNFINISHED PARENTHESES" region [] $
5404 Code.toSnippet source surroundings (Just region)
5407 "I just saw an open parenthesis, so I was expecting to see a type next."
5410 ["Something","like",D.dullyellow "(Maybe Int)","or"
5411 ,D.dullyellow "(List Person)" <> "."
5412 ,"Anything","where","you","are","putting","parentheses","around","normal","types."
5416 TTupleEnd row col ->
5418 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5419 region = toRegion row col
5421 Report.Report "UNFINISHED PARENTHESES" region [] $
5422 Code.toSnippet source surroundings (Just region)
5425 "I was expecting to see a closing parenthesis next, but I got stuck here:"
5428 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps?"]
5430 "I can get stuck when I run into keywords, operators, parentheses, or brackets\
5431 \ unexpectedly. So there may be some earlier syntax trouble (like extra parenthesis\
5432 \ or missing brackets) that is confusing me."
5436 TTupleType tipe row col ->
5437 toTypeReport source context tipe row col
5439 TTupleSpace space row col ->
5440 toSpaceReport source space row col
5442 TTupleIndentType1 row col ->
5444 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5445 region = toRegion row col
5447 Report.Report "UNFINISHED PARENTHESES" region [] $
5448 Code.toSnippet source surroundings (Just region)
5451 "I just saw an open parenthesis, so I was expecting to see a type next."
5455 ["Something","like",D.dullyellow "(Maybe Int)","or"
5456 ,D.dullyellow "(List Person)" <> "."
5457 ,"Anything","where","you","are","putting","parentheses","around","normal","types."
5460 "I can get confused by indentation in cases like this, so\
5461 \ maybe you have a type but it is not indented enough?"
5465 TTupleIndentTypeN row col ->
5467 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5468 region = toRegion row col
5470 Report.Report "UNFINISHED TUPLE TYPE" region [] $
5471 Code.toSnippet source surroundings (Just region)
5474 "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."
5478 ["A","tuple","type","looks","like",D.dullyellow "(Float,Float)","or"
5479 ,D.dullyellow "(String,Int)" <> ","
5480 ,"so","I","think","there","is","a","type","missing","here?"
5483 "I can get confused by indentation in cases like this, so\
5484 \ maybe you have an expression but it is not indented enough?"
5488 TTupleIndentEnd row col ->
5490 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5491 region = toRegion row col
5493 Report.Report "UNFINISHED PARENTHESES" region [] $
5494 Code.toSnippet source surroundings (Just region)
5497 "I was expecting to see a closing parenthesis next:"
5500 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps!"]
5502 "I can get confused by indentation in cases like this, so\
5503 \ maybe you have a closing parenthesis but it is not indented enough?"
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list