1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
3module Reporting.Error.Syntax
47import Prelude hiding (Char, String)
48import qualified Data.Char as Char
49import qualified Data.Name as Name
50import Data.Word (Word16)
51import Numeric (showHex)
53import qualified Elm.ModuleName as ModuleName
54import Parse.Primitives (Row, Col)
55import Parse.Symbol (BadOperator(..))
56import qualified Reporting.Annotation as A
57import qualified Reporting.Doc as D
58import qualified Reporting.Report as Report
59import qualified Reporting.Render.Code as Code
67 = ModuleNameUnspecified ModuleName.Raw
68 | ModuleNameMismatch ModuleName.Raw (A.Located ModuleName.Raw)
69 | UnexpectedPort A.Region
79 = ModuleSpace Space Row Col
80 | ModuleEndOfFile Row Col
82 | ModuleProblem Row Col
84 | ModuleExposing Exposing Row Col
86 | PortModuleProblem Row Col
87 | PortModuleName Row Col
88 | PortModuleExposing Exposing Row Col
98 | ImportExposing Row Col
99 | ImportExposingList Exposing Row Col
100 | ImportEnd Row Col -- different based on col=1 or if greater
102 | ImportIndentName Row Col
103 | ImportIndentAlias Row Col
104 | ImportIndentExposingList Row Col
108 | Declarations Decl Row Col
112 = ExposingSpace Space Row Col
113 | ExposingStart Row Col
114 | ExposingValue Row Col
115 | ExposingOperator Row Col
116 | ExposingOperatorReserved BadOperator Row Col
117 | ExposingOperatorRightParen Row Col
118 | ExposingTypePrivacy Row Col
119 | ExposingEnd Row Col
121 | ExposingIndentEnd Row Col
122 | ExposingIndentValue Row Col
131 | DeclSpace Space Row Col
134 | DeclType DeclType Row Col
135 | DeclDef Name.Name DeclDef Row Col
137 | DeclFreshLineStart 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
228 | IndentMoreExpr Row Col
234 | RecordField Row Col
235 | RecordEquals Row Col
236 | RecordExpr Expr Row Col
237 | RecordSpace Space Row Col
239 | RecordIndentOpen Row Col
240 | RecordIndentEnd Row Col
241 | RecordIndentField Row Col
242 | RecordIndentEquals Row Col
243 | RecordIndentExpr Row Col
247 = TupleExpr Expr Row Col
248 | TupleSpace Space Row Col
250 | TupleOperatorClose Row Col
251 | TupleOperatorReserved BadOperator Row Col
253 | TupleIndentExpr1 Row Col
254 | TupleIndentExprN Row Col
255 | TupleIndentEnd Row Col
259 = ListSpace Space Row Col
261 | ListExpr Expr Row Col
264 | ListIndentOpen Row Col
265 | ListIndentEnd Row Col
266 | ListIndentExpr Row Col
270 = FuncSpace Space Row Col
271 | FuncArg Pattern Row Col
272 | FuncBody Expr Row Col
275 | FuncIndentArg Row Col
276 | FuncIndentArrow Row Col
277 | FuncIndentBody Row Col
281 = CaseSpace Space Row Col
283 | CasePattern Pattern Row Col
285 | CaseExpr Expr Row Col
286 | CaseBranch Expr Row Col
288 | CaseIndentOf Row Col
289 | CaseIndentExpr Row Col
290 | CaseIndentPattern Row Col
291 | CaseIndentArrow Row Col
292 | CaseIndentBranch Row Col
293 | CasePatternAlignment Word16 Row Col
297 = IfSpace Space Row Col
300 | IfElseBranchStart Row Col
302 | IfCondition Expr Row Col
303 | IfThenBranch Expr Row Col
304 | IfElseBranch Expr Row Col
306 | IfIndentCondition Row Col
307 | IfIndentThen Row Col
308 | IfIndentThenBranch Row Col
309 | IfIndentElseBranch Row Col
310 | IfIndentElse Row Col
314 = LetSpace Space Row Col
316 | LetDefAlignment Word16 Row Col
318 | LetDef Name.Name Def Row Col
319 | LetDestruct Destruct Row Col
320 | LetBody Expr Row Col
321 | LetIndentDef Row Col
322 | LetIndentIn Row Col
323 | LetIndentBody Row Col
327 = DefSpace Space Row Col
328 | DefType Type Row Col
329 | DefNameRepeat Name.Name Row Col
330 | DefNameMatch Name.Name Name.Name Row Col
331 | DefArg Pattern Row Col
333 | DefBody Expr Row Col
334 | DefIndentEquals Row Col
335 | DefIndentType Row Col
336 | DefIndentBody Row Col
337 | DefAlignment Word16 Row Col
341 = DestructSpace Space Row Col
342 | DestructPattern Pattern Row Col
343 | DestructEquals Row Col
344 | DestructBody Expr Row Col
345 | DestructIndentEquals Row Col
346 | DestructIndentBody Row Col
354 = PRecord PRecord Row Col
355 | PTuple PTuple Row Col
356 | PList PList Row Col
360 | PString String Row Col
361 | PNumber Number Row Col
362 | PFloat Word16 Row Col
364 | PWildcardNotVar Name.Name Int Row Col
365 | PSpace Space Row Col
367 | PIndentStart Row Col
368 | PIndentAlias Row Col
372 = PRecordOpen Row Col
374 | PRecordField Row Col
375 | PRecordSpace Space Row Col
377 | PRecordIndentOpen Row Col
378 | PRecordIndentEnd Row Col
379 | PRecordIndentField Row Col
385 | PTupleExpr Pattern Row Col
386 | PTupleSpace Space Row Col
388 | PTupleIndentEnd Row Col
389 | PTupleIndentExpr1 Row Col
390 | PTupleIndentExprN Row Col
396 | PListExpr Pattern Row Col
397 | PListSpace Space Row Col
399 | PListIndentOpen Row Col
400 | PListIndentEnd Row Col
401 | PListIndentExpr Row Col
409 = TRecord TRecord Row Col
410 | TTuple TTuple Row Col
414 | TSpace Space Row Col
416 | TIndentStart Row Col
420 = TRecordOpen Row Col
423 | TRecordField Row Col
424 | TRecordColon Row Col
425 | TRecordType Type Row Col
427 | TRecordSpace Space Row Col
429 | TRecordIndentOpen Row Col
430 | TRecordIndentField Row Col
431 | TRecordIndentColon Row Col
432 | TRecordIndentType Row Col
433 | TRecordIndentEnd Row Col
439 | TTupleType Type Row Col
440 | TTupleSpace Space Row Col
442 | TTupleIndentType1 Row Col
443 | TTupleIndentTypeN Row Col
444 | TTupleIndentEnd Row Col
454 | CharNotString Word16
458 = StringEndless_Single
459 | StringEndless_Multi
460 | StringEscape Escape
465 | BadUnicodeFormat Word16
466 | BadUnicodeCode Word16
467 | BadUnicodeLength Word16 Int Int
474 | NumberNoLeadingZero
483 | EndlessMultiComment
490toReport :: Code.Source -> Error -> Report.Report
493 ModuleNameUnspecified name ->
495 region = toRegion 1 1
497 Report.Report "MODULE NAME MISSING" region [] $
500 "I need the module name to be declared at the top of this file, like this:"
501 , D.indent 4 $ D.fillSep $
502 [ D.cyan "module", D.fromName name, D.cyan "exposing", "(..)" ]
504 "Try adding that as the first line of your file!"
506 "It is best to replace (..) with an explicit list of types and\
507 \ functions you want to expose. When you know a value is only used\
508 \ within this module, you can refactor without worrying about uses\
509 \ elsewhere. Limiting exposed values can also speed up compilation\
510 \ because I can skip a bunch of work if I see that the exposed API\
514 ModuleNameMismatch expectedName (A.At region actualName) ->
515 Report.Report "MODULE NAME MISMATCH" region [ModuleName.toChars expectedName] $
516 Code.toSnippet source region Nothing
518 "It looks like this module name is out of sync:"
522 "I need it to match the file path, so I was expecting it to see `"
523 ++ ModuleName.toChars expectedName
524 ++ "` here. Make the following change, and you should be all set!"
526 D.dullyellow (D.fromName actualName) <> " -> " <> D.green (D.fromName expectedName)
528 "I require that module names correspond to file paths. This makes it much\
529 \ easier to explore unfamiliar codebases! So if you want to keep the current\
530 \ module name, try renaming the file instead."
534 UnexpectedPort region ->
535 Report.Report "UNEXPECTED PORTS" region [] $
536 Code.toSnippet source region Nothing
539 "You are declaring ports in a normal module."
543 ["Switch","this","to","say",D.cyan "port module","instead,"
544 ,"marking","that","this","module","contains","port","declarations."
547 "Ports are not a traditional FFI for calling JS functions directly. They need a different mindset! Read"
549 "to learn the syntax and how to use it effectively."
554 Report.Report "NO PORTS" region [] $
555 Code.toSnippet source region Nothing
558 "This module does not declare any ports, but it says it will:"
561 ["Switch","this","to",D.cyan "module"
562 ,"and","you","should","be","all","set!"
567 toParseErrorReport source modul
570toParseErrorReport :: Code.Source -> Module -> Report.Report
571toParseErrorReport source modul =
573 ModuleSpace space row col ->
574 toSpaceReport source space row col
576 ModuleEndOfFile row col ->
577 case Code.whatIsNext source row col of
578 Code.Keyword keyword ->
580 region = toKeywordRegion row col keyword
582 Report.Report "RESERVED WORD" region [] $
583 Code.toSnippet source region Nothing
586 "I got stuck on this reserved word:"
589 "The name `" ++ keyword ++ "` is reserved, so try using a different name?"
594 region = toKeywordRegion row col op
596 Report.Report "UNEXPECTED SYMBOL" region [] $
597 Code.toSnippet source region Nothing
600 "I ran into an unexpected symbol:"
603 "I was not expecting to see a " ++ op ++ " here. Try deleting it? Maybe\
604 \ I can give a better hint from there?"
607 Code.Close term bracket ->
609 region = toRegion row col
611 Report.Report ("UNEXPECTED " ++ map Char.toUpper term) region [] $
612 Code.toSnippet source region Nothing
615 "I ran into an unexpected " ++ term ++ ":"
618 "This " ++ bracket : " does not match up with an earlier open " ++ term ++ ". Try deleting it?"
623 region = toRegion row col
625 Report.Report "SYNTAX PROBLEM" region [] $
626 Code.toSnippet source region Nothing
632 "Whatever I am running into is confusing me a lot! Normally I can give fairly\
633 \ specific hints, but something is really tripping me up this time."
636 ModuleProblem row col ->
638 region = toRegion row col
640 Report.Report "UNFINISHED MODULE DECLARATION" region [] $
641 Code.toSnippet source region Nothing
644 "I am parsing an `module` declaration, but I got stuck here:"
648 "Here are some examples of valid `module` declarations:"
649 , D.indent 4 $ D.vcat $
650 [ D.fillSep [D.cyan "module","Main",D.cyan "exposing","(..)"]
651 , D.fillSep [D.cyan "module","Dict",D.cyan "exposing","(Dict, empty, get)"]
654 "I generally recommend using an explicit exposing list. I can skip compiling a bunch\
655 \ of files when the public interface of a module stays the same, so exposing fewer\
656 \ values can help improve compile times!"
660 ModuleName row col ->
662 region = toRegion row col
664 Report.Report "EXPECTING MODULE NAME" region [] $
665 Code.toSnippet source region Nothing
668 "I was parsing an `module` declaration until I got stuck here:"
672 "I was expecting to see the module name next, like in these examples:"
673 , D.indent 4 $ D.vcat $
674 [ D.fillSep [D.cyan "module","Dict",D.cyan "exposing","(..)"]
675 , D.fillSep [D.cyan "module","Maybe",D.cyan "exposing","(..)"]
676 , D.fillSep [D.cyan "module","Html.Attributes",D.cyan "exposing","(..)"]
677 , D.fillSep [D.cyan "module","Json.Decode",D.cyan "exposing","(..)"]
680 "Notice that the module names all start with capital letters. That is required!"
684 ModuleExposing exposing row col ->
685 toExposingReport source exposing row col
687 PortModuleProblem row col ->
689 region = toRegion row col
691 Report.Report "UNFINISHED PORT MODULE DECLARATION" region [] $
692 Code.toSnippet source region Nothing
695 "I am parsing an `port module` declaration, but I got stuck here:"
699 "Here are some examples of valid `port module` declarations:"
700 , D.indent 4 $ D.vcat $
701 [ D.fillSep [D.cyan "port",D.cyan "module","WebSockets",D.cyan "exposing","(send, listen, keepAlive)"]
702 , D.fillSep [D.cyan "port",D.cyan "module","Maps",D.cyan "exposing","(Location, goto)"]
704 , D.link "Note" "Read" "ports" "for more help."
708 PortModuleName row col ->
710 region = toRegion row col
712 Report.Report "EXPECTING MODULE NAME" region [] $
713 Code.toSnippet source region Nothing
716 "I was parsing an `module` declaration until I got stuck here:"
720 "I was expecting to see the module name next, like in these examples:"
721 , D.indent 4 $ D.vcat $
722 [ D.fillSep [D.cyan "port",D.cyan "module","WebSockets",D.cyan "exposing","(send, listen, keepAlive)"]
723 , D.fillSep [D.cyan "port",D.cyan "module","Maps",D.cyan "exposing","(Location, goto)"]
726 "Notice that the module names start with capital letters. That is required!"
730 PortModuleExposing exposing row col ->
731 toExposingReport source exposing row col
735 region = toRegion row col
737 Report.Report "BAD MODULE DECLARATION" region [] $
738 Code.toSnippet source region Nothing
741 "I cannot parse this module declaration:"
744 "This type of module is reserved for the @elm organization. It is used to\
745 \ define certain effects, avoiding building them into the compiler."
750 region = toRegion row col
752 toBadFirstLineReport keyword =
753 Report.Report "TOO MUCH INDENTATION" region [] $
754 Code.toSnippet source region Nothing
757 "This `" ++ keyword ++ "` should not have any spaces before it:"
760 "Delete the spaces before `" ++ keyword ++ "` until there are none left!"
764 case Code.whatIsNext source row col of
765 Code.Keyword "module" -> toBadFirstLineReport "module"
766 Code.Keyword "import" -> toBadFirstLineReport "import"
767 Code.Keyword "type" -> toBadFirstLineReport "type"
768 Code.Keyword "port" -> toBadFirstLineReport "port"
770 Report.Report "SYNTAX PROBLEM" region [] $
771 Code.toSnippet source region Nothing
778 "I am not sure what is going on, but I recommend starting an Elm\
779 \ file with the following lines:"
781 [ D.fillSep [D.cyan "import","Html"]
783 , D.fillSep [D.green "main","="]
784 , D.indent 2 $ D.fillSep [D.cyan "Html" <> ".text",D.dullyellow "\"Hello!\""]
787 "You should be able to copy those lines directly into your file. Check out\
788 \ some of the examples on https://elm-lang.org for more help getting started!"
790 "This can also happen when something is indented too much!"
794 ImportStart row col ->
795 toImportReport source row col
797 ImportName row col ->
799 region = toRegion row col
801 Report.Report "EXPECTING IMPORT NAME" region [] $
802 Code.toSnippet source region Nothing
805 "I was parsing an `import` until I got stuck here:"
809 "I was expecting to see a module name next, like in these examples:"
810 , D.indent 4 $ D.vcat $
811 [ D.fillSep [D.cyan "import","Dict"]
812 , D.fillSep [D.cyan "import","Maybe"]
813 , D.fillSep [D.cyan "import","Html.Attributes"]
814 , D.fillSep [D.cyan "import","Json.Decode"]
817 "Notice that the module names all start with capital letters. That is required!"
822 toImportReport source row col
824 ImportAlias row col ->
826 region = toRegion row col
828 Report.Report "EXECTING IMPORT ALIAS" region [] $
829 Code.toSnippet source region Nothing
832 "I was parsing an `import` until I got stuck here:"
836 "I was expecting to see an alias next, like in these examples:"
837 , D.indent 4 $ D.vcat $
838 [ D.fillSep [D.cyan "import","Html.Attributes",D.cyan "as","Attr"]
839 , D.fillSep [D.cyan "import","WebGL.Texture",D.cyan "as","Texture"]
840 , D.fillSep [D.cyan "import","Json.Decode",D.cyan "as","D"]
843 "Notice that the alias always starts with a capital letter. That is required!"
847 ImportExposing row col ->
848 toImportReport source row col
850 ImportExposingList exposing row col ->
851 toExposingReport source exposing row col
854 toImportReport source row col
856 ImportIndentName row col ->
857 toImportReport source row col
859 ImportIndentAlias row col ->
860 toImportReport source row col
862 ImportIndentExposingList row col ->
864 region = toRegion row col
866 Report.Report "UNFINISHED IMPORT" region [] $
867 Code.toSnippet source region Nothing
870 "I was parsing an `import` until I got stuck here:"
874 "I was expecting to see the list of exposed values next. For example, here\
875 \ are two ways to expose values from the `Html` module:"
876 , D.indent 4 $ D.vcat $
877 [ D.fillSep [D.cyan "import","Html",D.cyan "exposing","(..)"]
878 , D.fillSep [D.cyan "import","Html",D.cyan "exposing","(Html, div, text)"]
881 "I generally recommend the second style. It is more explicit, making it\
882 \ much easier to figure out where values are coming from in large projects!"
888 region = toRegion row col
890 Report.Report "BAD INFIX" region [] $
891 Code.toSnippet source region Nothing
894 "Something went wrong in this infix operator declaration:"
897 "This feature is used by the @elm organization to define the\
898 \ languages built-in operators."
901 Declarations decl _ _ ->
902 toDeclarationsReport source decl
909toImportReport :: Code.Source -> Row -> Col -> Report.Report
910toImportReport source row col =
912 region = toRegion row col
914 Report.Report "UNFINISHED IMPORT" region [] $
915 Code.toSnippet source region Nothing
918 "I am partway through parsing an import, but I got stuck here:"
922 "Here are some examples of valid `import` declarations:"
923 , D.indent 4 $ D.vcat $
924 [ D.fillSep [D.cyan "import","Html"]
925 , D.fillSep [D.cyan "import","Html",D.cyan "as","H"]
926 , D.fillSep [D.cyan "import","Html",D.cyan "as","H",D.cyan "exposing","(..)"]
927 , D.fillSep [D.cyan "import","Html",D.cyan "exposing","(Html, div, text)"]
930 "You are probably trying to import a different module, but try to make it look like one of these examples!"
939toExposingReport :: Code.Source -> Exposing -> Row -> Col -> Report.Report
940toExposingReport source exposing startRow startCol =
942 ExposingSpace space row col ->
943 toSpaceReport source space row col
945 ExposingStart row col ->
947 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
948 region = toRegion row col
950 Report.Report "PROBLEM IN EXPOSING" region [] $
951 Code.toSnippet source surroundings (Just region)
954 "I want to parse exposed values, but I am getting stuck here:"
958 ["Exposed","values","are","always","surrounded","by","parentheses."
959 ,"So","try","adding","a",D.green "(","here?"
961 , D.toSimpleNote "Here are some valid examples of `exposing` for reference:"
962 , D.indent 4 $ D.vcat $
963 [ D.fillSep [D.cyan "import","Html",D.cyan "exposing","(..)"]
964 , D.fillSep [D.cyan "import","Html",D.cyan "exposing","(Html, div, text)"]
967 "If you are getting tripped up, you can just expose everything for now. It should\
968 \ get easier to make an explicit exposing list as you see more examples in the wild."
972 ExposingValue row col ->
973 case Code.whatIsNext source row col of
974 Code.Keyword keyword ->
976 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
977 region = toKeywordRegion row col keyword
979 Report.Report "RESERVED WORD" region [] $
980 Code.toSnippet source surroundings (Just region)
983 "I got stuck on this reserved word:"
986 "It looks like you are trying to expose `" ++ keyword ++ "` but that is a reserved word. Is there a typo?"
991 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
992 region = toKeywordRegion row col op
994 Report.Report "UNEXPECTED SYMBOL" region [] $
995 Code.toSnippet source surroundings (Just region)
998 "I got stuck on this symbol:"
1002 "If you are trying to expose an operator, add parentheses around it like this:"
1003 , D.indent 4 $ D.dullyellow (D.fromChars op) <> " -> " <> D.green ("(" <> D.fromChars op <> ")")
1009 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1010 region = toRegion row col
1012 Report.Report "PROBLEM IN EXPOSING" region [] $
1013 Code.toSnippet source surroundings (Just region)
1016 "I got stuck while parsing these exposed values:"
1020 "I do not have an exact recommendation, so here are some valid examples\
1021 \ of `exposing` for reference:"
1022 , D.indent 4 $ D.vcat $
1023 [ D.fillSep [D.cyan "import","Html",D.cyan "exposing","(..)"]
1024 , D.fillSep [D.cyan "import","Basics",D.cyan "exposing","(Int, Float, Bool(..), (+), not, sqrt)"]
1027 "These examples show how to expose types, variants, operators, and functions. Everything\
1028 \ should be some permutation of these examples, just with different names."
1032 ExposingOperator row col ->
1034 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1035 region = toRegion row col
1037 Report.Report "PROBLEM IN EXPOSING" region [] $
1038 Code.toSnippet source surroundings (Just region)
1041 "I just saw an open parenthesis, so I was expecting an operator next:"
1044 ["It","is","possible","to","expose","operators,","so","I","was","expecting"
1045 ,"to","see","something","like",D.dullyellow "(+)","or",D.dullyellow "(|=)"
1046 ,"or",D.dullyellow "(||)","after","I","saw","that","open","parenthesis."
1050 ExposingOperatorReserved op row col ->
1052 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1053 region = toRegion row col
1055 Report.Report "RESERVED SYMBOL" region [] $
1056 Code.toSnippet source surroundings (Just region)
1059 "I cannot expose this as an operator:"
1062 BadDot -> D.reflow "Try getting rid of this entry? Maybe I can give you a better hint after that?"
1063 BadPipe -> D.fillSep ["Maybe","you","want",D.dullyellow "(||)","instead?"]
1064 BadArrow -> D.reflow "Try getting rid of this entry? Maybe I can give you a better hint after that?"
1065 BadEquals -> D.fillSep ["Maybe","you","want",D.dullyellow "(==)","instead?"]
1066 BadHasType -> D.fillSep ["Maybe","you","want",D.dullyellow "(::)","instead?"]
1069 ExposingOperatorRightParen row col ->
1071 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1072 region = toRegion row col
1074 Report.Report "PROBLEM IN EXPOSING" region [] $
1075 Code.toSnippet source surroundings (Just region)
1078 "It looks like you are exposing an operator, but I got stuck here:"
1081 ["I","was","expecting","to","see","the","closing","parenthesis","immediately"
1082 ,"after","the","operator.","Try","adding","a",D.green ")","right","here?"
1086 ExposingEnd row col ->
1088 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1089 region = toRegion row col
1091 Report.Report "UNFINISHED EXPOSING" region [] $
1092 Code.toSnippet source surroundings (Just region)
1095 "I was partway through parsing exposed values, but I got stuck here:"
1098 "Maybe there is a comma missing before this?"
1101 ExposingTypePrivacy row col ->
1103 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1104 region = toRegion row col
1106 Report.Report "PROBLEM EXPOSING CUSTOM TYPE VARIANTS" region [] $
1107 Code.toSnippet source surroundings (Just region)
1110 "It looks like you are trying to expose the variants of a custom type:"
1114 ["You","need","to","write","something","like"
1115 ,D.dullyellow "Status(..)","or",D.dullyellow "Entity(..)"
1116 ,"though.","It","is","all","or","nothing,","otherwise","`case`"
1117 ,"expressions","could","miss","a","variant","and","crash!"
1120 "It is often best to keep the variants hidden! If someone pattern matches on\
1121 \ the variants, it is a MAJOR change if any new variants are added. Suddenly\
1122 \ their `case` expressions do not cover all variants! So if you do not need\
1123 \ people to pattern match, keep the variants hidden and expose functions to\
1124 \ construct values of this type. This way you can add new variants as a MINOR change!"
1128 ExposingIndentEnd row col ->
1130 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1131 region = toRegion row col
1133 Report.Report "UNFINISHED EXPOSING" region [] $
1134 Code.toSnippet source surroundings (Just region)
1137 "I was partway through parsing exposed values, but I got stuck here:"
1141 ["I","was","expecting","a","closing","parenthesis."
1142 ,"Try","adding","a",D.green ")","right","here?"
1145 "I can get confused when there is not enough indentation, so if you already\
1146 \ have a closing parenthesis, it probably just needs some spaces in front of it."
1150 ExposingIndentValue row col ->
1152 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1153 region = toRegion row col
1155 Report.Report "UNFINISHED EXPOSING" region [] $
1156 Code.toSnippet source surroundings (Just region)
1159 "I was partway through parsing exposed values, but I got stuck here:"
1162 "I was expecting another value to expose."
1170toSpaceReport :: Code.Source -> Space -> Row -> Col -> Report.Report
1171toSpaceReport source space row col =
1175 region = toRegion row col
1177 Report.Report "NO TABS" region [] $
1178 Code.toSnippet source region Nothing
1181 "I ran into a tab, but tabs are not allowed in Elm files."
1184 "Replace the tab with spaces."
1187 EndlessMultiComment ->
1189 region = toWiderRegion row col 2
1191 Report.Report "ENDLESS COMMENT" region [] $
1192 Code.toSnippet source region Nothing
1195 "I cannot find the end of this multi-line comment:"
1198 [ D.reflow "Add a -} somewhere after this to end the comment."
1200 "Multi-line comments can be nested in Elm, so {- {- -} -} is a comment\
1201 \ that happens to contain another comment. Like parentheses and curly braces,\
1202 \ the start and end markers must always be balanced. Maybe that is the problem?"
1211toRegion :: Row -> Col -> A.Region
1214 pos = A.Position row col
1219toWiderRegion :: Row -> Col -> Word16 -> A.Region
1220toWiderRegion row col extra =
1222 (A.Position row col)
1223 (A.Position row (col + extra))
1226toKeywordRegion :: Row -> Col -> [Char.Char] -> A.Region
1227toKeywordRegion row col keyword =
1229 (A.Position row col)
1230 (A.Position row (col + fromIntegral (length keyword)))
1233toDeclarationsReport :: Code.Source -> Decl -> Report.Report
1234toDeclarationsReport source decl =
1236 DeclStart row col ->
1237 error "TODO DeclStart" row col
1239 DeclSpace space row col ->
1240 toSpaceReport source space row col
1242 Port port_ row col ->
1243 toPortReport source port_ row col
1245 DeclType declType row col ->
1246 toDeclTypeReport source declType row col
1248 DeclDef name declDef row col ->
1249 toDeclDefReport source name declDef row col
1251 DeclFreshLineStart row col ->
1252 error "TODO DeclFreshLineStart" row col
1254 DeclFreshLineAfterDocComment row col ->
1255 error "TODO DeclFreshLineAfterDocComment" row col
1262toPortReport :: Code.Source -> Port -> Row -> Col -> Report.Report
1263toPortReport source port_ startRow startCol =
1265 PortSpace space row col ->
1266 toSpaceReport source space row col
1269 case Code.whatIsNext source row col of
1270 Code.Keyword keyword ->
1272 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1273 region = toKeywordRegion row col keyword
1275 Report.Report "RESERVED WORD" region [] $
1276 Code.toSnippet source surroundings (Just region)
1279 "I cannot handle ports with names like this:"
1282 "You are trying to make a port named `" ++ keyword
1283 ++ "` but that is a reserved word. Try using some other name?"
1288 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1289 region = toRegion row col
1291 Report.Report "PORT PROBLEM" region [] $
1292 Code.toSnippet source surroundings (Just region)
1295 "I just saw the start of a `port` declaration, but then I got stuck here:"
1299 ["I","was","expecting","to","see","a","name","like"
1300 ,D.dullyellow "send","or",D.dullyellow "receive","next."
1301 ,"Something","that","starts","with","a","lower-case","letter."
1307 PortColon row col ->
1309 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1310 region = toRegion row col
1312 Report.Report "PORT PROBLEM" region [] $
1313 Code.toSnippet source surroundings (Just region)
1316 "I just saw the start of a `port` declaration, but then I got stuck here:"
1320 "I was expecting to see a colon next. And then a type that tells me\
1321 \ what type of values are going to flow through."
1326 PortType tipe row col ->
1327 toTypeReport source tipe row col
1329 PortIndentName row col ->
1331 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1332 region = toRegion row col
1334 Report.Report "UNFINISHED PORT" region [] $
1335 Code.toSnippet source surroundings (Just region)
1338 "I just saw the start of a `port` declaration, but then I got stuck here:"
1342 ["I","was","expecting","to","see","a","name","like"
1343 ,D.dullyellow "send","or",D.dullyellow "receive","next."
1344 ,"Something","that","starts","with","a","lower-case","letter."
1350 PortIndentColon row col ->
1352 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1353 region = toRegion row col
1355 Report.Report "UNFINISHED PORT" region [] $
1356 Code.toSnippet source surroundings (Just region)
1359 "I just saw the start of a `port` declaration, but then I got stuck here:"
1363 "I was expecting to see a colon next. And then a type that tells me\
1364 \ what type of values are going to flow through."
1369 PortIndentType row col ->
1371 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1372 region = toRegion row col
1374 Report.Report "UNFINISHED PORT" region [] $
1375 Code.toSnippet source surroundings (Just region)
1378 "I just saw the start of a `port` declaration, but then I got stuck here:"
1382 "I was expecting to see a type next. Here are examples of outgoing and\
1383 \ incoming ports for reference:"
1385 [ D.fillSep [D.cyan "port","send",":","String -> Cmd msg"]
1386 , D.fillSep [D.cyan "port","receive",":","(String -> msg) -> Sub msg"]
1389 "The first line defines a `send` port so you can send strings out to JavaScript.\
1390 \ Maybe you send them on a WebSocket or put them into IndexedDB. The second line\
1391 \ defines a `receive` port so you can receive strings from JavaScript. Maybe you\
1392 \ get receive messages when new WebSocket messages come in or when an entry in\
1393 \ IndexedDB changes for some external reason."
1402 "Here are some example `port` declarations for reference:"
1404 [ D.fillSep [D.cyan "port","send",":","String -> Cmd msg"]
1405 , D.fillSep [D.cyan "port","receive",":","(String -> msg) -> Sub msg"]
1408 "The first line defines a `send` port so you can send strings out to JavaScript.\
1409 \ Maybe you send them on a WebSocket or put them into IndexedDB. The second line\
1410 \ defines a `receive` port so you can receive strings from JavaScript. Maybe you\
1411 \ get receive messages when new WebSocket messages come in or when the IndexedDB\
1412 \ is changed for some external reason."
1420toDeclTypeReport :: Code.Source -> DeclType -> Row -> Col -> Report.Report
1421toDeclTypeReport source declType startRow startCol =
1423 DT_Space space row col ->
1424 toSpaceReport source space row col
1428 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1429 region = toRegion row col
1431 Report.Report "EXPECTING TYPE NAME" region [] $
1432 Code.toSnippet source surroundings (Just region)
1435 "I think I am parsing a type declaration, but I got stuck here:"
1439 ["I","was","expecting","a","name","like",D.dullyellow "Status","or",D.dullyellow "Style"
1440 ,"next.","Just","make","sure","it","is","a","name","that","starts","with","a","capital","letter!"
1446 DT_Alias typeAlias row col ->
1447 toTypeAliasReport source typeAlias row col
1449 DT_Union customType row col ->
1450 toCustomTypeReport source customType row col
1452 DT_IndentName row col ->
1454 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1455 region = toRegion row col
1457 Report.Report "EXPECTING TYPE NAME" region [] $
1458 Code.toSnippet source surroundings (Just region)
1461 "I think I am parsing a type declaration, but I got stuck here:"
1465 ["I","was","expecting","a","name","like",D.dullyellow "Status","or",D.dullyellow "Style"
1466 ,"next.","Just","make","sure","it","is","a","name","that","starts","with","a","capital","letter!"
1473toTypeAliasReport :: Code.Source -> TypeAlias -> Row -> Col -> Report.Report
1474toTypeAliasReport source typeAlias startRow startCol =
1476 AliasSpace space row col ->
1477 toSpaceReport source space row col
1479 AliasName row col ->
1481 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1482 region = toRegion row col
1484 Report.Report "EXPECTING TYPE ALIAS NAME" region [] $
1485 Code.toSnippet source surroundings (Just region)
1488 "I am partway through parsing a type alias, but I got stuck here:"
1492 ["I","was","expecting","a","name","like",D.dullyellow "Person","or",D.dullyellow "Point"
1493 ,"next.","Just","make","sure","it","is","a","name","that","starts","with","a","capital","letter!"
1499 AliasEquals row col ->
1500 case Code.whatIsNext source row col of
1501 Code.Keyword keyword ->
1503 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1504 region = toKeywordRegion row col keyword
1506 Report.Report "RESERVED WORD" region [] $
1507 Code.toSnippet source surroundings (Just region)
1510 "I ran into a reserved word unexpectedly while parsing this type alias:"
1514 "It looks like you are trying use `" ++ keyword
1515 ++ "` as a type variable, but it is a reserved word. Try using a different name?"
1522 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1523 region = toRegion row col
1525 Report.Report "PROBLEM IN TYPE ALIAS" region [] $
1526 Code.toSnippet source surroundings (Just region)
1529 "I am partway through parsing a type alias, but I got stuck here:"
1533 "I was expecting to see a type variable or an an equals sign next."
1538 AliasBody tipe row col ->
1539 toTypeReport source tipe row col
1541 AliasIndentEquals row col ->
1543 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1544 region = toRegion row col
1546 Report.Report "UNFINISHED TYPE ALIAS" region [] $
1547 Code.toSnippet source surroundings (Just region)
1550 "I am partway through parsing a type alias, but I got stuck here:"
1554 "I was expecting to see a type variable or an an equals sign next."
1559 AliasIndentBody row col ->
1561 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1562 region = toRegion row col
1564 Report.Report "UNFINISHED TYPE ALIAS" region [] $
1565 Code.toSnippet source surroundings (Just region)
1568 "I am partway through parsing a type alias, but I got stuck here:"
1572 ["I","was","expecting","to","see","a","type","next.","Something","as","simple"
1573 ,"as",D.dullyellow "Int","or",D.dullyellow "Float","would","work!"
1580typeAliasNote :: D.Doc
1584 "Here is an example of a valid `type alias` for reference:"
1586 [ D.indent 0 $ D.fillSep [D.cyan "type",D.cyan "alias",D.green "Person","="]
1587 , D.indent 2 $ D.vcat $
1595 "This would let us use `Person` as a shorthand for that record type. Using this\
1596 \ shorthand makes type annotations much easier to read, and makes changing code\
1597 \ easier if you decide later that there is more to a person than age and height!"
1601toCustomTypeReport :: Code.Source -> CustomType -> Row -> Col -> Report.Report
1602toCustomTypeReport source customType startRow startCol =
1604 CT_Space space row col ->
1605 toSpaceReport source space row col
1609 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1610 region = toRegion row col
1612 Report.Report "EXPECTING TYPE NAME" region [] $
1613 Code.toSnippet source surroundings (Just region)
1616 "I think I am parsing a type declaration, but I got stuck here:"
1620 ["I","was","expecting","a","name","like",D.dullyellow "Status","or",D.dullyellow "Style"
1621 ,"next.","Just","make","sure","it","is","a","name","that","starts","with","a","capital","letter!"
1627 CT_Equals row col ->
1628 case Code.whatIsNext source row col of
1629 Code.Keyword keyword ->
1631 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1632 region = toKeywordRegion row col keyword
1634 Report.Report "RESERVED WORD" region [] $
1635 Code.toSnippet source surroundings (Just region)
1638 "I ran into a reserved word unexpectedly while parsing this custom type:"
1642 "It looks like you are trying use `" ++ keyword
1643 ++ "` as a type variable, but it is a reserved word. Try using a different name?"
1650 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1651 region = toRegion row col
1653 Report.Report "PROBLEM IN CUSTOM TYPE" region [] $
1654 Code.toSnippet source surroundings (Just region)
1657 "I am partway through parsing a custom type, but I got stuck here:"
1661 "I was expecting to see a type variable or an an equals sign next."
1668 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1669 region = toRegion row col
1671 Report.Report "PROBLEM IN CUSTOM TYPE" region [] $
1672 Code.toSnippet source surroundings (Just region)
1675 "I am partway through parsing a custom type, but I got stuck here:"
1679 "I was expecting to see a vertical bar like | next."
1684 CT_Variant row col ->
1686 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1687 region = toRegion row col
1689 Report.Report "PROBLEM IN CUSTOM TYPE" region [] $
1690 Code.toSnippet source surroundings (Just region)
1693 "I am partway through parsing a custom type, but I got stuck here:"
1697 ["I","was","expecting","to","see","a","variant","name","next."
1698 ,"Something","like",D.dullyellow "Success","or",D.dullyellow "Sandwich" <> "."
1699 ,"Any","name","that","starts","with","a","capital","letter","really!"
1705 CT_VariantArg tipe row col ->
1706 toTypeReport source tipe row col
1708 CT_IndentEquals row col ->
1710 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1711 region = toRegion row col
1713 Report.Report "UNFINISHED CUSTOM TYPE" region [] $
1714 Code.toSnippet source surroundings (Just region)
1717 "I am partway through parsing a custom type, but I got stuck here:"
1721 "I was expecting to see a type variable or an an equals sign next."
1726 CT_IndentBar row col ->
1728 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1729 region = toRegion row col
1731 Report.Report "UNFINISHED CUSTOM TYPE" region [] $
1732 Code.toSnippet source surroundings (Just region)
1735 "I am partway through parsing a custom type, but I got stuck here:"
1739 "I was expecting to see a vertical bar like | next."
1744 CT_IndentAfterBar row col ->
1746 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1747 region = toRegion row col
1749 Report.Report "UNFINISHED CUSTOM TYPE" region [] $
1750 Code.toSnippet source surroundings (Just region)
1753 "I am partway through parsing a custom type, but I got stuck here:"
1757 "I just saw a vertical bar, so I was expecting to see another variant defined next."
1762 CT_IndentAfterEquals row col ->
1764 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1765 region = toRegion row col
1767 Report.Report "UNFINISHED CUSTOM TYPE" region [] $
1768 Code.toSnippet source surroundings (Just region)
1771 "I am partway through parsing a custom type, but I got stuck here:"
1775 "I just saw an equals sign, so I was expecting to see the first variant defined next."
1781customTypeNote :: D.Doc
1785 "Here is an example of a valid `type` declaration for reference:"
1787 [ D.indent 0 $ D.fillSep [D.cyan "type",D.green "Status"]
1788 , D.indent 2 $ D.fillSep ["=","Failure"]
1789 , D.indent 2 $ D.fillSep ["|","Waiting"]
1790 , D.indent 2 $ D.fillSep ["|","Success","String"]
1793 "This defines a new `Status` type with three variants. This could be useful if\
1794 \ we are waiting for an HTTP request. Maybe we start with `Waiting` and then\
1795 \ switch to `Failure` or `Success \"message from server\"` depending on how\
1796 \ things go. Notice that the Success variant has some associated data, allowing\
1797 \ us to store a String if the request goes well!"
1805toDeclDefReport :: Code.Source -> Name.Name -> DeclDef -> Row -> Col -> Report.Report
1806toDeclDefReport source name declDef startRow startCol =
1808 DeclDefSpace space row col ->
1809 toSpaceReport source space row col
1811 DeclDefEquals row col ->
1812 case Code.whatIsNext source row col of
1813 Code.Keyword keyword ->
1815 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1816 region = toKeywordRegion row col keyword
1818 Report.Report "RESERVED WORD" region [] $
1819 Code.toSnippet source surroundings (Just region)
1822 "It looks like you are trying to use `" ++ keyword ++ "` as an argument:"
1825 "This is a reserved word! Try using some other name?"
1830 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1831 region = toKeywordRegion row col op
1833 Report.Report "UNEXPECTED SYMBOL" region [] $
1834 Code.toSnippet source surroundings (Just region)
1837 "I was not expecting to see this symbol here:"
1841 "I am not sure what is going wrong exactly, so here is a valid\
1842 \ definition (with an optional type annotation) for reference:"
1844 [ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
1845 , D.fillSep [D.green "add","x","y","="]
1846 , D.fillSep [" ","x","+","y"]
1849 "Try to use that format with your `" ++ Name.toChars name ++ "` definition!"
1855 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1856 region = toRegion row col
1858 Report.Report "PROBLEM IN DEFINITION" region [] $
1859 Code.toSnippet source surroundings (Just region)
1862 "I got stuck while parsing the `" ++ Name.toChars name ++ "` definition:"
1866 "I am not sure what is going wrong exactly, so here is a valid\
1867 \ definition (with an optional type annotation) for reference:"
1869 [ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
1870 , D.fillSep [D.green "add","x","y","="]
1871 , D.fillSep [" ","x","+","y"]
1874 "Try to use that format!"
1878 DeclDefType tipe row col ->
1879 toTypeReport source tipe row col
1881 DeclDefArg pattern row col ->
1882 toPatternReport source PArg pattern row col
1884 DeclDefBody expr row col ->
1885 toExprReport source (InDef name startRow startCol) expr row col
1887 DeclDefNameRepeat row col ->
1889 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1890 region = toRegion row col
1892 Report.Report "EXPECTING DEFINITION" region [] $
1893 Code.toSnippet source surroundings (Just region)
1896 "I just saw the type annotation for `" ++ Name.toChars name
1897 ++ "` so I was expecting to see its definition here:"
1901 "Type annotations always appear directly above the relevant\
1902 \ definition, without anything else (even doc comments) in between."
1907 DeclDefNameMatch defName row col ->
1909 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1910 region = toRegion row col
1912 Report.Report "NAME MISMATCH" region [] $
1913 Code.toSnippet source surroundings (Just region)
1916 "I just saw a type annotation for `" ++ Name.toChars name ++ "`, but it is followed by a definition for `" ++ Name.toChars defName ++ "`:"
1920 "These names do not match! Is there a typo?"
1921 , D.indent 4 $ D.fillSep $
1922 [D.dullyellow (D.fromName defName),"->",D.green (D.fromName name)]
1926 DeclDefIndentType row col ->
1928 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1929 region = toRegion row col
1931 Report.Report "UNFINISHED DEFINITION" region [] $
1932 Code.toSnippet source surroundings (Just region)
1935 "I got stuck while parsing the `" ++ Name.toChars name ++ "` type annotation:"
1939 "I just saw a colon, so I am expecting to see a type next."
1944 DeclDefIndentEquals row col ->
1946 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1947 region = toRegion row col
1949 Report.Report "UNFINISHED DEFINITION" region [] $
1950 Code.toSnippet source surroundings (Just region)
1953 "I got stuck while parsing the `" ++ Name.toChars name ++ "` definition:"
1957 "I was expecting to see an argument or an equals sign next."
1962 DeclDefIndentBody row col ->
1964 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1965 region = toRegion row col
1967 Report.Report "UNFINISHED DEFINITION" region [] $
1968 Code.toSnippet source surroundings (Just region)
1971 "I got stuck while parsing the `" ++ Name.toChars name ++ "` definition:"
1975 "I was expecting to see an expression next. What is it equal to?"
1985 "Here is a valid definition (with a type annotation) for reference:"
1987 [ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
1988 , D.fillSep [D.green "add","x","y","="]
1989 , D.fillSep [" ","x","+","y"]
1992 "The top line (called a \"type annotation\") is optional. You can leave it off\
1993 \ if you want. As you get more comfortable with Elm and as your project grows,\
1994 \ it becomes more and more valuable to add them though! They work great as\
1995 \ compiler-verified documentation, and they often improve error messages!"
2004 = InNode Node Row Col Context
2005 | InDef Name.Name Row Col
2021getDefName :: Context -> Name.Name
2024 InDef name _ _ -> name
2025 InNode _ _ _ c -> getDefName c
2028isWithin :: Node -> Context -> Bool
2029isWithin desiredNode context =
2031 InDef _ _ _ -> False
2032 InNode actualNode _ _ _ -> desiredNode == actualNode
2039toExprReport :: Code.Source -> Context -> Expr -> Row -> Col -> Report.Report
2040toExprReport source context expr startRow startCol =
2043 toLetReport source context let_ row col
2045 Case case_ row col ->
2046 toCaseReport source context case_ row col
2049 toIfReport source context if_ row col
2051 List list row col ->
2052 toListReport source context list row col
2054 Record record row col ->
2055 toRecordReport source context record row col
2057 Tuple tuple row col ->
2058 toTupleReport source context tuple row col
2060 Func func row col ->
2061 toFuncReport source context func row col
2064 let region = toRegion row col in
2065 Report.Report "EXPECTING RECORD ACCESSOR" region [] $
2066 Code.toSnippet source region Nothing
2069 "I was expecting to see a record accessor here:"
2072 ["Something","like",D.dullyellow".name","or",D.dullyellow".price"
2073 ,"that","accesses","a","value","from","a","record."
2078 let region = toRegion row col in
2079 Report.Report "EXPECTING RECORD ACCESSOR" region [] $
2080 Code.toSnippet source region Nothing
2083 "I am trying to parse a record accessor here:"
2088 ["Something","like",D.dullyellow".name","or",D.dullyellow".price"
2089 ,"that","accesses","a","value","from","a","record."
2093 "Record field names must start with a lower case letter!"
2097 OperatorRight op row col ->
2098 let region = toRegion row col in
2099 Report.Report "MISSING EXPRESSION" region [] $
2100 Code.toSnippet source region Nothing
2103 "I was expecting to see an expression after this " ++ Name.toChars op ++ " operator:"
2107 ["You","can","just","put","anything","for","now,","like"
2108 ,D.dullyellow "42","or",D.dullyellow"\"hello\"" <> "."
2109 ,"Once","there","is","something","there,","I","can","probably"
2110 ,"give","a","more","specific","hint!"
2113 "This can also happen if run into reserved words like `let` or `as` unexpectedly.\
2114 \ Or if I run into operators in unexpected spots. Point is, there are a\
2115 \ couple ways I can get confused and give sort of weird advice!"
2119 OperatorReserved operator row col ->
2120 toOperatorReport source context operator row col
2124 (contextRow, contextCol, aThing) =
2126 InDef name r c -> (r, c, "the `" ++ Name.toChars name ++ "` definition")
2127 InNode NRecord r c _ -> (r, c, "a record")
2128 InNode NParens r c _ -> (r, c, "some parentheses")
2129 InNode NList r c _ -> (r, c, "a list")
2130 InNode NFunc r c _ -> (r, c, "an anonymous function")
2131 InNode NCond r c _ -> (r, c, "an `if` expression")
2132 InNode NThen r c _ -> (r, c, "an `if` expression")
2133 InNode NElse r c _ -> (r, c, "an `if` expression")
2134 InNode NCase r c _ -> (r, c, "a `case` expression")
2135 InNode NBranch r c _ -> (r, c, "a `case` expression")
2136 -- TODO check if this is actually the best way to get error messages here
2138 surroundings = A.Region (A.Position contextRow contextCol) (A.Position row col)
2139 region = toRegion row col
2141 Report.Report "MISSING EXPRESSION" region [] $
2142 Code.toSnippet source surroundings (Just region)
2145 "I am partway through parsing " ++ aThing ++ ", but I got stuck here:"
2149 ["I","was","expecting","to","see","an","expression","like"
2150 ,D.dullyellow "42","or",D.dullyellow"\"hello\"" <> "."
2151 ,"Once","there","is","something","there,","I","can","probably"
2152 ,"give","a","more","specific","hint!"
2155 "This can also happen if run into reserved words like `let` or `as` unexpectedly.\
2156 \ Or if I run into operators in unexpected spots. Point is, there are a\
2157 \ couple ways I can get confused and give sort of weird advice!"
2161 Char char row col ->
2162 toCharReport source char row col
2164 String string row col ->
2165 toStringReport source string row col
2167 Number number row col ->
2168 toNumberReport source number row col
2170 Space space row col ->
2171 toSpaceReport source space row col
2173 EndlessShader row col ->
2175 region = toWiderRegion row col 6
2177 Report.Report "ENDLESS SHADER" region [] $
2178 Code.toSnippet source region Nothing
2180 D.reflow "I cannot find the end of this shader:"
2182 D.reflow "Add a |] somewhere after this to end the shader."
2185 ShaderProblem problem row col ->
2187 region = toRegion row col
2189 Report.Report "SHADER PROBLEM" region [] $
2190 Code.toSnippet source region Nothing
2193 "I ran into a problem while parsing this GLSL block."
2197 "I use a 3rd party GLSL parser for now, and I did my best to extract their error message:"
2198 , D.indent 4 $ D.vcat $
2199 map D.fromChars (filter (/="") (lines problem))
2203 IndentOperatorRight op row col ->
2205 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2206 region = toRegion row col
2208 Report.Report "MISSING EXPRESSION" region [] $
2209 Code.toSnippet source surroundings (Just region)
2212 "I was expecting to see an expression after this " ++ Name.toChars op ++ " operator:"
2217 ["You","can","just","put","anything","for","now,","like"
2218 ,D.dullyellow "42","or",D.dullyellow"\"hello\"" <> "."
2219 ,"Once","there","is","something","there,","I","can","probably"
2220 ,"give","a","more","specific","hint!"
2224 "I may be getting confused by your indentation? The easiest way to make sure\
2225 \ this is not an indentation problem is to put the expression on the right of\
2226 \ the " ++ Name.toChars op ++ " operator on the same line."
2230 IndentMoreExpr _ _ ->
2231 error "TODO IndentMoreExpr"
2238toCharReport :: Code.Source -> Char -> Row -> Col -> Report.Report
2239toCharReport source char row col =
2243 region = toRegion row col
2245 Report.Report "MISSING SINGLE QUOTE" region [] $
2246 Code.toSnippet source region Nothing
2249 "I thought I was parsing a character, but I got to the end of\
2250 \ the line without seeing the closing single quote:"
2253 "Add a closing single quote here!"
2256 CharEscape escape ->
2257 toEscapeReport source escape row col
2259 CharNotString width ->
2261 region = toWiderRegion row col width
2263 Report.Report "NEEDS DOUBLE QUOTES" region [] $
2264 Code.toSnippet source region Nothing
2266 "The following string uses single quotes:"
2269 [ "Please switch to double quotes instead:"
2271 D.dullyellow "'this'" <> " => " <> D.green "\"this\""
2273 "Elm uses double quotes for strings like \"hello\", whereas it uses single\
2274 \ quotes for individual characters like 'a' and 'ø'. This distinction helps with\
2275 \ code like (String.any (\\c -> c == 'X') \"90210\") where you are inspecting\
2276 \ individual characters."
2285toStringReport :: Code.Source -> String -> Row -> Col -> Report.Report
2286toStringReport source string row col =
2288 StringEndless_Single ->
2290 region = toRegion row col
2292 Report.Report "ENDLESS STRING" region [] $
2293 Code.toSnippet source region Nothing
2296 "I got to the end of the line without seeing the closing double quote:"
2300 ["Strings","look","like",D.green "\"this\"","with","double"
2301 ,"quotes","on","each","end.","Is","the","closing","double"
2302 ,"quote","missing","in","your","code?"
2304 , D.link "Note" "Read" "TODO" "if you want a string that spans multiple lines."
2308 StringEndless_Multi ->
2310 region = toWiderRegion row col 3
2312 Report.Report "ENDLESS STRING" region [] $
2313 Code.toSnippet source region Nothing
2316 "I cannot find the end of this multi-line string:"
2319 [ D.reflow "Add a \"\"\" somewhere after this to end the string."
2320 , D.link "Hint" "Read" "TODO" "for more information on strings and multi-line strings."
2324 StringEscape escape ->
2325 toEscapeReport source escape row col
2332toEscapeReport :: Code.Source -> Escape -> Row -> Col -> Report.Report
2333toEscapeReport source escape row col =
2337 region = toWiderRegion row col 2
2339 Report.Report "UNKNOWN ESCAPE" region [] $
2340 Code.toSnippet source region Nothing
2343 "Backslashes always start escaped characters, but I do not recognize this one:"
2347 "Valid escape characters include:"
2348 , D.dullyellow $ D.indent 4 $ D.vcat $
2358 "Do you want one of those instead? Maybe you need \\\\ to escape a backslash?"
2360 "The last style lets encode ANY character by its Unicode code\
2361 \ point. That means \\u{0009} and \\t are the same. You can use\
2362 \ that style for anything not covered by the other six escapes!"
2366 BadUnicodeFormat width ->
2368 region = toWiderRegion row col width
2370 Report.Report "BAD UNICODE ESCAPE" region [] $
2371 Code.toSnippet source region Nothing
2374 "I ran into an invalid Unicode escape:"
2378 "Here are some examples of valid Unicode escapes:"
2379 , D.dullyellow $ D.indent 4 $ D.vcat $
2386 "Notice that the code point is always surrounded by curly braces.\
2387 \ Maybe you are missing the opening or closing curly brace?"
2390 BadUnicodeCode width ->
2392 region = toWiderRegion row col width
2394 Report.Report "BAD UNICODE ESCAPE" region [] $
2395 Code.toSnippet source region Nothing
2398 "This is not a valid code point:"
2401 "The valid code points are between 0 and 10FFFF inclusive."
2404 BadUnicodeLength width numDigits badCode ->
2406 region = toWiderRegion row col width
2408 Report.Report "BAD UNICODE ESCAPE" region [] $
2409 Code.toSnippet source region Nothing $
2410 if numDigits < 4 then
2413 "Every code point needs at least four digits:"
2416 goodCode = replicate (4 - numDigits) '0' ++ map Char.toUpper (showHex badCode "")
2417 suggestion = "\\u{" <> D.fromChars goodCode <> "}"
2419 D.fillSep ["Try",D.green suggestion,"instead?"]
2425 "This code point has too many digits:"
2428 ["Valid","code","points","are","between"
2429 ,D.green "\\u{0000}","and",D.green "\\u{10FFFF}" <> ","
2430 ,"so","try","trimming","any","leading","zeros","until"
2431 ,"you","have","between","four","and","six","digits."
2440toNumberReport :: Code.Source -> Number -> Row -> Col -> Report.Report
2441toNumberReport source number row col =
2443 region = toRegion row col
2447 Report.Report "WEIRD NUMBER" region [] $
2448 Code.toSnippet source region Nothing
2451 "I thought I was reading a number, but I ran into some weird stuff here:"
2455 "I recognize numbers in the following formats:"
2456 , D.indent 4 $ D.vcat [ "42", "3.14", "6.022e23", "0x002B" ]
2458 "So is there a way to write it like one of those?"
2463 Report.Report "WEIRD NUMBER" region [] $
2464 Code.toSnippet source region Nothing
2467 "Numbers cannot end with a dot like this:"
2470 ["Switching","to",D.green (D.fromChars (show int))
2471 ,"or",D.green (D.fromChars (show int ++ ".0"))
2472 ,"will","work","though!"
2477 Report.Report "WEIRD HEXIDECIMAL" region [] $
2478 Code.toSnippet source region Nothing
2481 "I thought I was reading a hexidecimal number until I got here:"
2485 "Valid hexidecimal digits include 0123456789abcdefABCDEF, so I can\
2486 \ only recognize things like this:"
2487 , D.indent 4 $ D.vcat [ "0x2B", "0x002B", "0x00ffb3" ]
2491 NumberNoLeadingZero ->
2492 Report.Report "LEADING ZEROS" region [] $
2493 Code.toSnippet source region Nothing
2496 "I do not accept numbers with leading zeros:"
2500 "Just delete the leading zeros and it should work!"
2502 "Some languages let you to specify octal numbers by adding a leading zero.\
2503 \ So in C, writing 0111 is the same as writing 73. Some people are used to\
2504 \ that, but others probably want it to equal 111. Either path is going to\
2505 \ surprise people from certain backgrounds, so Elm tries to avoid this whole\
2515toOperatorReport :: Code.Source -> Context -> BadOperator -> Row -> Col -> Report.Report
2516toOperatorReport source context operator row col =
2520 region = toRegion row col
2522 Report.Report "UNEXPECTED SYMBOL" region [] $
2523 Code.toSnippet source region Nothing
2525 "I was not expecting this dot:"
2528 "Dots are for record access and decimal points, so\
2529 \ they cannot float around on their own. Maybe\
2530 \ there is some extra whitespace?"
2535 region = toRegion row col
2537 Report.Report "UNEXPECTED SYMBOL" region [] $
2538 Code.toSnippet source region Nothing
2541 "I was not expecting this vertical bar:"
2544 "Vertical bars should only appear in custom type declarations. Maybe you want || instead?"
2549 region = toWiderRegion row col 2
2551 Report.Report "UNEXPECTED ARROW" region [] $
2552 Code.toSnippet source region Nothing $
2553 if isWithin NBranch context then
2556 "I was not expecting to see an arrow here:"
2561 "I think I am parsing a `case` expression right now, so it makes sense to\
2562 \ see arrows around here. This one is confusing me though!"
2565 "I may be getting confused by the indentation. Every pattern in a `case` must be\
2566 \ exactly aligned (with exactly the same amount of indentation) so maybe this arrow\
2567 \ appears after the next `case` pattern (correctly!) but the pattern itself is\
2568 \ indented too far?"
2575 "I was not expecting an arrow here:"
2578 "Arrows should only appear in `case` expressions and anonymous functions. Maybe\
2579 \ you want > or >= instead?"
2584 region = toRegion row col
2585 name = getDefName context
2587 Report.Report "UNEXPECTED EQUALS" region [] $
2588 Code.toSnippet source region Nothing
2591 "I was not expecting to see this equals sign:"
2595 D.reflow "Maybe you want == instead? To check if two values are equal?"
2598 if isWithin NRecord context then
2599 "Records look like { x = 3, y = 4 } with the equals sign right\
2600 \ after the field name. So maybe you forgot a comma?"
2602 "I may be getting confused by your indentation. Is this supposed to be part of\
2603 \ a definition AFTER the `" ++ Name.toChars name ++ "` definition? If so,\
2604 \ the problem may be a bit before the equals sign. I need all definitions to\
2605 \ be exactly aligned (with exactly the same indentation) so the problem may be that\
2606 \ this new definition is indented a bit too much."
2612 region = toRegion row col
2613 name = getDefName context
2615 Report.Report "UNEXPECTED SYMBOL" region [] $
2616 Code.toSnippet source region Nothing $
2619 "I was not expecting to run into the \"has type\" symbol here:"
2624 ["Maybe","you","want",D.green "::","instead?"
2625 ,"To","put","something","on","the","front","of","a","list?"
2628 "The single colon is reserved for type annotations and record types, but I think\
2629 \ I am parsing the definition of `" ++ Name.toChars name ++ "` right now."
2632 "I may be getting confused by your indentation. Is this supposed to be part of\
2633 \ a type annotation AFTER the `" ++ Name.toChars name ++ "` definition? If so,\
2634 \ the problem may be a bit before the \"has type\" symbol. I need all definitions to\
2635 \ be exactly aligned (with exactly the same indentation) so the problem may be that\
2636 \ this new definition is indented a bit too much."
2645toLetReport :: Code.Source -> Context -> Let -> Row -> Col -> Report.Report
2646toLetReport source context let_ startRow startCol =
2648 LetSpace space row col ->
2649 toSpaceReport source space row col
2653 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2654 region = toRegion row col
2656 Report.Report "LET PROBLEM" region [] $
2657 Code.toSnippet source surroundings (Just region)
2660 "I was partway through parsing a `let` expression, but I got stuck here:"
2664 ["Based","on","the","indentation,","I","was","expecting","to","see","the",D.cyan "in"
2665 ,"keyword","next.","Is","there","a","typo?"
2668 "This can also happen if you are trying to define another value within the `let` but\
2669 \ it is not indented enough. Make sure each definition has exactly the same amount of\
2670 \ spaces before it. They should line up exactly!"
2674 LetDefAlignment _ row col ->
2676 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2677 region = toRegion row col
2679 Report.Report "LET PROBLEM" region [] $
2680 Code.toSnippet source surroundings (Just region)
2683 "I was partway through parsing a `let` expression, but I got stuck here:"
2687 ["Based","on","the","indentation,","I","was","expecting","to","see","the",D.cyan "in"
2688 ,"keyword","next.","Is","there","a","typo?"
2691 "This can also happen if you are trying to define another value within the `let` but\
2692 \ it is not indented enough. Make sure each definition has exactly the same amount of\
2693 \ spaces before it. The should line up exactly!"
2697 LetDefName row col ->
2698 case Code.whatIsNext source row col of
2699 Code.Keyword keyword ->
2701 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2702 region = toKeywordRegion row col keyword
2704 Report.Report "RESERVED WORD" region [] $
2705 Code.toSnippet source surroundings (Just region)
2708 "I was partway through parsing a `let` expression, but I got stuck here:"
2711 "It looks like you are trying to use `" ++ keyword ++ "` as a variable name, but\
2712 \ it is a reserved word! Try using a different name instead."
2716 toUnfinishLetReport source row col startRow startCol $
2718 "I was expecting the name of a definition next."
2720 LetDef name def row col ->
2721 error "TODO LetDef" name def row col
2723 LetDestruct destruct row col ->
2724 error "TODO LetDestruct" destruct row col
2726 LetBody expr row col ->
2727 toExprReport source context expr row col
2729 LetIndentDef row col ->
2730 toUnfinishLetReport source row col startRow startCol $
2732 "I was expecting a value to be defined here."
2734 LetIndentIn row col ->
2735 toUnfinishLetReport source row col startRow startCol $
2737 ["I","was","expecting","to","see","the",D.cyan "in","keyword","next."
2738 ,"Or","maybe","more","of","that","expression?"
2741 LetIndentBody row col ->
2742 toUnfinishLetReport source row col startRow startCol $
2744 "I was expecting an expression next. Tell me what should happen with the value you just defined!"
2747toUnfinishLetReport :: Code.Source -> Row -> Col -> Row -> Col -> D.Doc -> Report.Report
2748toUnfinishLetReport source row col startRow startCol message =
2750 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2751 region = toRegion row col
2753 Report.Report "UNFINISHED LET" region [] $
2754 Code.toSnippet source surroundings (Just region)
2757 "I was partway through parsing a `let` expression, but I got stuck here:"
2762 "Here is an example with a valid `let` expression for reference:"
2764 [ D.indent 0 $ D.fillSep [D.green "viewPerson","person","="]
2765 , D.indent 2 $ D.fillSep [D.cyan "let"]
2766 , D.indent 4 $ D.fillSep ["fullName","="]
2767 , D.indent 6 $ D.fillSep ["person.firstName","++",D.dullyellow "\" \"","++","person.lastName"]
2768 , D.indent 2 $ D.fillSep [D.cyan "in"]
2769 , D.indent 2 $ D.fillSep ["div","[]","[","text","fullName","]"]
2772 "Here we defined a `viewPerson` function that turns a person into some HTML. We use\
2773 \ a `let` expression to define the `fullName` we want to show. Notice the indentation! The\
2774 \ `fullName` is indented more than the `let` keyword, and the actual value of `fullName` is\
2775 \ indented a bit more than that. That is important!"
2784toCaseReport :: Code.Source -> Context -> Case -> Row -> Col -> Report.Report
2785toCaseReport source context case_ startRow startCol =
2787 CaseSpace space row col ->
2788 toSpaceReport source space row col
2791 toUnfinishCaseReport source row col startRow startCol $
2792 D.fillSep ["I","was","expecting","to","see","the",D.dullyellow "of","keyword","next."]
2794 CasePattern pattern row col ->
2795 toPatternReport source PCase pattern row col
2797 CaseArrow row col ->
2798 case Code.whatIsNext source row col of
2799 Code.Keyword keyword ->
2801 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2802 region = toKeywordRegion row col keyword
2804 Report.Report "RESERVED WORD" region [] $
2805 Code.toSnippet source surroundings (Just region)
2808 "I am partway through parsing a `case` expression, but I got stuck here:"
2811 "It looks like you are trying to use `" ++ keyword ++ "` in one of your\
2812 \ patterns, but it is a reserved word. Try using a different name?"
2815 Code.Operator ":" ->
2817 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2818 region = toRegion row col
2820 Report.Report "UNEXPECTED OPERATOR" region [] $
2821 Code.toSnippet source surroundings (Just region)
2824 "I am partway through parsing a `case` expression, but I got stuck here:"
2827 ["I","am","seeing",D.dullyellow ":","but","maybe","you","want",D.green "::","instead?"
2828 ,"For","pattern","matching","on","lists?"
2832 Code.Operator "=" ->
2834 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2835 region = toRegion row col
2837 Report.Report "UNEXPECTED OPERATOR" region [] $
2838 Code.toSnippet source surroundings (Just region)
2841 "I am partway through parsing a `case` expression, but I got stuck here:"
2844 ["I","am","seeing",D.dullyellow "=","but","maybe","you","want",D.green "->","instead?"
2850 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2851 region = toRegion row col
2853 Report.Report "MISSING ARROW" region [] $
2854 Code.toSnippet source surroundings (Just region)
2857 "I am partway through parsing a `case` expression, but I got stuck here:"
2859 addNoteForCaseIndentError $
2861 "I was expecting to see an arrow next."
2864 CaseExpr expr row col ->
2865 toExprReport source (InNode NCase startRow startCol context) expr row col
2867 CaseBranch expr row col ->
2868 toExprReport source (InNode NBranch startRow startCol context) expr row col
2870 CaseIndentOf row col ->
2871 toUnfinishCaseReport source row col startRow startCol $
2872 D.fillSep ["I","was","expecting","to","see","the",D.dullyellow "of","keyword","next."]
2874 CaseIndentExpr row col ->
2875 toUnfinishCaseReport source row col startRow startCol $
2876 D.reflow "I was expecting to see a expression next."
2878 CaseIndentPattern row col ->
2879 toUnfinishCaseReport source row col startRow startCol $
2880 D.reflow "I was expecting to see a pattern next."
2882 CaseIndentArrow row col ->
2883 toUnfinishCaseReport source row col startRow startCol $
2885 ["I","just","saw","a","pattern,","so","I","was","expecting"
2886 ,"to","see","a",D.dullyellow "->","next."
2889 CaseIndentBranch row col ->
2890 toUnfinishCaseReport source row col startRow startCol $
2892 "I was expecting to see an expression next. What should I do when\
2893 \ I run into this particular pattern?"
2895 CasePatternAlignment indent row col ->
2896 toUnfinishCaseReport source row col startRow startCol $
2898 "I suspect this is a pattern that is not indented far enough? (" ++ show indent ++ " spaces)"
2901toUnfinishCaseReport :: Code.Source -> Row -> Col -> Row -> Col -> D.Doc -> Report.Report
2902toUnfinishCaseReport source row col startRow startCol message =
2904 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2905 region = toRegion row col
2907 Report.Report "UNFINISHED CASE" region [] $
2908 Code.toSnippet source surroundings (Just region)
2911 "I was partway through parsing a `case` expression, but I got stuck here:"
2916 "Here is an example of a valid `case` expression for reference."
2918 [ D.indent 4 $ D.fillSep [D.cyan "case","maybeWidth",D.cyan "of"]
2919 , D.indent 6 $ D.fillSep [D.green "Just","width","->"]
2920 , D.indent 8 $ D.fillSep ["width","+",D.dullyellow "200"]
2922 , D.indent 6 $ D.fillSep [D.green "Nothing","->"]
2923 , D.indent 8 $ D.fillSep [D.dullyellow "400"]
2926 "Notice the indentation. Each pattern is aligned, and each branch is indented\
2927 \ a bit more than the corresponding pattern. That is important!"
2932addNoteForCaseIndentError :: D.Doc -> D.Doc
2933addNoteForCaseIndentError message =
2938 "Sometimes I get confused by indentation, so try to make your `case` look\
2939 \ something like this:"
2941 [ D.indent 4 $ D.fillSep [D.cyan "case","maybeWidth",D.cyan "of"]
2942 , D.indent 6 $ D.fillSep [D.green "Just","width","->"]
2943 , D.indent 8 $ D.fillSep ["width","+",D.dullyellow "200"]
2945 , D.indent 6 $ D.fillSep [D.green "Nothing","->"]
2946 , D.indent 8 $ D.fillSep [D.dullyellow "400"]
2949 "Notice the indentation! Each pattern is aligned, and each branch is indented\
2950 \ a bit more than the corresponding pattern. That is important!"
2958toIfReport :: Code.Source -> Context -> If -> Row -> Col -> Report.Report
2959toIfReport source context if_ startRow startCol =
2961 IfSpace space row col ->
2962 toSpaceReport source space row col
2966 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2967 region = toRegion row col
2969 Report.Report "UNFINISHED IF" region [] $
2970 Code.toSnippet source surroundings (Just region)
2973 "I was expecting to see more of this `if` expression, but I got stuck here:"
2976 ["I","was","expecting","to","see","the",D.cyan "then","keyword","next."
2982 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2983 region = toRegion row col
2985 Report.Report "UNFINISHED IF" region [] $
2986 Code.toSnippet source surroundings (Just region)
2989 "I was expecting to see more of this `if` expression, but I got stuck here:"
2992 ["I","was","expecting","to","see","the",D.cyan "else","keyword","next."
2996 IfElseBranchStart row col ->
2998 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2999 region = toRegion row col
3001 Report.Report "UNFINISHED IF" region [] $
3002 Code.toSnippet source surroundings (Just region)
3005 "I just saw the start of an `else` branch, but then I got stuck here:"
3008 "I was expecting to see an expression next. Maybe it is not filled in yet?"
3011 IfCondition expr row col ->
3012 toExprReport source (InNode NCond startRow startCol context) expr row col
3014 IfThenBranch expr row col ->
3015 toExprReport source (InNode NThen startRow startCol context) expr row col
3017 IfElseBranch expr row col ->
3018 toExprReport source (InNode NElse startRow startCol context) expr row col
3020 IfIndentCondition row col ->
3022 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3023 region = toRegion row col
3025 Report.Report "UNFINISHED IF" region [] $
3026 Code.toSnippet source surroundings (Just region)
3029 "I was expecting to see more of this `if` expression, but I got stuck here:"
3033 ["I","was","expecting","to","see","an","expression","like",D.dullyellow "x < 0"
3034 ,"that","evaluates","to","True","or","False."
3037 "I can be confused by indentation. Maybe something is not indented enough?"
3041 IfIndentThen row col ->
3043 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3044 region = toRegion row col
3046 Report.Report "UNFINISHED IF" region [] $
3047 Code.toSnippet source surroundings (Just region)
3050 "I was expecting to see more of this `if` expression, but I got stuck here:"
3054 ["I","was","expecting","to","see","the",D.cyan "then","keyword","next."
3057 "I can be confused by indentation. Maybe something is not indented enough?"
3061 IfIndentThenBranch row col ->
3063 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3064 region = toRegion row col
3066 Report.Report "UNFINISHED IF" region [] $
3067 Code.toSnippet source surroundings (Just region)
3070 "I got stuck after the start of this `then` branch:"
3074 "I was expecting to see an expression next. Maybe it is not filled in yet?"
3076 "I can be confused by indentation, so if the `then` branch is already\
3077 \ present, it may not be indented enough for me to recognize it."
3081 IfIndentElseBranch row col ->
3083 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3084 region = toRegion row col
3086 Report.Report "UNFINISHED IF" region [] $
3087 Code.toSnippet source surroundings (Just region)
3090 "I got stuck after the start of this `else` branch:"
3094 "I was expecting to see an expression next. Maybe it is not filled in yet?"
3096 "I can be confused by indentation, so if the `else` branch is already\
3097 \ present, it may not be indented enough for me to recognize it."
3101 IfIndentElse row col ->
3103 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3104 region = toRegion row col
3106 Report.Report "UNFINISHED IF" region [] $
3107 Code.toSnippet source surroundings (Just region)
3110 "I was expecting to see an `else` branch after this:"
3114 "I know what to do when the condition is `True`, but not when it is `False`."
3116 ["Add","an",D.cyan "else","branch","to","handle","that","scenario!"]
3125toRecordReport :: Code.Source -> Context -> Record -> Row -> Col -> Report.Report
3126toRecordReport source context record startRow startCol =
3128 RecordOpen row col ->
3129 case Code.whatIsNext source row col of
3130 Code.Keyword keyword ->
3132 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3133 region = toKeywordRegion row col keyword
3135 Report.Report "RESERVED WORD" region [] $
3136 Code.toSnippet source surroundings (Just region)
3139 "I just started parsing a record, but I got stuck on this field name:"
3142 "It looks like you are trying to use `" ++ keyword ++ "` as a field name, but \
3143 \ that is a reserved word. Try using a different name!"
3148 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3149 region = toRegion row col
3151 Report.Report "UNFINISHED RECORD" region [] $
3152 Code.toSnippet source surroundings (Just region)
3155 "I just started parsing a record, but I got stuck here:"
3158 ["Records","look","like",D.dullyellow "{ x = 3, y = 4 },"
3159 ,"so","I","was","expecting","to","see","a","field","name","next."
3163 RecordEnd row col ->
3165 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3166 region = toRegion row col
3168 Report.Report "UNFINISHED RECORD" region [] $
3169 Code.toSnippet source surroundings (Just region)
3172 "I am partway through parsing a record, but I got stuck here:"
3176 ["I","was","expecting","to","see","a","closing","curly","brace","before","this,"
3177 ,"so","try","adding","a",D.dullyellow "}","and","see","if","that","helps?"
3180 "When I get stuck like this, it usually means that there is a missing parenthesis\
3181 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
3185 RecordField row col ->
3186 case Code.whatIsNext source row col of
3187 Code.Keyword keyword ->
3189 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3190 region = toKeywordRegion row col keyword
3192 Report.Report "RESERVED WORD" region [] $
3193 Code.toSnippet source surroundings (Just region)
3196 "I am partway through parsing a record, but I got stuck on this field name:"
3199 "It looks like you are trying to use `" ++ keyword ++ "` as a field name, but \
3200 \ that is a reserved word. Try using a different name!"
3205 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3206 region = toRegion row col
3208 Report.Report "UNFINISHED RECORD" region [] $
3209 Code.toSnippet source surroundings (Just region)
3212 "I am partway through parsing a record, but I got stuck after that last comma:"
3214 addNoteForRecordError $
3216 "Trailing commas are not allowed in records, so I was expecting to see another\
3217 \ record field defined next. If you are done defining the record, the fix may\
3218 \ be to delete that last comma?"
3221 RecordEquals row col ->
3223 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3224 region = toRegion row col
3226 Report.Report "UNFINISHED RECORD" region [] $
3227 Code.toSnippet source surroundings (Just region)
3230 "I am partway through parsing a record, but I got stuck here:"
3232 addNoteForRecordError $
3234 ["I","just","saw","a","field","name,","so","I","was","expecting","to","see"
3235 ,"an","equals","sign","next.","So","try","putting","an",D.green "=","sign","here?"
3239 RecordExpr expr row col ->
3240 toExprReport source (InNode NRecord startRow startCol context) expr row col
3242 RecordSpace space row col ->
3243 toSpaceReport source space row col
3245 RecordIndentOpen row col ->
3247 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3248 region = toRegion row col
3250 Report.Report "UNFINISHED RECORD" region [] $
3251 Code.toSnippet source surroundings (Just region)
3254 "I just saw the opening curly brace of a record, but then I got stuck here:"
3256 addNoteForRecordIndentError $
3258 ["I","am","expecting","a","record","like",D.dullyellow "{ x = 3, y = 4 }","here."
3259 ,"Try","defining","some","fields","of","your","own?"
3263 RecordIndentEnd row col ->
3265 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3266 region = toRegion row col
3268 Report.Report "UNFINISHED RECORD" region [] $
3269 Code.toSnippet source surroundings (Just region)
3272 "I was expecting to see a closing curly brace next:"
3274 addNoteForRecordIndentError $
3276 ["Try","putting","an",D.green "}","and","see","if","that","helps?"
3280 RecordIndentField row col ->
3282 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3283 region = toRegion row col
3285 Report.Report "UNFINISHED RECORD" region [] $
3286 Code.toSnippet source surroundings (Just region)
3289 "I am partway through parsing a record, but I got stuck after that last comma:"
3291 addNoteForRecordError $
3293 "Trailing commas are not allowed in records, so the fix may be to\
3294 \ delete that last comma? Or maybe you were in the middle of defining\
3295 \ an additional field?"
3298 RecordIndentEquals row col ->
3300 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3301 region = toRegion row col
3303 Report.Report "UNFINISHED RECORD" region [] $
3304 Code.toSnippet source surroundings (Just region)
3307 "I am partway through parsing a record. I just saw a record\
3308 \ field, so I was expecting to see an equals sign next:"
3310 addNoteForRecordIndentError $
3312 ["Try","putting","an",D.green "=","followed","by","an","expression?"
3316 RecordIndentExpr row col ->
3318 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3319 region = toRegion row col
3321 Report.Report "UNFINISHED RECORD" region [] $
3322 Code.toSnippet source surroundings (Just region)
3325 "I am partway through parsing a record, and I was expecting to run into an expression next:"
3327 addNoteForRecordIndentError $
3329 ["Try","putting","something,","like"
3330 ,D.dullyellow "42","or",D.dullyellow"\"hello\"","for","now?"
3335addNoteForRecordError :: D.Doc -> D.Doc
3336addNoteForRecordError normalRecommendation =
3338 normalRecommendation
3341 "If you are trying to define a record across multiple lines, I recommend using this format:"
3342 , D.indent 4 $ D.vcat $
3343 [ "{ name = \"Alice\""
3349 "Notice that each line starts with some indentation. Usually two or four spaces. I\
3350 \ know this style can be jarring for people coming from C-like syntax, but folks generally\
3351 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
3355addNoteForRecordIndentError :: D.Doc -> D.Doc
3356addNoteForRecordIndentError normalRecommendation =
3358 normalRecommendation
3361 "I may be confused by indentation. For example, if you are trying to define\
3362 \ a record across multiple lines, I recommend using this format:"
3363 , D.indent 4 $ D.vcat $
3364 [ "{ name = \"Alice\""
3370 "Notice that each line starts with some indentation. Usually two or four spaces. I\
3371 \ know this style can be jarring for people coming from C-like syntax, but folks generally\
3372 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
3380toTupleReport :: Code.Source -> Context -> Tuple -> Row -> Col -> Report.Report
3381toTupleReport source context tuple startRow startCol =
3383 TupleExpr expr row col ->
3384 toExprReport source (InNode NParens startRow startCol context) expr row col
3386 TupleSpace space row col ->
3387 toSpaceReport source space row col
3391 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3392 region = toRegion row col
3394 Report.Report "UNFINISHED PARENTHESES" region [] $
3395 Code.toSnippet source surroundings (Just region)
3398 "I was expecting to see a closing parentheses next, but I got stuck here:"
3401 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps?"]
3403 "I can get stuck when I run into keywords, operators, parentheses, or brackets\
3404 \ unexpectedly. So there may be some earlier syntax trouble (like extra parenthesis\
3405 \ or missing brackets) that is confusing me."
3409 TupleOperatorClose row col ->
3411 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3412 region = toRegion row col
3414 Report.Report "UNFINISHED OPERATOR FUNCTION" region [] $
3415 Code.toSnippet source surroundings (Just region)
3417 D.reflow "I was expecting a closing parenthesis here:"
3420 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps!"]
3422 "I think I am parsing an operator function right now, so I am expecting to see\
3423 \ something like (+) or (&&) where an operator is surrounded by parentheses with\
3428 TupleOperatorReserved operator row col ->
3430 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3431 region = toRegion row col
3433 Report.Report "UNEXPECTED SYMBOL" region [] $
3434 Code.toSnippet source surroundings (Just region)
3437 "I ran into an unexpected symbol here:"
3441 BadDot -> ["Maybe","you","wanted","a","record","accessor","like",D.dullyellow ".x","or",D.dullyellow ".name","instead?"]
3442 BadPipe -> ["Try",D.dullyellow "(||)","instead?","To","turn","boolean","OR","into","a","function?"]
3443 BadArrow -> ["Maybe","you","wanted",D.dullyellow "(>)","or",D.dullyellow "(>=)","instead?"]
3444 BadEquals -> ["Try",D.dullyellow "(==)","instead?","To","make","a","function","that","checks","equality?"]
3445 BadHasType -> ["Try",D.dullyellow "(::)","instead?","To","add","values","to","the","front","of","lists?"]
3448 TupleIndentExpr1 row col ->
3450 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3451 region = toRegion row col
3453 Report.Report "UNFINISHED PARENTHESES" region [] $
3454 Code.toSnippet source surroundings (Just region)
3457 "I just saw an open parenthesis, so I was expecting to see an expression next."
3461 ["Something","like",D.dullyellow "(4 + 5)","or"
3462 ,D.dullyellow "(String.reverse \"desserts\")" <> "."
3463 ,"Anything","where","you","are","putting","parentheses","around","normal","expressions."
3466 "I can get confused by indentation in cases like this, so\
3467 \ maybe you have an expression but it is not indented enough?"
3471 TupleIndentExprN row col ->
3473 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3474 region = toRegion row col
3476 Report.Report "UNFINISHED TUPLE" region [] $
3477 Code.toSnippet source surroundings (Just region)
3480 "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."
3484 ["A","tuple","looks","like",D.dullyellow "(3,4)","or"
3485 ,D.dullyellow "(\"Tom\",42)" <> ","
3486 ,"so","I","think","there","is","an","expression","missing","here?"
3489 "I can get confused by indentation in cases like this, so\
3490 \ maybe you have an expression but it is not indented enough?"
3494 TupleIndentEnd row col ->
3496 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3497 region = toRegion row col
3499 Report.Report "UNFINISHED PARENTHESES" region [] $
3500 Code.toSnippet source surroundings (Just region)
3503 "I was expecting to see a closing parenthesis next:"
3506 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps!"]
3508 "I can get confused by indentation in cases like this, so\
3509 \ maybe you have a closing parenthesis but it is not indented enough?"
3514toListReport :: Code.Source -> Context -> List -> Row -> Col -> Report.Report
3515toListReport source context list startRow startCol =
3517 ListSpace space row col ->
3518 toSpaceReport source space row col
3522 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3523 region = toRegion row col
3525 Report.Report "UNFINISHED LIST" region [] $
3526 Code.toSnippet source surroundings (Just region)
3529 "I am partway through parsing a list, but I got stuck here:"
3533 ["I","was","expecting","to","see","a","closing","square","bracket","before","this,"
3534 ,"so","try","adding","a",D.dullyellow "]","and","see","if","that","helps?"
3537 "When I get stuck like this, it usually means that there is a missing parenthesis\
3538 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
3542 ListExpr expr row col ->
3546 surroundings = A.Region (A.Position startRow startCol) (A.Position r c)
3547 region = toRegion r c
3549 Report.Report "UNFINISHED LIST" region [] $
3550 Code.toSnippet source surroundings (Just region)
3553 "I was expecting to see another list entry after that last comma:"
3557 "Trailing commas are not allowed in lists, so the fix may be to delete the comma?"
3559 "I recommend using the following format for lists that span multiple lines:"
3560 , D.indent 4 $ D.vcat $
3567 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
3568 \ This style can be jarring for people coming from C-like syntax, but folks generally\
3569 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
3574 toExprReport source (InNode NList startRow startCol context) expr row col
3578 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3579 region = toRegion row col
3581 Report.Report "UNFINISHED LIST" region [] $
3582 Code.toSnippet source surroundings (Just region)
3585 "I am partway through parsing a list, but I got stuck here:"
3589 ["I","was","expecting","to","see","a","closing","square","bracket","before","this,"
3590 ,"so","try","adding","a",D.dullyellow "]","and","see","if","that","helps?"
3593 "When I get stuck like this, it usually means that there is a missing parenthesis\
3594 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
3598 ListIndentOpen row col ->
3600 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3601 region = toRegion row col
3603 Report.Report "UNFINISHED LIST" region [] $
3604 Code.toSnippet source surroundings (Just region)
3607 "I cannot find the end of this list:"
3611 ["You","could","change","it","to","something","like"
3612 ,D.dullyellow "[3,4,5]"
3614 ,D.dullyellow "[]" <> "."
3615 ,"Anything","where","there","is","an","open","and","close","square","brace,"
3616 ,"and","where","the","elements","of","the","list","are","separated","by","commas."
3619 "I may be confused by indentation. For example, if you are trying to define\
3620 \ a list across multiple lines, I recommend using this format:"
3621 , D.indent 4 $ D.vcat $
3628 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
3629 \ This style can be jarring for people coming from C-like syntax, but folks generally\
3630 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
3634 ListIndentEnd row col ->
3636 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3637 region = toRegion row col
3639 Report.Report "UNFINISHED LIST" region [] $
3640 Code.toSnippet source surroundings (Just region)
3643 "I cannot find the end of this list:"
3647 ["You","can","just","add","a","closing",D.dullyellow "]"
3648 ,"right","here,","and","I","will","be","all","set!"
3651 "I may be confused by indentation. For example, if you are trying to define\
3652 \ a list across multiple lines, I recommend using this format:"
3653 , D.indent 4 $ D.vcat $
3660 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
3661 \ This style can be jarring for people coming from C-like syntax, but folks generally\
3662 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
3666 ListIndentExpr row col ->
3668 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3669 region = toRegion row col
3671 Report.Report "UNFINISHED LIST" region [] $
3672 Code.toSnippet source surroundings (Just region)
3675 "I was expecting to see another list entry after this comma:"
3679 "Trailing commas are not allowed in lists, so the fix may be to delete the comma?"
3681 "I recommend using the following format for lists that span multiple lines:"
3682 , D.indent 4 $ D.vcat $
3689 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
3690 \ This style can be jarring for people coming from C-like syntax, but folks generally\
3691 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
3696toFuncReport :: Code.Source -> Context -> Func -> Row -> Col -> Report.Report
3697toFuncReport source context func startRow startCol =
3699 FuncSpace space row col ->
3700 toSpaceReport source space row col
3702 FuncArg pattern row col ->
3703 toPatternReport source PArg pattern row col
3705 FuncBody expr row col ->
3706 toExprReport source (InNode NFunc startRow startCol context) expr row col
3708 FuncArrow row col ->
3709 case Code.whatIsNext source row col of
3710 Code.Keyword keyword ->
3712 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3713 region = toKeywordRegion row col keyword
3715 Report.Report "RESERVED WORD" region [] $
3716 Code.toSnippet source surroundings (Just region)
3719 "I was parsing an anonymous function, but I got stuck here:"
3722 "It looks like you are trying to use `" ++ keyword ++ "` as an argument, but\
3723 \ it is a reserved word in this language. Try using a different argument name!"
3728 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3729 region = toRegion row col
3731 Report.Report "UNFINISHED ANONYMOUS FUNCTION" region [] $
3732 Code.toSnippet source surroundings (Just region)
3735 "I just saw the beginning of an anonymous function, so I was expecting to see an arrow next:"
3738 ["The","syntax","for","anonymous","functions","is"
3739 ,D.dullyellow "(\\x -> x + 1)"
3740 ,"so","I","am","missing","the","arrow","and","the","body","of","the","function."
3744 FuncIndentArg row col ->
3746 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3747 region = toRegion row col
3749 Report.Report "MISSING ARGUMENT" region [] $
3750 Code.toSnippet source surroundings (Just region)
3753 "I just saw the beginning of an anonymous function, so I was expecting to see an argument next:"
3757 ["Something","like",D.dullyellow"x","or",D.dullyellow "name" <> "."
3758 ,"Anything","that","starts","with","a","lower","case","letter!"
3761 "The syntax for anonymous functions is (\\x -> x + 1) where the backslash\
3762 \ is meant to look a bit like a lambda if you squint. This visual pun seemed\
3763 \ like a better idea at the time!"
3767 FuncIndentArrow row col ->
3769 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3770 region = toRegion row col
3772 Report.Report "UNFINISHED ANONYMOUS FUNCTION" region [] $
3773 Code.toSnippet source surroundings (Just region)
3776 "I just saw the beginning of an anonymous function, so I was expecting to see an arrow next:"
3780 ["The","syntax","for","anonymous","functions","is"
3781 ,D.dullyellow "(\\x -> x + 1)"
3782 ,"so","I","am","missing","the","arrow","and","the","body","of","the","function."
3785 "It is possible that I am confused about indetation! I generally recommend\
3786 \ switching to named functions if the definition cannot fit inline nicely, so\
3787 \ either (1) try to fit the whole anonymous function on one line or (2) break\
3788 \ the whole thing out into a named function. Things tend to be clearer that way!"
3792 FuncIndentBody row col ->
3794 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3795 region = toRegion row col
3797 Report.Report "UNFINISHED ANONYMOUS FUNCTION" region [] $
3798 Code.toSnippet source surroundings (Just region)
3801 "I was expecting to see the body of your anonymous function next:"
3805 ["The","syntax","for","anonymous","functions","is"
3806 ,D.dullyellow "(\\x -> x + 1)"
3807 ,"so","I","am","missing","all","the","stuff","after","the","arrow!"
3810 "It is possible that I am confused about indetation! I generally recommend\
3811 \ switching to named functions if the definition cannot fit inline nicely, so\
3812 \ either (1) try to fit the whole anonymous function on one line or (2) break\
3813 \ the whole thing out into a named function. Things tend to be clearer that way!"
3827toPatternReport :: Code.Source -> PContext -> Pattern -> Row -> Col -> Report.Report
3828toPatternReport source context pattern startRow startCol =
3830 PRecord record row col ->
3831 toPRecordReport source record row col
3833 PTuple tuple row col ->
3834 toPTupleReport source context tuple row col
3836 PList list row col ->
3837 toPListReport source context list row col
3840 case Code.whatIsNext source row col of
3841 Code.Keyword keyword ->
3843 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3844 region = toKeywordRegion row col keyword
3847 PArg -> "an argument"
3848 PCase -> "a pattern"
3850 Report.Report "RESERVED WORD" region [] $
3851 Code.toSnippet source surroundings (Just region)
3854 "It looks like you are trying to use `" ++ keyword ++ "` as " ++ aThing ++ ":"
3857 "This is a reserved word! Try using some other name?"
3863 PChar char row col ->
3864 toCharReport source char row col
3866 PString string row col ->
3867 toStringReport source string row col
3869 PNumber number row col ->
3870 toNumberReport source number row col
3872 PFloat width row col ->
3874 region = toWiderRegion row col width
3876 Report.Report "UNEXPECTED PATTERN" region [] $
3877 Code.toSnippet source region Nothing
3880 "I cannot pattern match with floating point numbers:"
3883 ["Equality","on","floats","can","be","unreliable,","so","you","usually","want"
3884 ,"to","check","that","they","are","nearby","with","some","sort","of"
3885 ,D.dullyellow "(abs (actual - expected) < 0.001)","check."
3891 region = toRegion row col
3893 Report.Report "UNFINISHED PATTERN" region [] $
3894 Code.toSnippet source region Nothing $
3897 "I was expecting to see a variable name after the `as` keyword:"
3901 ["The","`as`","keyword","lets","you","write","patterns","like"
3902 ,"((" <> D.dullyellow "x" <> "," <> D.dullyellow "y" <> ") " <> D.cyan "as" <> D.dullyellow " point" <> ")"
3903 ,"so","you","can","refer","to","individual","parts","of","the","tuple","with"
3904 ,D.dullyellow "x","and",D.dullyellow "y","or","you","refer","to","the","whole"
3905 ,"thing","with",D.dullyellow "point."
3908 "So I was expecting to see a variable name after the `as` keyword here. Sometimes\
3909 \ people just want to use `as` as a variable name though. Try using a different name\
3914 PWildcardNotVar name width row col ->
3916 region = toWiderRegion row col (fromIntegral width)
3918 case dropWhile (=='_') (Name.toChars name) of
3919 [] -> [D.dullyellow "x","or",D.dullyellow "age"]
3920 c:cs -> [D.dullyellow (D.fromChars (Char.toLower c : cs))]
3922 Report.Report "UNEXPECTED NAME" region [] $
3923 Code.toSnippet source region Nothing $
3926 "Variable names cannot start with underscores like this:"
3929 ["You","can","either","have","an","underscore","like",D.dullyellow "_","to"
3930 ,"ignore","the","value,","or","you","can","have","a","name","like"
3931 ] ++ examples ++ ["to","use","the","matched","value." ]
3934 PSpace space row col ->
3935 toSpaceReport source space row col
3937 PIndentStart row col ->
3938 error "TODO PIndentStart" row col
3940 PIndentAlias row col ->
3942 region = toRegion row col
3944 Report.Report "UNFINISHED PATTERN" region [] $
3945 Code.toSnippet source region Nothing $
3948 "I was expecting to see a variable name after the `as` keyword:"
3952 ["The","`as`","keyword","lets","you","write","patterns","like"
3953 ,"((" <> D.dullyellow "x" <> "," <> D.dullyellow "y" <> ") " <> D.cyan "as" <> D.dullyellow " point" <> ")"
3954 ,"so","you","can","refer","to","individual","parts","of","the","tuple","with"
3955 ,D.dullyellow "x","and",D.dullyellow "y","or","you","refer","to","the","whole"
3956 ,"thing","with",D.dullyellow "point."
3959 "So I was expecting to see a variable name after the `as` keyword here. Sometimes\
3960 \ people just want to use `as` as a variable name though. Try using a different name\
3966toPRecordReport :: Code.Source -> PRecord -> Row -> Col -> Report.Report
3967toPRecordReport source record startRow startCol =
3969 PRecordOpen row col ->
3970 toUnfinishRecordPatternReport source row col startRow startCol $
3971 D.reflow "I was expecting to see a field name next."
3973 PRecordEnd row col ->
3974 toUnfinishRecordPatternReport source row col startRow startCol $
3976 ["I","was","expecting","to","see","a","closing","curly","brace","next."
3977 ,"Try","adding","a",D.dullyellow "}","here?"
3980 PRecordField row col ->
3981 case Code.whatIsNext source row col of
3982 Code.Keyword keyword ->
3984 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3985 region = toKeywordRegion row col keyword
3987 Report.Report "RESERVED WORD" region [] $
3988 Code.toSnippet source surroundings (Just region)
3991 "I was not expecting to see `" ++ keyword ++ "` as a record field name:"
3994 "This is a reserved word, not available for variable names. Try another name!"
3998 toUnfinishRecordPatternReport source row col startRow startCol $
3999 D.reflow "I was expecting to see a field name next."
4001 PRecordSpace space row col ->
4002 toSpaceReport source space row col
4004 PRecordIndentOpen row col ->
4005 toUnfinishRecordPatternReport source row col startRow startCol $
4006 D.reflow "I was expecting to see a field name next."
4008 PRecordIndentEnd row col ->
4009 toUnfinishRecordPatternReport source row col startRow startCol $
4011 ["I","was","expecting","to","see","a","closing","curly","brace","next."
4012 ,"Try","adding","a",D.dullyellow "}","here?"
4015 PRecordIndentField row col ->
4016 toUnfinishRecordPatternReport source row col startRow startCol $
4017 D.reflow "I was expecting to see a field name next."
4020toUnfinishRecordPatternReport :: Code.Source -> Row -> Col -> Row -> Col -> D.Doc -> Report.Report
4021toUnfinishRecordPatternReport source row col startRow startCol message =
4023 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4024 region = toRegion row col
4026 Report.Report "UNFINISHED RECORD PATTERN" region [] $
4027 Code.toSnippet source surroundings (Just region)
4030 "I was partway through parsing a record pattern, but I got stuck here:"
4035 ["A","record","pattern","looks","like",D.dullyellow "{x,y}","or",D.dullyellow "{name,age}"
4036 ,"where","you","list","the","field","names","you","want","to","access."
4043toPTupleReport :: Code.Source -> PContext -> PTuple -> Row -> Col -> Report.Report
4044toPTupleReport source context tuple startRow startCol =
4046 PTupleOpen row col ->
4047 case Code.whatIsNext source row col of
4048 Code.Keyword keyword ->
4050 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4051 region = toKeywordRegion row col keyword
4053 Report.Report "RESERVED WORD" region [] $
4054 Code.toSnippet source surroundings (Just region)
4057 "It looks like you are trying to use `" ++ keyword ++ "` as a variable name:"
4060 "This is a reserved word! Try using some other name?"
4065 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4066 region = toRegion row col
4068 Report.Report "UNFINISHED PARENTHESES" region [] $
4069 Code.toSnippet source surroundings (Just region)
4072 "I just saw an open parenthesis, but I got stuck here:"
4075 ["I","was","expecting","so","see","a","pattern","next."
4076 ,"Maybe","it","will","end","up","being","something"
4077 ,"like",D.dullyellow "(x,y)","or",D.dullyellow "(name, _)" <> "?"
4081 PTupleEnd row col ->
4083 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4084 region = toRegion row col
4086 Report.Report "UNFINISHED PARENTHESES" region [] $
4087 Code.toSnippet source surroundings (Just region) $
4090 "I was expecting a closing parenthesis next:"
4092 D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps?"]
4095 PTupleExpr pattern row col ->
4096 toPatternReport source context pattern row col
4098 PTupleSpace space row col ->
4099 toSpaceReport source space row col
4101 PTupleIndentEnd row col ->
4103 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4104 region = toRegion row col
4106 Report.Report "UNFINISHED PARENTHESES" region [] $
4107 Code.toSnippet source surroundings (Just region) $
4110 "I was expecting a closing parenthesis next:"
4113 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps?"]
4115 "I can get confused by indentation in cases like this, so\
4116 \ maybe you have a closing parenthesis but it is not indented enough?"
4120 PTupleIndentExpr1 row col ->
4122 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4123 region = toRegion row col
4125 Report.Report "UNFINISHED PARENTHESES" region [] $
4126 Code.toSnippet source surroundings (Just region) $
4129 "I just saw an open parenthesis, but then I got stuck here:"
4132 ["I","was","expecting","so","see","a","pattern","next."
4133 ,"Maybe","it","will","end","up","being","something"
4134 ,"like",D.dullyellow "(x,y)","or",D.dullyellow "(name, _)" <> "?"
4138 PTupleIndentExprN row col ->
4140 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4141 region = toRegion row col
4143 Report.Report "UNFINISHED TUPLE PATTERN" region [] $
4144 Code.toSnippet source surroundings (Just region) $
4147 "I am partway through parsing a tuple pattern, but I got stuck here:"
4151 ["I","was","expecting","so","see","a","pattern","next."
4152 ,"I","am","expecting","the","final","result","to","be","something"
4153 ,"like",D.dullyellow "(x,y)","or",D.dullyellow "(name, _)" <> "."
4156 "I can get confused by indentation in cases like this, so the problem\
4157 \ may be that the next part is not indented enough?"
4162toPListReport :: Code.Source -> PContext -> PList -> Row -> Col -> Report.Report
4163toPListReport source context list startRow startCol =
4165 PListOpen row col ->
4166 case Code.whatIsNext source row col of
4167 Code.Keyword keyword ->
4169 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4170 region = toKeywordRegion row col keyword
4172 Report.Report "RESERVED WORD" region [] $
4173 Code.toSnippet source surroundings (Just region)
4176 "It looks like you are trying to use `" ++ keyword ++ "` to name an element of a list:"
4179 "This is a reserved word though! Try using some other name?"
4184 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4185 region = toRegion row col
4187 Report.Report "UNFINISHED LIST PATTERN" region [] $
4188 Code.toSnippet source surroundings (Just region) $
4191 "I just saw an open square bracket, but then I got stuck here:"
4193 D.fillSep ["Try","adding","a",D.dullyellow "]","to","see","if","that","helps?"]
4198 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4199 region = toRegion row col
4201 Report.Report "UNFINISHED LIST PATTERN" region [] $
4202 Code.toSnippet source surroundings (Just region) $
4205 "I was expecting a closing square bracket to end this list pattern:"
4207 D.fillSep ["Try","adding","a",D.dullyellow "]","to","see","if","that","helps?"]
4210 PListExpr pattern row col ->
4211 toPatternReport source context pattern row col
4213 PListSpace space row col ->
4214 toSpaceReport source space row col
4216 PListIndentOpen row col ->
4218 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4219 region = toRegion row col
4221 Report.Report "UNFINISHED LIST PATTERN" region [] $
4222 Code.toSnippet source surroundings (Just region) $
4225 "I just saw an open square bracket, but then I got stuck here:"
4228 [ D.fillSep ["Try","adding","a",D.dullyellow "]","to","see","if","that","helps?"]
4230 "I can get confused by indentation in cases like this, so\
4231 \ maybe there is something next, but it is not indented enough?"
4235 PListIndentEnd row col ->
4237 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4238 region = toRegion row col
4240 Report.Report "UNFINISHED LIST PATTERN" region [] $
4241 Code.toSnippet source surroundings (Just region) $
4244 "I was expecting a closing square bracket to end this list pattern:"
4247 [ D.fillSep ["Try","adding","a",D.dullyellow "]","to","see","if","that","helps?"]
4249 "I can get confused by indentation in cases like this, so\
4250 \ maybe you have a closing square bracket but it is not indented enough?"
4254 PListIndentExpr row col ->
4256 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4257 region = toRegion row col
4259 Report.Report "UNFINISHED LIST PATTERN" region [] $
4260 Code.toSnippet source surroundings (Just region) $
4263 "I am partway through parsing a list pattern, but I got stuck here:"
4267 "I was expecting to see another pattern next. Maybe a variable name."
4269 "I can get confused by indentation in cases like this, so\
4270 \ maybe there is more to this pattern but it is not indented enough?"
4279-- TODO add context? say something special if you are in type annotation vs custom type vs type alias?
4281toTypeReport :: Code.Source -> Type -> Row -> Col -> Report.Report
4282toTypeReport source tipe startRow startCol =
4284 TRecord record row col ->
4285 toTRecordReport source record row col
4287 TTuple tuple row col ->
4288 toTTupleReport source tuple row col
4291 error "TODO TArrow" row col
4294 error "TODO TStart" row col startRow startCol
4296 TSpace space row col ->
4297 toSpaceReport source space row col
4299 TIndentStart row col ->
4300 error "TODO TIndentStart" row col
4304toTRecordReport :: Code.Source -> TRecord -> Row -> Col -> Report.Report
4305toTRecordReport source record startRow startCol =
4307 TRecordOpen row col ->
4308 case Code.whatIsNext source row col of
4309 Code.Keyword keyword ->
4311 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4312 region = toKeywordRegion row col keyword
4314 Report.Report "RESERVED WORD" region [] $
4315 Code.toSnippet source surroundings (Just region)
4318 "I just started parsing a record type, but I got stuck on this field name:"
4321 "It looks like you are trying to use `" ++ keyword ++ "` as a field name, but \
4322 \ that is a reserved word. Try using a different name!"
4327 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4328 region = toRegion row col
4330 Report.Report "UNFINISHED RECORD TYPE" region [] $
4331 Code.toSnippet source surroundings (Just region)
4334 "I just started parsing a record type, but I got stuck here:"
4337 ["Record","types","look","like",D.dullyellow "{ name : String, age : Int },"
4338 ,"so","I","was","expecting","to","see","a","field","name","next."
4342 TRecordEnd row col ->
4344 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4345 region = toRegion row col
4347 Report.Report "UNFINISHED RECORD TYPE" region [] $
4348 Code.toSnippet source surroundings (Just region)
4351 "I am partway through parsing a record type, but I got stuck here:"
4355 ["I","was","expecting","to","see","a","closing","curly","brace","before","this,"
4356 ,"so","try","adding","a",D.dullyellow "}","and","see","if","that","helps?"
4359 "When I get stuck like this, it usually means that there is a missing parenthesis\
4360 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
4364 TRecordField row col ->
4365 case Code.whatIsNext source row col of
4366 Code.Keyword keyword ->
4368 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4369 region = toKeywordRegion row col keyword
4371 Report.Report "RESERVED WORD" region [] $
4372 Code.toSnippet source surroundings (Just region)
4375 "I am partway through parsing a record type, but I got stuck on this field name:"
4378 "It looks like you are trying to use `" ++ keyword ++ "` as a field name, but \
4379 \ that is a reserved word. Try using a different name!"
4384 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4385 region = toRegion row col
4387 Report.Report "UNFINISHED RECORD TYPE" region [] $
4388 Code.toSnippet source surroundings (Just region)
4391 "I am partway through parsing a record type, but I got stuck after that last comma:"
4393 addNoteForRecordTypeError $
4395 "Trailing commas are not allowed in records, so I was expecting to see another\
4396 \ record field defined next. If you are done defining the record, the fix may\
4397 \ be to delete that last comma?"
4400 TRecordColon row col ->
4402 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4403 region = toRegion row col
4405 Report.Report "UNFINISHED RECORD TYPE" region [] $
4406 Code.toSnippet source surroundings (Just region)
4409 "I am partway through parsing a record type, but I got stuck here:"
4411 addNoteForRecordTypeError $
4413 ["I","just","saw","a","field","name,","so","I","was","expecting","to","see"
4414 ,"a","colon","next.","So","try","putting","an",D.green ":","sign","here?"
4418 TRecordType tipe row col ->
4419 toTypeReport source tipe row col
4421 TRecordSpace space row col ->
4422 toSpaceReport source space row col
4424 TRecordIndentOpen row col ->
4426 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4427 region = toRegion row col
4429 Report.Report "UNFINISHED RECORD TYPE" region [] $
4430 Code.toSnippet source surroundings (Just region)
4433 "I just saw the opening curly brace of a record type, but then I got stuck here:"
4435 addNoteForRecordTypeIndentError $
4437 ["I","am","expecting","a","record","like",D.dullyellow "{ name : String, age : Int }","here."
4438 ,"Try","defining","some","fields","of","your","own?"
4442 TRecordIndentEnd row col ->
4444 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4445 region = toRegion row col
4447 Report.Report "UNFINISHED RECORD TYPE" region [] $
4448 Code.toSnippet source surroundings (Just region)
4451 "I was expecting to see a closing curly brace next:"
4453 addNoteForRecordTypeIndentError $
4455 ["Try","putting","an",D.green "}","and","see","if","that","helps?"
4459 TRecordIndentField row col ->
4461 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4462 region = toRegion row col
4464 Report.Report "UNFINISHED RECORD TYPE" region [] $
4465 Code.toSnippet source surroundings (Just region)
4468 "I am partway through parsing a record type, but I got stuck after that last comma:"
4470 addNoteForRecordTypeIndentError $
4472 "Trailing commas are not allowed in record types, so the fix may be to\
4473 \ delete that last comma? Or maybe you were in the middle of defining\
4474 \ an additional field?"
4477 TRecordIndentColon row col ->
4479 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4480 region = toRegion row col
4482 Report.Report "UNFINISHED RECORD TYPE" region [] $
4483 Code.toSnippet source surroundings (Just region)
4486 "I am partway through parsing a record type. I just saw a record\
4487 \ field, so I was expecting to see a colon next:"
4489 addNoteForRecordTypeIndentError $
4491 ["Try","putting","an",D.green ":","followed","by","a","type?"
4495 TRecordIndentType row col ->
4497 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4498 region = toRegion row col
4500 Report.Report "UNFINISHED RECORD TYPE" region [] $
4501 Code.toSnippet source surroundings (Just region)
4504 "I am partway through parsing a record type, and I was expecting to run into a type next:"
4506 addNoteForRecordTypeIndentError $
4508 ["Try","putting","something,","like"
4509 ,D.dullyellow "Int","or",D.dullyellow "String","for","now?"
4514addNoteForRecordTypeError :: D.Doc -> D.Doc
4515addNoteForRecordTypeError normalRecommendation =
4517 normalRecommendation
4520 "If you are trying to define a record type across multiple lines, I recommend using this format:"
4521 , D.indent 4 $ D.vcat $
4524 , ", height : Float"
4528 "Notice that each line starts with some indentation. Usually two or four spaces. I\
4529 \ know this style can be jarring for people coming from C-like syntax, but folks generally\
4530 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
4534addNoteForRecordTypeIndentError :: D.Doc -> D.Doc
4535addNoteForRecordTypeIndentError normalRecommendation =
4537 normalRecommendation
4540 "I may be confused by indentation. For example, if you are trying to define\
4541 \ a record type across multiple lines, I recommend using this format:"
4542 , D.indent 4 $ D.vcat $
4545 , ", height : Float"
4549 "Notice that each line starts with some indentation. Usually two or four spaces. I\
4550 \ know this style can be jarring for people coming from C-like syntax, but folks generally\
4551 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
4555toTTupleReport :: Code.Source -> TTuple -> Row -> Col -> Report.Report
4556toTTupleReport source tuple startRow startCol =
4558 TTupleOpen row col ->
4559 case Code.whatIsNext source row col of
4560 Code.Keyword keyword ->
4562 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4563 region = toKeywordRegion row col keyword
4565 Report.Report "RESERVED WORD" region [] $
4566 Code.toSnippet source surroundings (Just region)
4569 "I ran into a reserved word unexpectedly:"
4572 "It looks like you are trying to use `" ++ keyword ++ "` as a variable name, but \
4573 \ it is a reserved word. Try using a different name!"
4578 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4579 region = toRegion row col
4581 Report.Report "UNFINISHED PARENTHESES" region [] $
4582 Code.toSnippet source surroundings (Just region)
4585 "I just saw an open parenthesis, so I was expecting to see a type next."
4588 ["Something","like",D.dullyellow "(Maybe Int)","or"
4589 ,D.dullyellow "(List Person)" <> "."
4590 ,"Anything","where","you","are","putting","parentheses","around","normal","types."
4594 TTupleEnd row col ->
4596 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4597 region = toRegion row col
4599 Report.Report "UNFINISHED PARENTHESES" region [] $
4600 Code.toSnippet source surroundings (Just region)
4603 "I was expecting to see a closing parentheses next, but I got stuck here:"
4606 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps?"]
4608 "I can get stuck when I run into keywords, operators, parentheses, or brackets\
4609 \ unexpectedly. So there may be some earlier syntax trouble (like extra parenthesis\
4610 \ or missing brackets) that is confusing me."
4614 TTupleType tipe row col ->
4615 toTypeReport source tipe row col
4617 TTupleSpace space row col ->
4618 toSpaceReport source space row col
4620 TTupleIndentType1 row col ->
4622 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4623 region = toRegion row col
4625 Report.Report "UNFINISHED PARENTHESES" region [] $
4626 Code.toSnippet source surroundings (Just region)
4629 "I just saw an open parenthesis, so I was expecting to see a type next."
4633 ["Something","like",D.dullyellow "(Maybe Int)","or"
4634 ,D.dullyellow "(List Person)" <> "."
4635 ,"Anything","where","you","are","putting","parentheses","around","normal","types."
4638 "I can get confused by indentation in cases like this, so\
4639 \ maybe you have a type but it is not indented enough?"
4643 TTupleIndentTypeN row col ->
4645 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4646 region = toRegion row col
4648 Report.Report "UNFINISHED TUPLE TYPE" region [] $
4649 Code.toSnippet source surroundings (Just region)
4652 "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."
4656 ["A","tuple","type","looks","like",D.dullyellow "(Float,Float)","or"
4657 ,D.dullyellow "(String,Int)" <> ","
4658 ,"so","I","think","there","is","a","type","missing","here?"
4661 "I can get confused by indentation in cases like this, so\
4662 \ maybe you have an expression but it is not indented enough?"
4666 TTupleIndentEnd row col ->
4668 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4669 region = toRegion row col
4671 Report.Report "UNFINISHED PARENTHESES" region [] $
4672 Code.toSnippet source surroundings (Just region)
4675 "I was expecting to see a closing parenthesis next:"
4678 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps!"]
4680 "I can get confused by indentation in cases like this, so\
4681 \ 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