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 | ExposingEnd Row Col
120 | ExposingTypePrivacy Row Col
121 | ExposingTypePrivacyDots Row Col
122 | ExposingTypePrivacyEnd Row Col
124 | ExposingIndentEnd Row Col
125 | ExposingIndentValue Row Col
126 | ExposingIndentValueEnd Row Col
127 | ExposingIndentTypePrivacy Row Col
128 | ExposingIndentTypePrivacyDots Row Col
129 | ExposingIndentTypePrivacyEnd Row Col
138 | DeclSpace Space Row Col
141 | DeclType DeclType Row Col
142 | DeclDef Name.Name DeclDef Row Col
144 | DeclFreshLineStart Row Col
145 | DeclFreshLineAfterDocComment Row Col
149 = DeclDefSpace Space Row Col
150 | DeclDefEquals Row Col
151 | DeclDefType Type Row Col
152 | DeclDefArg Pattern Row Col
153 | DeclDefBody Expr Row Col
154 | DeclDefNameRepeat Row Col
155 | DeclDefNameMatch Name.Name Row Col
157 | DeclDefIndentType Row Col
158 | DeclDefIndentEquals Row Col
159 | DeclDefIndentBody Row Col
161 | DeclDefFreshLineAfterType Row Col
165 = PortSpace Space Row Col
168 | PortType Type Row Col
169 | PortIndentName Row Col
170 | PortIndentColon Row Col
171 | PortIndentType Row Col
179 = DT_Space Space Row Col
181 | DT_Alias TypeAlias Row Col
182 | DT_Union CustomType Row Col
184 | DT_IndentName Row Col
188 = AliasSpace Space Row Col
190 | AliasEquals Row Col
191 | AliasBody Type Row Col
193 | AliasIndentEquals Row Col
194 | AliasIndentBody Row Col
198 = CT_Space Space Row Col
203 | CT_VariantArg Type Row Col
205 | CT_IndentEquals Row Col
206 | CT_IndentBar Row Col
207 | CT_IndentAfterBar Row Col
208 | CT_IndentAfterEquals Row Col
220 | Record Record Row Col
221 | Tuple Tuple Row Col
226 | OperatorRight Name.Name Row Col
227 | OperatorReserved BadOperator Row Col
231 | String String Row Col
232 | Number Number Row Col
233 | Space Space Row Col
234 | EndlessShader Row Col
235 | ShaderProblem [Char.Char] Row Col
236 | IndentOperatorRight Name.Name Row Col
237 | IndentMoreExpr Row Col
243 | RecordField Row Col
244 | RecordEquals Row Col
245 | RecordExpr Expr Row Col
246 | RecordSpace Space Row Col
248 | RecordIndentOpen Row Col
249 | RecordIndentEnd Row Col
250 | RecordIndentField Row Col
251 | RecordIndentEquals Row Col
252 | RecordIndentExpr Row Col
256 = TupleExpr Expr Row Col
257 | TupleSpace Space Row Col
259 | TupleOperatorClose Row Col
260 | TupleOperatorReserved BadOperator Row Col
262 | TupleIndentExpr1 Row Col
263 | TupleIndentExprN Row Col
264 | TupleIndentEnd Row Col
268 = ListSpace Space Row Col
270 | ListExpr Expr Row Col
273 | ListIndentOpen Row Col
274 | ListIndentEnd Row Col
275 | ListIndentExpr Row Col
279 = FuncSpace Space Row Col
280 | FuncArg Pattern Row Col
281 | FuncBody Expr Row Col
284 | FuncIndentArg Row Col
285 | FuncIndentArrow Row Col
286 | FuncIndentBody Row Col
290 = CaseSpace Space Row Col
292 | CasePattern Pattern Row Col
294 | CaseExpr Expr Row Col
295 | CaseBranch Expr Row Col
297 | CaseIndentOf Row Col
298 | CaseIndentExpr Row Col
299 | CaseIndentPattern Row Col
300 | CaseIndentArrow Row Col
301 | CaseIndentBranch Row Col
302 | CasePatternAlignment Word16 Row Col
306 = IfSpace Space Row Col
309 | IfElseBranchStart Row Col
311 | IfCondition Expr Row Col
312 | IfThenBranch Expr Row Col
313 | IfElseBranch Expr Row Col
315 | IfIndentCondition Row Col
316 | IfIndentThen Row Col
317 | IfIndentThenBranch Row Col
318 | IfIndentElseBranch Row Col
319 | IfIndentElse Row Col
323 = LetSpace Space Row Col
325 | LetDefAlignment Word16 Row Col
327 | LetDef Name.Name Def Row Col
328 | LetDestruct Destruct Row Col
329 | LetBody Expr Row Col
330 | LetIndentDef Row Col
331 | LetIndentIn Row Col
332 | LetIndentBody Row Col
336 = DefSpace Space Row Col
337 | DefType Type Row Col
338 | DefNameRepeat Name.Name Row Col
339 | DefNameMatch Name.Name Name.Name Row Col
340 | DefArg Pattern Row Col
342 | DefBody Expr Row Col
343 | DefIndentEquals Row Col
344 | DefIndentType Row Col
345 | DefIndentBody Row Col
346 | DefAlignment Word16 Row Col
350 = DestructSpace Space Row Col
351 | DestructPattern Pattern Row Col
352 | DestructEquals Row Col
353 | DestructBody Expr Row Col
354 | DestructIndentEquals Row Col
355 | DestructIndentBody Row Col
363 = PRecord PRecord Row Col
364 | PTuple PTuple Row Col
365 | PList PList Row Col
369 | PString String Row Col
370 | PNumber Number Row Col
373 | PWildcardNotVar Int Row Col
374 | PSpace Space Row Col
376 | PIndentStart Row Col
377 | PIndentAlias Row Col
381 = PRecordOpen Row Col
383 | PRecordField Row Col
384 | PRecordSpace Space Row Col
386 | PRecordIndentOpen Row Col
387 | PRecordIndentEnd Row Col
388 | PRecordIndentField Row Col
394 | PTupleExpr Pattern Row Col
395 | PTupleSpace Space Row Col
397 | PTupleIndentOpen Row Col
398 | PTupleIndentEnd Row Col
399 | PTupleIndentExpr Row Col
405 | PListExpr Pattern Row Col
406 | PListSpace Space Row Col
408 | PListIndentOpen Row Col
409 | PListIndentEnd Row Col
410 | PListIndentExpr Row Col
418 = TRecord TRecord Row Col
419 | TTuple TTuple Row Col
424 | TSpace Space Row Col
426 | TIndentStart Row Col
430 = TRecordOpen Row Col
433 | TRecordField Row Col
434 | TRecordColon Row Col
435 | TRecordType Type Row Col
437 | TRecordSpace Space Row Col
439 | TRecordIndentOpen Row Col
440 | TRecordIndentField Row Col
441 | TRecordIndentColon Row Col
442 | TRecordIndentType Row Col
443 | TRecordIndentEnd Row Col
449 | TTupleType Type Row Col
450 | TTupleSpace Space Row Col
452 | TTupleIndentOpen Row Col
453 | TTupleIndentType Row Col
454 | TTupleIndentEnd Row Col
464 | CharNotString Word16
468 = StringEndless_Single
469 | StringEndless_Multi
470 | StringEscape Escape
475 | BadUnicodeFormat Word16
476 | BadUnicodeCode Word16
477 | BadUnicodeLength Word16 Int Int
484 | NumberNoLeadingZero
493 | EndlessMultiComment
500toReport :: Code.Source -> Error -> Report.Report
503 ModuleNameUnspecified name ->
505 region = toRegion 1 1
507 Report.Report "MODULE NAME MISSING" region [] $
510 "I need the module name to be declared at the top of this file, like this:"
511 , D.indent 4 $ D.green $ D.fromChars $
512 "module " ++ ModuleName.toChars name ++ " exposing (..)"
514 "Try adding that as the first line of your file!"
516 "It is best to replace (..) with an explicit list of types and\
517 \ functions you want to expose. When you know a value is only used\
518 \ within this module, you can refactor without worrying about uses\
519 \ elsewhere. Limiting exposed values can also speed up compilation\
520 \ because I can skip a bunch of work if I see that the exposed API\
524 ModuleNameMismatch expectedName (A.At region actualName) ->
525 Report.Report "MODULE NAME MISMATCH" region [ModuleName.toChars expectedName] $
526 Code.toSnippet source region Nothing
528 "It looks like this module name is out of sync:"
532 "I need it to match the file path, so I was expecting it to see `"
533 ++ ModuleName.toChars expectedName
534 ++ "` here. Make the following change, and you should be all set!"
536 D.dullyellow (D.fromName actualName) <> " -> " <> D.green (D.fromName expectedName)
538 "I require that module names correspond to file paths. This makes it much\
539 \ easier to explore unfamiliar codebases! So if you want to keep the current\
540 \ module name, try renaming the file instead."
544 UnexpectedPort region ->
545 Report.Report "UNEXPECTED PORTS" region [] $
546 Code.toSnippet source region Nothing
549 "You are declaring ports in a normal module."
553 ["Switch","this","to","say",D.green "port module","instead,"
554 ,"marking","that","this","module","contains","port","declarations."
557 "Ports are not a traditional FFI for calling JS functions directly. They need a different mindset! Read"
559 "to learn the syntax and how to use it effectively."
564 Report.Report "NO PORTS" region [] $
565 Code.toSnippet source region Nothing
568 "This module does not declare any ports, but it says it will:"
571 ["Switch","this","to",D.green "module"
572 ,"and","you","should","be","all","set!"
577 toParseErrorReport source modul
580toParseErrorReport :: Code.Source -> Module -> Report.Report
581toParseErrorReport source modul =
583 ModuleSpace space row col ->
584 toSpaceReport source space row col
586 ModuleEndOfFile row col ->
588 region = toRegion row col
590 Report.Report "EXPECTING END OF FILE" region [] $
591 Code.toSnippet source region Nothing
594 "I was not expecting to see anything more here:"
597 "I think I have read all the declarations in the file and that there is nothing\
598 \ left to see, so whatever I am running into is confusing me a lot!"
601 ModuleProblem row col ->
603 region = toRegion row col
605 Report.Report "UNFINISHED MODULE DECLARATION" region [] $
606 Code.toSnippet source region Nothing
609 "I am parsing an `module` declaration, but I got stuck here:"
613 "Here are some examples of valid `module` declarations:"
614 , D.indent 4 $ D.vcat $
615 [ D.fillSep [D.cyan "module","Main",D.cyan "exposing","(..)"]
616 , D.fillSep [D.cyan "module","Dict",D.cyan "exposing","(Dict, empty, get)"]
619 "I generally recommend using an explicit exposing list. I can skip compiling a bunch\
620 \ of files when the public interface of a module stays the same, so exposing fewer\
621 \ values can help improve compile times!"
625 ModuleName row col ->
627 region = toRegion row col
629 Report.Report "EXPECTING MODULE NAME" region [] $
630 Code.toSnippet source region Nothing
633 "I was parsing an `module` declaration until I got stuck here:"
637 "I was expecting to see the module name next, like in these examples:"
638 , D.indent 4 $ D.vcat $
639 [ D.fillSep [D.cyan "module","Dict",D.cyan "exposing","(..)"]
640 , D.fillSep [D.cyan "module","Maybe",D.cyan "exposing","(..)"]
641 , D.fillSep [D.cyan "module","Html.Attributes",D.cyan "exposing","(..)"]
642 , D.fillSep [D.cyan "module","Json.Decode",D.cyan "exposing","(..)"]
645 "Notice that the module names all start with capital letters. That is required!"
649 ModuleExposing exposing row col ->
650 error "TODO ModuleExposing" exposing row col
652 PortModuleProblem row col ->
654 region = toRegion row col
656 Report.Report "UNFINISHED PORT MODULE DECLARATION" region [] $
657 Code.toSnippet source region Nothing
660 "I am parsing an `port module` declaration, but I got stuck here:"
664 "Here are some examples of valid `port module` declarations:"
665 , D.indent 4 $ D.vcat $
666 [ D.fillSep [D.cyan "port",D.cyan "module","WebSockets",D.cyan "exposing","(send, listen, keepAlive)"]
667 , D.fillSep [D.cyan "port",D.cyan "module","Maps",D.cyan "exposing","(Location, goto)"]
669 , D.link "Note" "Read" "ports" "for more help."
673 PortModuleName row col ->
675 region = toRegion row col
677 Report.Report "EXPECTING MODULE NAME" region [] $
678 Code.toSnippet source region Nothing
681 "I was parsing an `module` declaration until I got stuck here:"
685 "I was expecting to see the module name next, like in these examples:"
686 , D.indent 4 $ D.vcat $
687 [ D.fillSep [D.cyan "port",D.cyan "module","WebSockets",D.cyan "exposing","(send, listen, keepAlive)"]
688 , D.fillSep [D.cyan "port",D.cyan "module","Maps",D.cyan "exposing","(Location, goto)"]
691 "Notice that the module names start with capital letters. That is required!"
695 PortModuleExposing exposing row col ->
696 error "TODO PortModuleExposing" exposing row col
700 region = toRegion row col
702 Report.Report "BAD MODULE DECLARATION" region [] $
703 Code.toSnippet source region Nothing
706 "I cannot parse this module declaration:"
709 "This type of module is reserved for the @elm organization. It is used to\
710 \ define certain effects, avoiding building them into the compiler."
715 region = toRegion row col
717 toBadFirstLineReport keyword =
718 Report.Report "TOO MUCH INDENTATION" region [] $
719 Code.toSnippet source region Nothing
722 "This `" ++ keyword ++ "` should not have any spaces before it:"
725 "Delete the spaces before `" ++ keyword ++ "` until there are none left!"
729 case Code.whatIsNext source row col of
730 Code.Keyword "module" -> toBadFirstLineReport "module"
731 Code.Keyword "import" -> toBadFirstLineReport "import"
732 Code.Keyword "type" -> toBadFirstLineReport "type"
733 Code.Keyword "port" -> toBadFirstLineReport "port"
735 Report.Report "SYNTAX PROBLEM" region [] $
736 Code.toSnippet source region Nothing
743 "I am not sure what is going on, but I recommend starting an Elm\
744 \ file with the following lines:"
746 [ D.fillSep [D.cyan "import","Html"]
748 , D.fillSep [D.green "main","="]
749 , D.indent 2 $ D.fillSep [D.cyan "Html" <> ".text",D.dullyellow "\"Hello!\""]
752 "You should be able to copy those lines directly into your file. Check out\
753 \ some of the examples on https://elm-lang.org for more help getting started!"
755 "This can also happen when something is indented too much!"
759 ImportStart row col ->
760 toImportReport source row col
762 ImportName row col ->
764 region = toRegion row col
766 Report.Report "EXPECTING IMPORT NAME" region [] $
767 Code.toSnippet source region Nothing
770 "I was parsing an `import` until I got stuck here:"
774 "I was expecting to see a module name next, like in these examples:"
775 , D.indent 4 $ D.vcat $
776 [ D.fillSep [D.cyan "import","Dict"]
777 , D.fillSep [D.cyan "import","Maybe"]
778 , D.fillSep [D.cyan "import","Html.Attributes"]
779 , D.fillSep [D.cyan "import","Json.Decode"]
782 "Notice that the module names all start with capital letters. That is required!"
787 toImportReport source row col
789 ImportAlias row col ->
791 region = toRegion row col
793 Report.Report "EXECTING IMPORT ALIAS" region [] $
794 Code.toSnippet source region Nothing
797 "I was parsing an `import` until I got stuck here:"
801 "I was expecting to see an alias next, like in these examples:"
802 , D.indent 4 $ D.vcat $
803 [ D.fillSep [D.cyan "import","Html.Attributes",D.cyan "as","Attr"]
804 , D.fillSep [D.cyan "import","WebGL.Texture",D.cyan "as","Texture"]
805 , D.fillSep [D.cyan "import","Json.Decode",D.cyan "as","D"]
808 "Notice that the alias always starts with a capital letter. That is required!"
812 ImportExposing row col ->
813 toImportReport source row col
815 ImportExposingList exposing row col ->
816 error "TODO ImportExposingList" exposing row col
819 toImportReport source row col
821 ImportIndentName row col ->
822 toImportReport source row col
824 ImportIndentAlias row col ->
825 toImportReport source row col
827 ImportIndentExposingList row col ->
829 region = toRegion row col
831 Report.Report "UNFINISHED IMPORT" region [] $
832 Code.toSnippet source region Nothing
835 "I was parsing an `import` until I got stuck here:"
839 "I was expecting to see the list of exposed values next. For example, here\
840 \ are two ways to expose values from the `Html` module:"
841 , D.indent 4 $ D.vcat $
842 [ D.fillSep [D.cyan "import","Html",D.cyan "exposing","(..)"]
843 , D.fillSep [D.cyan "import","Html",D.cyan "exposing","(Html, div, text)"]
846 "I generally recommend the second style. It is more explicit, making it\
847 \ much easier to figure out where values are coming from in large projects!"
853 region = toRegion row col
855 Report.Report "BAD INFIX" region [] $
856 Code.toSnippet source region Nothing
859 "Something went wrong in this infix operator declaration:"
862 "This feature is used by the @elm organization to define the\
863 \ languages built-in operators."
866 Declarations decl _ _ ->
867 toDeclarationsReport source decl
874toImportReport :: Code.Source -> Row -> Col -> Report.Report
875toImportReport source row col =
877 region = toRegion row col
879 Report.Report "UNFINISHED IMPORT" region [] $
880 Code.toSnippet source region Nothing
883 "I am partway through parsing an import, but I got stuck here:"
887 "Here are some examples of valid `import` declarations:"
888 , D.indent 4 $ D.vcat $
889 [ D.fillSep [D.cyan "import","Html"]
890 , D.fillSep [D.cyan "import","Html",D.cyan "as","H"]
891 , D.fillSep [D.cyan "import","Html",D.cyan "as","H",D.cyan "exposing","(..)"]
892 , D.fillSep [D.cyan "import","Html",D.cyan "exposing","(Html, div, text)"]
895 "You are probably trying to import a different module, but try to make it look like one of these examples!"
904toSpaceReport :: Code.Source -> Space -> Row -> Col -> Report.Report
905toSpaceReport source space row col =
909 region = toRegion row col
911 Report.Report "NO TABS" region [] $
912 Code.toSnippet source region Nothing
915 "I ran into a tab, but tabs are not allowed in Elm files."
918 "Replace the tab with spaces."
921 EndlessMultiComment ->
923 region = toWiderRegion row col 2
925 Report.Report "ENDLESS COMMENT" region [] $
926 Code.toSnippet source region Nothing
929 "I cannot find the end of this multi-line comment:"
932 [ D.reflow "Add a -} somewhere after this to end the comment."
934 "Multi-line comments can be nested in Elm, so {- {- -} -} is a comment\
935 \ that happens to contain another comment. Like parentheses and curly braces,\
936 \ the start and end markers must always be balanced. Maybe that is the problem?"
945toRegion :: Row -> Col -> A.Region
948 pos = A.Position row col
953toWiderRegion :: Row -> Col -> Word16 -> A.Region
954toWiderRegion row col extra =
957 (A.Position row (col + extra))
960toDeclarationsReport :: Code.Source -> Decl -> Report.Report
961toDeclarationsReport source decl =
964 error "TODO DeclStart" row col
966 DeclSpace space row col ->
967 toSpaceReport source space row col
970 error "TODO Port" port row col
972 DeclType declType row col ->
973 error "TODO DeclType" declType row col
975 DeclDef name declDef row col ->
976 toDeclDefReport source name declDef row col
978 DeclFreshLineStart row col ->
979 error "TODO DeclFreshLineStart" row col
981 DeclFreshLineAfterDocComment row col ->
982 error "TODO DeclFreshLineAfterDocComment" row col
985toDeclDefReport :: Code.Source -> Name.Name -> DeclDef -> Row -> Col -> Report.Report
986toDeclDefReport source name declDef startRow startCol =
988 DeclDefSpace space row col ->
989 toSpaceReport source space row col
991 DeclDefEquals row col ->
992 error "TODO DeclDefEquals" row col
994 DeclDefType tipe row col ->
995 error "TODO DeclDefType" tipe row col
997 DeclDefArg pattern row col ->
998 error "TODO DeclDefArg" pattern row col
1000 DeclDefBody expr row col ->
1001 toExprReport source (InDef name startRow startCol) expr row col
1003 DeclDefNameRepeat row col ->
1005 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1006 region = toRegion row col
1008 Report.Report "EXPECTING DEFINITION" region [] $
1009 Code.toSnippet source surroundings (Just region)
1012 "I just saw the type annotation for `" ++ Name.toChars name
1013 ++ "` so I was expecting to see its definition here:"
1016 "Type annotations always appear directly above the relevant\
1017 \ definition, without anything else (even doc comments) in between."
1020 DeclDefNameMatch defName row col ->
1022 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1023 region = toRegion row col
1025 Report.Report "NAME MISMATCH" region [] $
1026 Code.toSnippet source surroundings (Just region)
1029 "I just saw a type annotation for `" ++ Name.toChars name ++ "`, but it is followed by a definition for `" ++ Name.toChars defName ++ "`:"
1033 "These names do not match! Is there a typo?"
1034 , D.indent 4 $ D.fillSep $
1035 [D.dullyellow (D.fromName defName),"->",D.green (D.fromName name)]
1039 DeclDefIndentType row col ->
1040 error "TODO DeclDefIndentType" row col
1042 DeclDefIndentEquals row col ->
1043 error "TODO DeclDefIndentEquals" row col
1045 DeclDefIndentBody row col ->
1046 error "TODO DeclDefIndentBody" row col
1048 DeclDefFreshLineAfterType row col ->
1049 error "TODO DeclDefFreshLineAfterType" row col
1057 = InNode Node Row Col Context
1058 | InDef Name.Name Row Col
1072getDefName :: Context -> Name.Name
1075 InDef name _ _ -> name
1076 InNode _ _ _ c -> getDefName c
1079isWithin :: Node -> Context -> Bool
1080isWithin desiredNode context =
1082 InDef _ _ _ -> False
1083 InNode actualNode _ _ _ -> desiredNode == actualNode
1090toExprReport :: Code.Source -> Context -> Expr -> Row -> Col -> Report.Report
1091toExprReport source context expr startRow startCol =
1100 toIfReport source context if_ row col
1102 List list row col ->
1103 toListReport source context list row col
1105 Record record row col ->
1106 toRecordReport source context record row col
1108 Tuple tuple row col ->
1109 toTupleReport source context tuple row col
1111 Func func row col ->
1112 toFuncReport source context func row col
1115 let region = toRegion row col in
1116 Report.Report "EXPECTING RECORD ACCESSOR" region [] $
1117 Code.toSnippet source region Nothing
1120 "I was expecting to see a record accessor here:"
1123 ["Something","like",D.dullyellow".name","or",D.dullyellow".price"
1124 ,"that","accesses","a","value","from","a","record."
1129 let region = toRegion row col in
1130 Report.Report "EXPECTING RECORD ACCESSOR" region [] $
1131 Code.toSnippet source region Nothing
1134 "I am trying to parse a record accessor here:"
1139 ["Something","like",D.dullyellow".name","or",D.dullyellow".price"
1140 ,"that","accesses","a","value","from","a","record."
1144 "Record field names must start with a lower case letter!"
1148 OperatorRight op row col ->
1149 let region = toRegion row col in
1150 Report.Report "MISSING EXPRESSION" region [] $
1151 Code.toSnippet source region Nothing
1154 "I was expecting to see an expression after this " ++ Name.toChars op ++ " operator:"
1158 ["You","can","just","put","anything","for","now,","like"
1159 ,D.dullyellow "42","or",D.dullyellow"\"hello\"" <> "."
1160 ,"Once","there","is","something","there,","I","can","probably"
1161 ,"give","a","more","specific","hint!"
1164 "This can also happen if run into reserved words like `let` or `as` unexpectedly.\
1165 \ Or if I run into operators in unexpected spots. Point is, there are a\
1166 \ couple ways I can get confused and give sort of weird advice!"
1170 OperatorReserved operator row col ->
1171 toOperatorReport source context operator row col
1175 (contextRow, contextCol, aThing) =
1177 InDef name r c -> (r, c, "the `" ++ Name.toChars name ++ "` definition")
1178 InNode NRecord r c _ -> (r, c, "a record")
1179 InNode NParens r c _ -> (r, c, "some parentheses")
1180 InNode NList r c _ -> (r, c, "a list")
1181 InNode NFunc r c _ -> (r, c, "an anonymous function")
1182 InNode NCond r c _ -> (r, c, "an `if` expression")
1183 InNode NThen r c _ -> (r, c, "an `if` expression")
1184 InNode NElse r c _ -> (r, c, "an `if` expression")
1185 -- TODO check if this is actually the best way to get error messages here
1187 surroundings = A.Region (A.Position contextRow contextCol) (A.Position row col)
1188 region = toRegion row col
1190 Report.Report "MISSING EXPRESSION" region [] $
1191 Code.toSnippet source surroundings (Just region)
1194 "I am partway through parsing " ++ aThing ++ ", but I got stuck here:"
1198 ["I","was","expecting","to","see","an","expression","like"
1199 ,D.dullyellow "42","or",D.dullyellow"\"hello\"" <> "."
1200 ,"Once","there","is","something","there,","I","can","probably"
1201 ,"give","a","more","specific","hint!"
1204 "This can also happen if run into reserved words like `let` or `as` unexpectedly.\
1205 \ Or if I run into operators in unexpected spots. Point is, there are a\
1206 \ couple ways I can get confused and give sort of weird advice!"
1210 Char char row col ->
1211 toCharReport source char row col
1213 String string row col ->
1214 toStringReport source string row col
1216 Number number row col ->
1217 toNumberReport source number row col
1219 Space space row col ->
1220 toSpaceReport source space row col
1222 EndlessShader row col ->
1224 region = toWiderRegion row col 6
1226 Report.Report "ENDLESS SHADER" region [] $
1227 Code.toSnippet source region Nothing
1229 D.reflow "I cannot find the end of this shader:"
1231 D.reflow "Add a |] somewhere after this to end the shader."
1234 ShaderProblem problem row col ->
1236 region = toRegion row col
1238 Report.Report "SHADER PROBLEM" region [] $
1239 Code.toSnippet source region Nothing
1242 "I ran into a problem while parsing this GLSL block."
1246 "I use a 3rd party GLSL parser for now, and I did my best to extract their error message:"
1247 , D.indent 4 $ D.vcat $
1248 map D.fromChars (filter (/="") (lines problem))
1252 IndentOperatorRight op row col ->
1254 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1255 region = toRegion row col
1257 Report.Report "MISSING EXPRESSION" region [] $
1258 Code.toSnippet source surroundings (Just region)
1261 "I was expecting to see an expression after this " ++ Name.toChars op ++ " operator:"
1266 ["You","can","just","put","anything","for","now,","like"
1267 ,D.dullyellow "42","or",D.dullyellow"\"hello\"" <> "."
1268 ,"Once","there","is","something","there,","I","can","probably"
1269 ,"give","a","more","specific","hint!"
1273 "I may be getting confused by your indentation? The easiest way to make sure\
1274 \ this is not an indentation problem is to put the expression on the right of\
1275 \ the " ++ Name.toChars op ++ " operator on the same line."
1279 IndentMoreExpr _ _ ->
1280 error "TODO IndentMoreExpr"
1287toCharReport :: Code.Source -> Char -> Row -> Col -> Report.Report
1288toCharReport source char row col =
1292 region = toRegion row col
1294 Report.Report "MISSING SINGLE QUOTE" region [] $
1295 Code.toSnippet source region Nothing
1298 "I thought I was parsing a character, but I got to the end of\
1299 \ the line without seeing the closing single quote:"
1302 "Add a closing single quote here!"
1305 CharEscape escape ->
1306 toEscapeReport source escape row col
1308 CharNotString width ->
1310 region = toWiderRegion row col width
1312 Report.Report "NEEDS DOUBLE QUOTES" region [] $
1313 Code.toSnippet source region Nothing
1315 "The following string uses single quotes:"
1318 [ "Please switch to double quotes instead:"
1320 D.dullyellow "'this'" <> " => " <> D.green "\"this\""
1322 "Elm uses double quotes for strings like \"hello\", whereas it uses single\
1323 \ quotes for individual characters like 'a' and 'ø'. This distinction helps with\
1324 \ code like (String.any (\\c -> c == 'X') \"90210\") where you are inspecting\
1325 \ individual characters."
1334toStringReport :: Code.Source -> String -> Row -> Col -> Report.Report
1335toStringReport source string row col =
1337 StringEndless_Single ->
1339 region = toRegion row col
1341 Report.Report "ENDLESS STRING" region [] $
1342 Code.toSnippet source region Nothing
1345 "I got to the end of the line without seeing the closing double quote:"
1349 ["Strings","look","like",D.green "\"this\"","with","double"
1350 ,"quotes","on","each","end.","Is","the","closing","double"
1351 ,"quote","missing","in","your","code?"
1353 , D.link "Note" "Read" "TODO" "if you want a string that spans multiple lines."
1357 StringEndless_Multi ->
1359 region = toWiderRegion row col 3
1361 Report.Report "ENDLESS STRING" region [] $
1362 Code.toSnippet source region Nothing
1365 "I cannot find the end of this multi-line string:"
1368 [ D.reflow "Add a \"\"\" somewhere after this to end the string."
1369 , D.link "Hint" "Read" "TODO" "for more information on strings and multi-line strings."
1373 StringEscape escape ->
1374 toEscapeReport source escape row col
1381toEscapeReport :: Code.Source -> Escape -> Row -> Col -> Report.Report
1382toEscapeReport source escape row col =
1386 region = toWiderRegion row col 2
1388 Report.Report "UNKNOWN ESCAPE" region [] $
1389 Code.toSnippet source region Nothing
1392 "Backslashes always start escaped characters, but I do not recognize this one:"
1396 "Valid escape characters include:"
1397 , D.dullyellow $ D.indent 4 $ D.vcat $
1407 "Do you want one of those instead? Maybe you need \\\\ to escape a backslash?"
1409 "The last style lets encode ANY character by its Unicode code\
1410 \ point. That means \\u{0009} and \\t are the same. You can use\
1411 \ that style for anything not covered by the other six escapes!"
1415 BadUnicodeFormat width ->
1417 region = toWiderRegion row col width
1419 Report.Report "BAD UNICODE ESCAPE" region [] $
1420 Code.toSnippet source region Nothing
1423 "I ran into an invalid Unicode escape:"
1427 "Here are some examples of valid Unicode escapes:"
1428 , D.dullyellow $ D.indent 4 $ D.vcat $
1435 "Notice that the code point is always surrounded by curly braces.\
1436 \ Maybe you are missing the opening or closing curly brace?"
1439 BadUnicodeCode width ->
1441 region = toWiderRegion row col width
1443 Report.Report "BAD UNICODE ESCAPE" region [] $
1444 Code.toSnippet source region Nothing
1447 "This is not a valid code point:"
1450 "The valid code points are between 0 and 10FFFF inclusive."
1453 BadUnicodeLength width numDigits badCode ->
1455 region = toWiderRegion row col width
1457 Report.Report "BAD UNICODE ESCAPE" region [] $
1458 Code.toSnippet source region Nothing $
1459 if numDigits < 4 then
1462 "Every code point needs at least four digits:"
1465 goodCode = replicate (4 - numDigits) '0' ++ map Char.toUpper (showHex badCode "")
1466 suggestion = "\\u{" <> D.fromChars goodCode <> "}"
1468 D.fillSep ["Try",D.green suggestion,"instead?"]
1474 "This code point has too many digits:"
1477 ["Valid","code","points","are","between"
1478 ,D.green "\\u{0000}","and",D.green "\\u{10FFFF}" <> ","
1479 ,"so","try","trimming","any","leading","zeros","until"
1480 ,"you","have","between","four","and","six","digits."
1489toNumberReport :: Code.Source -> Number -> Row -> Col -> Report.Report
1490toNumberReport source number row col =
1492 region = toRegion row col
1496 Report.Report "WEIRD NUMBER" region [] $
1497 Code.toSnippet source region Nothing
1500 "I thought I was reading a number, but I ran into some weird stuff here:"
1504 "I recognize numbers in the following formats:"
1505 , D.indent 4 $ D.vcat [ "42", "3.14", "6.022e23", "0x002B" ]
1507 "So is there a way to write it like one of those?"
1512 Report.Report "WEIRD NUMBER" region [] $
1513 Code.toSnippet source region Nothing
1516 "Numbers cannot end with a dot like this:"
1519 ["Switching","to",D.green (D.fromChars (show int))
1520 ,"or",D.green (D.fromChars (show int ++ ".0"))
1521 ,"will","work","though!"
1526 Report.Report "WEIRD HEXIDECIMAL" region [] $
1527 Code.toSnippet source region Nothing
1530 "I thought I was reading a hexidecimal number until I got here:"
1534 "Valid hexidecimal digits include 0123456789abcdefABCDEF, so I can\
1535 \ only recognize things like this:"
1536 , D.indent 4 $ D.vcat [ "0x2B", "0x002B", "0x00ffb3" ]
1540 NumberNoLeadingZero ->
1541 Report.Report "LEADING ZEROS" region [] $
1542 Code.toSnippet source region Nothing
1545 "I do not accept numbers with leading zeros:"
1549 "Just delete the leading zeros and it should work!"
1551 "Some languages let you to specify octal numbers by adding a leading zero.\
1552 \ So in C, writing 0111 is the same as writing 73. Some people are used to\
1553 \ that, but others probably want it to equal 111. Either path is going to\
1554 \ surprise people from certain backgrounds, so Elm tries to avoid this whole\
1564toOperatorReport :: Code.Source -> Context -> BadOperator -> Row -> Col -> Report.Report
1565toOperatorReport source context operator row col =
1569 region = toRegion row col
1571 Report.Report "UNEXPECTED SYMBOL" region [] $
1572 Code.toSnippet source region Nothing
1574 "I was not expecting this dot:"
1577 "Dots are for record access and decimal points, so\
1578 \ they cannot float around on their own. Maybe\
1579 \ there is some extra whitespace?"
1584 region = toRegion row col
1586 Report.Report "UNEXPECTED SYMBOL" region [] $
1587 Code.toSnippet source region Nothing
1590 "I was not expecting this vertical bar:"
1593 "Vertical bars should only appear in custom type declarations. Maybe you want || instead?"
1598 region = toWiderRegion row col 2
1600 Report.Report "UNEXPECTED ARROW" region [] $
1601 Code.toSnippet source region Nothing $
1602 if error "TODO inCase" then
1605 "I was not expecting to see an arrow here:"
1610 "I think I am parsing a `case` expression right now, so it makes sense to\
1611 \ see arrows around here. This one is confusing me though!"
1614 "I may be getting confused by the indentation. Every pattern in a `case` must be\
1615 \ exactly aligned (with exactly the same amount of indentation) so maybe this arrow\
1616 \ appears after the next `case` pattern (correctly!) but the pattern itself is\
1617 \ indented too far?"
1624 "I was not expecting an arrow here:"
1627 "Arrows should only appear in `case` expressions and anonymous functions. Maybe\
1628 \ you want > or >= instead?"
1633 region = toRegion row col
1634 name = getDefName context
1636 Report.Report "UNEXPECTED EQUALS" region [] $
1637 Code.toSnippet source region Nothing
1640 "I was not expecting to see this equals sign:"
1644 D.reflow "Maybe you want == instead? To check if two values are equal?"
1647 if isWithin NRecord context then
1648 "Records look like { x = 3, y = 4 } with the equals sign right\
1649 \ after the field name. So maybe you forgot a comma?"
1651 "I may be getting confused by your indentation. Is this supposed to be part of\
1652 \ a definition AFTER the `" ++ Name.toChars name ++ "` definition? If so,\
1653 \ the problem may be a bit before the equals sign. I need all definitions to\
1654 \ be exactly aligned (with exactly the same indentation) so the problem may be that\
1655 \ this new definition is indented a bit too much."
1661 region = toRegion row col
1662 name = getDefName context
1664 Report.Report "UNEXPECTED SYMBOL" region [] $
1665 Code.toSnippet source region Nothing $
1668 "I was not expecting to run into the \"has type\" symbol here:"
1673 ["Maybe","you","want",D.green "::","instead?"
1674 ,"To","put","something","on","the","front","of","a","list?"
1677 "The single colon is reserved for type annotations and record types, but I think\
1678 \ I am parsing the definition of `" ++ Name.toChars name ++ "` right now."
1681 "I may be getting confused by your indentation. Is this supposed to be part of\
1682 \ a type annotation AFTER the `" ++ Name.toChars name ++ "` definition? If so,\
1683 \ the problem may be a bit before the \"has type\" symbol. I need all definitions to\
1684 \ be exactly aligned (with exactly the same indentation) so the problem may be that\
1685 \ this new definition is indented a bit too much."
1694toIfReport :: Code.Source -> Context -> If -> Row -> Col -> Report.Report
1695toIfReport source context if_ startRow startCol =
1697 IfSpace space row col ->
1698 toSpaceReport source space row col
1702 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1703 region = toRegion row col
1705 Report.Report "UNFINISHED IF" region [] $
1706 Code.toSnippet source surroundings (Just region)
1709 "I was expecting to see more of this `if` expression, but I got stuck here:"
1712 ["I","was","expecting","to","see","the",D.green "then","keyword","next."
1718 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1719 region = toRegion row col
1721 Report.Report "UNFINISHED IF" region [] $
1722 Code.toSnippet source surroundings (Just region)
1725 "I was expecting to see more of this `if` expression, but I got stuck here:"
1728 ["I","was","expecting","to","see","the",D.green "else","keyword","next."
1732 IfElseBranchStart row col ->
1734 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1735 region = toRegion row col
1737 Report.Report "UNFINISHED IF" region [] $
1738 Code.toSnippet source surroundings (Just region)
1741 "I just saw the start of an `else` branch, but then I got stuck here:"
1744 "I was expecting to see an expression next. Maybe it is not filled in yet?"
1747 IfCondition expr row col ->
1748 toExprReport source (InNode NCond startRow startCol context) expr row col
1750 IfThenBranch expr row col ->
1751 toExprReport source (InNode NThen startRow startCol context) expr row col
1753 IfElseBranch expr row col ->
1754 toExprReport source (InNode NElse startRow startCol context) expr row col
1756 IfIndentCondition row col ->
1758 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1759 region = toRegion row col
1761 Report.Report "UNFINISHED IF" region [] $
1762 Code.toSnippet source surroundings (Just region)
1765 "I was expecting to see more of this `if` expression, but I got stuck here:"
1769 ["I","was","expecting","to","see","an","expression","like",D.dullyellow "x < 0"
1770 ,"that","evaluates","to","True","or","False."
1773 "I can be confused by indentation. Maybe something is not indented enough?"
1777 IfIndentThen row col ->
1779 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1780 region = toRegion row col
1782 Report.Report "UNFINISHED IF" region [] $
1783 Code.toSnippet source surroundings (Just region)
1786 "I was expecting to see more of this `if` expression, but I got stuck here:"
1790 ["I","was","expecting","to","see","the",D.green "then","keyword","next."
1793 "I can be confused by indentation. Maybe something is not indented enough?"
1797 IfIndentThenBranch row col ->
1799 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1800 region = toRegion row col
1802 Report.Report "UNFINISHED IF" region [] $
1803 Code.toSnippet source surroundings (Just region)
1806 "I got stuck after the start of this `then` branch:"
1810 "I was expecting to see an expression next. Maybe it is not filled in yet?"
1812 "I can be confused by indentation, so if the `then` branch is already\
1813 \ present, it may not be indented enough for me to recognize it."
1817 IfIndentElseBranch row col ->
1819 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1820 region = toRegion row col
1822 Report.Report "UNFINISHED IF" region [] $
1823 Code.toSnippet source surroundings (Just region)
1826 "I got stuck after the start of this `else` branch:"
1830 "I was expecting to see an expression next. Maybe it is not filled in yet?"
1832 "I can be confused by indentation, so if the `else` branch is already\
1833 \ present, it may not be indented enough for me to recognize it."
1837 IfIndentElse row col ->
1839 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1840 region = toRegion row col
1842 Report.Report "UNFINISHED IF" region [] $
1843 Code.toSnippet source surroundings (Just region)
1846 "I was expecting to see an `else` branch after this:"
1850 "I know what to do when the condition is `True`, but not when it is `False`."
1852 ["Add","an",D.green "else","branch","to","handle","that","scenario!"]
1861toRecordReport :: Code.Source -> Context -> Record -> Row -> Col -> Report.Report
1862toRecordReport source context record startRow startCol =
1864 RecordOpen row col ->
1866 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1867 region = toRegion row col
1869 case Code.whatIsNext source row col of
1870 Code.Keyword keyword ->
1871 Report.Report "RESERVED WORD" region [] $
1872 Code.toSnippet source surroundings (Just region)
1875 "I just started parsing a record, but I got stuck on this field name:"
1878 "It looks like you are trying to use `" ++ keyword ++ "` as a field name, but \
1879 \ that is a reserved word. Try using a different name!"
1883 Report.Report "UNFINISHED RECORD" region [] $
1884 Code.toSnippet source surroundings (Just region)
1887 "I just started parsing a record, but I got stuck here:"
1890 ["Records","look","like",D.dullyellow "{ x = 3, y = 4 },"
1891 ,"so","I","was","expecting","to","see","a","field","name","next."
1895 RecordEnd row col ->
1897 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1898 region = toRegion row col
1900 Report.Report "UNFINISHED RECORD" region [] $
1901 Code.toSnippet source surroundings (Just region)
1904 "I am partway through parsing a record, but I got stuck here:"
1908 ["I","was","expecting","to","see","a","closing","curly","brace","before","this,"
1909 ,"so","try","adding","a",D.dullyellow "}","and","see","if","that","helps?"
1912 "When I get stuck like this, it usually means that there is a missing parenthesis\
1913 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
1917 RecordField row col ->
1919 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1920 region = toRegion row col
1922 case Code.whatIsNext source row col of
1923 Code.Keyword keyword ->
1924 Report.Report "RESERVED WORD" region [] $
1925 Code.toSnippet source surroundings (Just region)
1928 "I am partway through parsing a record, but I got stuck on this field name:"
1931 "It looks like you are trying to use `" ++ keyword ++ "` as a field name, but \
1932 \ that is a reserved word. Try using a different name!"
1936 Report.Report "UNFINISHED RECORD" region [] $
1937 Code.toSnippet source surroundings (Just region)
1940 "I am partway through parsing a record, but I got stuck after that last comma:"
1942 addNoteForRecordError $
1944 "Trailing commas are not allowed in records, so I was expecting to see another\
1945 \ record field defined next. If you are done defining the record, the fix may\
1946 \ be to delete that last comma?"
1949 RecordEquals row col ->
1951 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1952 region = toRegion row col
1954 Report.Report "UNFINISHED RECORD" region [] $
1955 Code.toSnippet source surroundings (Just region)
1958 "I am partway through parsing a record, but I got stuck here:"
1960 addNoteForRecordError $
1962 ["I","just","saw","a","field","name,","so","I","was","expecting","to","see"
1963 ,"an","equals","sign","next.","So","try","putting","an",D.green "=","sign","here?"
1967 RecordExpr expr row col ->
1968 toExprReport source (InNode NRecord startRow startCol context) expr row col
1970 RecordSpace space row col ->
1971 toSpaceReport source space row col
1973 RecordIndentOpen row col ->
1975 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1976 region = toRegion row col
1978 Report.Report "UNFINISHED RECORD" region [] $
1979 Code.toSnippet source surroundings (Just region)
1982 "I just saw the opening curly brace of a record, but then I got stuck here:"
1984 addNoteForRecordIndentError $
1986 ["I","am","expecting","a","record","like",D.dullyellow "{ x = 3, y = 4 }","here."
1987 ,"Try","defining","some","fields","of","your","own?"
1991 RecordIndentEnd row col ->
1993 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1994 region = toRegion row col
1996 Report.Report "UNFINISHED RECORD" region [] $
1997 Code.toSnippet source surroundings (Just region)
2000 "I was expecting to see a closing curly brace next:"
2002 addNoteForRecordIndentError $
2004 ["Try","putting","an",D.green "}","and","see","if","that","helps?"
2008 RecordIndentField row col ->
2010 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2011 region = toRegion row col
2013 Report.Report "UNFINISHED RECORD" region [] $
2014 Code.toSnippet source surroundings (Just region)
2017 "I am partway through parsing a record, but I got stuck after that last comma:"
2019 addNoteForRecordError $
2021 "Trailing commas are not allowed in records, so the fix may be to\
2022 \ delete that last comma? Or maybe you were in the middle of defining\
2023 \ an additional field?"
2026 RecordIndentEquals row col ->
2028 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2029 region = toRegion row col
2031 Report.Report "UNFINISHED RECORD" region [] $
2032 Code.toSnippet source surroundings (Just region)
2035 "I am partway through parsing a record. I just saw a record\
2036 \ field, so I was expecting to see an equals sign next:"
2038 addNoteForRecordIndentError $
2040 ["Try","putting","an",D.green "=","followed","by","an","expression?"
2044 RecordIndentExpr row col ->
2046 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2047 region = toRegion row col
2049 Report.Report "UNFINISHED RECORD" region [] $
2050 Code.toSnippet source surroundings (Just region)
2053 "I am partway through parsing a record, and I was expecting to run into an expression next:"
2055 addNoteForRecordIndentError $
2057 ["Try","putting","something,","like"
2058 ,D.dullyellow "42","or",D.dullyellow"\"hello\"","for","now?"
2063addNoteForRecordError :: D.Doc -> D.Doc
2064addNoteForRecordError normalRecommendation =
2066 normalRecommendation
2069 "If you are trying to define a record across multiple lines, I recommend using this format:"
2070 , D.indent 4 $ D.vcat $
2071 [ "{ name = \"Alice\""
2077 "Notice that nothing comes directly after a newline. Each line starts with some spaces. I\
2078 \ know this style can be jarring for people coming from C-like syntax, but folks generally\
2079 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
2083addNoteForRecordIndentError :: D.Doc -> D.Doc
2084addNoteForRecordIndentError normalRecommendation =
2086 normalRecommendation
2089 "I may be confused by indentation. For example, if you are trying to define\
2090 \ a record across multiple lines, I recommend using this format:"
2091 , D.indent 4 $ D.vcat $
2098 "Notice that nothing comes directly after a newline. Each line starts with some spaces. I\
2099 \ know this style can be jarring for people coming from C-like syntax, but folks generally\
2100 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
2108toTupleReport :: Code.Source -> Context -> Tuple -> Row -> Col -> Report.Report
2109toTupleReport source context tuple startRow startCol =
2111 TupleExpr expr row col ->
2112 toExprReport source (InNode NParens startRow startCol context) expr row col
2114 TupleSpace space row col ->
2115 toSpaceReport source space row col
2119 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2120 region = toRegion row col
2122 Report.Report "UNFINISHED PARENTHESES" region [] $
2123 Code.toSnippet source surroundings (Just region)
2126 "I was expecting to see a closing parentheses next, but I got stuck here:"
2129 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps?"]
2131 "I can get stuck when I run into keywords, operators, parentheses, or brackets\
2132 \ unexpectedly. So there may be some earlier syntax trouble (like extra parenthesis\
2133 \ or missing brackets) that is confusing me."
2137 TupleOperatorClose row col ->
2139 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2140 region = toRegion row col
2142 Report.Report "UNFINISHED OPERATOR FUNCTION" region [] $
2143 Code.toSnippet source surroundings (Just region)
2145 D.reflow "I was expecting a closing parenthesis here:"
2148 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps!"]
2150 "I think I am parsing an operator function right now, so I am expecting to see\
2151 \ something like (+) or (&&) where an operator is surrounded by parentheses with\
2156 TupleOperatorReserved operator row col ->
2158 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2159 region = toRegion row col
2161 Report.Report "UNEXPECTED SYMBOL" region [] $
2162 Code.toSnippet source surroundings (Just region)
2165 "I ran into an unexpected symbol here:"
2169 BadDot -> ["Maybe","you","wanted","a","record","accessor","like",D.dullyellow ".x","or",D.dullyellow ".name","instead?"]
2170 BadPipe -> ["Try",D.dullyellow "(||)","instead?","To","turn","boolean","OR","into","a","function?"]
2171 BadArrow -> ["Maybe","you","wanted",D.dullyellow "(>)","or",D.dullyellow "(>=)","instead?"]
2172 BadEquals -> ["Try",D.dullyellow "(==)","instead?","To","make","a","function","that","checks","equality?"]
2173 BadHasType -> ["Try",D.dullyellow "(::)","instead?","To","add","values","to","the","front","of","lists?"]
2176 TupleIndentExpr1 row col ->
2178 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2179 region = toRegion row col
2181 Report.Report "UNFINISHED PARENTHESES" region [] $
2182 Code.toSnippet source surroundings (Just region)
2185 "I just saw an open parenthesis, so I was expecting to see an expression next."
2189 ["Something","like",D.dullyellow "(4 + 5)","or"
2190 ,D.dullyellow "(String.reverse \"desserts\")" <> "."
2191 ,"Anything","where","you","are","putting","parentheses","around","normal","expressions."
2194 "I can get confused by indentation in cases like this, so\
2195 \ maybe you have an expression but it is not indented enough?"
2199 TupleIndentExprN row col ->
2201 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2202 region = toRegion row col
2204 Report.Report "UNFINISHED TUPLE" region [] $
2205 Code.toSnippet source surroundings (Just region)
2208 "I think I am in the middle of parsing a tuple. I just saw a comma, so I was expecting to see expression next."
2212 ["A","tuple","looks","like",D.dullyellow "(3,4)","or"
2213 ,D.dullyellow "(\"Tom\",42)" <> ","
2214 ,"so","I","think","there","is","an","expression","missing","here?"
2217 "I can get confused by indentation in cases like this, so\
2218 \ maybe you have an expression but it is not indented enough?"
2222 TupleIndentEnd row col ->
2224 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2225 region = toRegion row col
2227 Report.Report "UNFINISHED PARENTHESES" region [] $
2228 Code.toSnippet source surroundings (Just region)
2231 "I was expecting to see a closing parenthesis next:"
2234 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps!"]
2236 "I can get confused by indentation in cases like this, so\
2237 \ maybe you have a closing parenthesis but it is not indented enough?"
2242toListReport :: Code.Source -> Context -> List -> Row -> Col -> Report.Report
2243toListReport source context list startRow startCol =
2245 ListSpace space row col ->
2246 toSpaceReport source space row col
2250 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2251 region = toRegion row col
2253 Report.Report "UNFINISHED LIST" region [] $
2254 Code.toSnippet source surroundings (Just region)
2257 "I am partway through parsing a list, but I got stuck here:"
2261 ["I","was","expecting","to","see","a","closing","square","bracket","before","this,"
2262 ,"so","try","adding","a",D.dullyellow "]","and","see","if","that","helps?"
2265 "When I get stuck like this, it usually means that there is a missing parenthesis\
2266 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
2270 ListExpr expr row col ->
2274 surroundings = A.Region (A.Position startRow startCol) (A.Position r c)
2275 region = toRegion r c
2277 Report.Report "UNFINISHED LIST" region [] $
2278 Code.toSnippet source surroundings (Just region)
2281 "I was expecting to see another list entry after that last comma:"
2285 "Trailing commas are not allowed in lists, so the fix may be to delete the comma?"
2287 "I recommend using the following format for lists that span multiple lines:"
2288 , D.indent 4 $ D.vcat $
2295 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
2296 \ This style can be jarring for people coming from C-like syntax, but folks generally\
2297 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
2302 toExprReport source (InNode NList startRow startCol context) expr row col
2306 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2307 region = toRegion row col
2309 Report.Report "UNFINISHED LIST" region [] $
2310 Code.toSnippet source surroundings (Just region)
2313 "I am partway through parsing a list, but I got stuck here:"
2317 ["I","was","expecting","to","see","a","closing","square","bracket","before","this,"
2318 ,"so","try","adding","a",D.dullyellow "]","and","see","if","that","helps?"
2321 "When I get stuck like this, it usually means that there is a missing parenthesis\
2322 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
2326 ListIndentOpen row col ->
2328 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2329 region = toRegion row col
2331 Report.Report "UNFINISHED LIST" region [] $
2332 Code.toSnippet source surroundings (Just region)
2335 "I cannot find the end of this list:"
2339 ["You","could","change","it","to","something","like"
2340 ,D.dullyellow "[3,4,5]"
2342 ,D.dullyellow "[]" <> "."
2343 ,"Anything","where","there","is","an","open","and","close","square","brace,"
2344 ,"and","where","the","elements","of","the","list","are","separated","by","commas."
2347 "I may be confused by indentation. For example, if you are trying to define\
2348 \ a list across multiple lines, I recommend using this format:"
2349 , D.indent 4 $ D.vcat $
2356 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
2357 \ This style can be jarring for people coming from C-like syntax, but folks generally\
2358 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
2362 ListIndentEnd row col ->
2364 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2365 region = toRegion row col
2367 Report.Report "UNFINISHED LIST" region [] $
2368 Code.toSnippet source surroundings (Just region)
2371 "I cannot find the end of this list:"
2375 ["You","can","just","add","a","closing",D.dullyellow "]"
2376 ,"right","here,","and","I","will","be","all","set!"
2379 "I may be confused by indentation. For example, if you are trying to define\
2380 \ a list across multiple lines, I recommend using this format:"
2381 , D.indent 4 $ D.vcat $
2388 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
2389 \ This style can be jarring for people coming from C-like syntax, but folks generally\
2390 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
2394 ListIndentExpr row col ->
2396 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2397 region = toRegion row col
2399 Report.Report "UNFINISHED LIST" region [] $
2400 Code.toSnippet source surroundings (Just region)
2403 "I was expecting to see another list entry after this comma:"
2407 "Trailing commas are not allowed in lists, so the fix may be to delete the comma?"
2409 "I recommend using the following format for lists that span multiple lines:"
2410 , D.indent 4 $ D.vcat $
2417 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
2418 \ This style can be jarring for people coming from C-like syntax, but folks generally\
2419 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
2424toFuncReport :: Code.Source -> Context -> Func -> Row -> Col -> Report.Report
2425toFuncReport source context func startRow startCol =
2427 FuncSpace space row col ->
2428 toSpaceReport source space row col
2430 FuncArg pattern row col ->
2431 error "TODO FuncArg" pattern row col
2433 FuncBody expr row col ->
2434 toExprReport source (InNode NFunc startRow startCol context) expr row col
2436 FuncArrow row col ->
2438 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2439 region = toRegion row col
2441 case Code.whatIsNext source row col of
2442 Code.Keyword keyword ->
2443 Report.Report "RESERVED WORD" region [] $
2444 Code.toSnippet source surroundings (Just region)
2447 "I was parsing an anonymous function, but I got stuck here:"
2450 "It looks like you are trying to use `" ++ keyword ++ "` as an argument, but\
2451 \ it is a reserved word in this language. Try using a different argument name!"
2455 Report.Report "UNFINISHED ANONYMOUS FUNCTION" region [] $
2456 Code.toSnippet source surroundings (Just region)
2459 "I just saw the beginning of an anonymous function, so I was expecting to see an arrow next:"
2462 ["The","syntax","for","anonymous","functions","is"
2463 ,D.dullyellow "(\\x -> x + 1)"
2464 ,"so","I","am","missing","the","arrow","and","the","body","of","the","function."
2468 FuncIndentArg row col ->
2470 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2471 region = toRegion row col
2473 Report.Report "MISSING ARGUMENT" region [] $
2474 Code.toSnippet source surroundings (Just region)
2477 "I just saw the beginning of an anonymous function, so I was expecting to see an argument next:"
2481 ["Something","like",D.dullyellow"x","or",D.dullyellow "name" <> "."
2482 ,"Anything","that","starts","with","a","lower","case","letter!"
2485 "The syntax for anonymous functions is (\\x -> x + 1) where the backslash\
2486 \ is meant to look a bit like a lambda if you squint. This visual pun seemed\
2487 \ like a better idea at the time!"
2491 FuncIndentArrow row col ->
2493 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2494 region = toRegion row col
2496 Report.Report "UNFINISHED ANONYMOUS FUNCTION" region [] $
2497 Code.toSnippet source surroundings (Just region)
2500 "I just saw the beginning of an anonymous function, so I was expecting to see an arrow next:"
2504 ["The","syntax","for","anonymous","functions","is"
2505 ,D.dullyellow "(\\x -> x + 1)"
2506 ,"so","I","am","missing","the","arrow","and","the","body","of","the","function."
2509 "It is possible that I am confused about indetation! I generally recommend\
2510 \ switching to named functions if the definition cannot fit inline nicely, so\
2511 \ either (1) try to fit the whole anonymous function on one line or (2) break\
2512 \ the whole thing out into a named function. Things tend to be clearer that way!"
2516 FuncIndentBody row col ->
2518 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2519 region = toRegion row col
2521 Report.Report "UNFINISHED ANONYMOUS FUNCTION" region [] $
2522 Code.toSnippet source surroundings (Just region)
2525 "I was expecting to see the body of your anonymous function next:"
2529 ["The","syntax","for","anonymous","functions","is"
2530 ,D.dullyellow "(\\x -> x + 1)"
2531 ,"so","I","am","missing","all","the","stuff","after","the","arrow!"
2534 "It is possible that I am confused about indetation! I generally recommend\
2535 \ switching to named functions if the definition cannot fit inline nicely, so\
2536 \ either (1) try to fit the whole anonymous function on one line or (2) break\
2537 \ the whole thing out into a named function. Things tend to be clearer that way!"
2546 CommentOnNothing region ->
2547 Report.Report "STRAY COMMENT" region [] $
2548 Code.toSnippet source region Nothing
2550 "This documentation comment is not followed by anything."
2553 "All documentation comments need to be right above the declaration they\
2554 \ describe. Maybe some code got deleted or commented out by accident? Or\
2555 \ maybe this comment is here by accident?"
2558 ParseError row col context expectation ->
2560 pos = A.Position row col
2561 region = A.Region pos pos
2566 Report.Report "EXPECTING DOC COMMENT" region [] $
2567 Code.toSnippet source region Nothing
2570 "I was expecting a doc comment here:"
2573 "Check out" "TODO" "for examples of doc comments."
2579 Report.Report "EXPECTING A WILDCARD" region [] $
2580 Code.toSnippet source region Nothing
2583 "I was expecting a _ here:"
2586 "An underscore indicates that “I do not care about this value” and is\
2587 \ called a wildcard pattern because it will match with any type of values."
2590 WildcardNotVar startCol endCol ->
2593 A.Region (A.Position row startCol) (A.Position row endCol)
2595 Report.Report "INVALID PATTERN" badRegion [] $
2596 Code.toSnippet source badRegion Nothing
2599 "I was expecting to see an underscore without any additional characters:"
2602 "There are two options. Either (1) remove the extra characters and ignore the\
2603 \ value or (2) remove the starting underscore to give the value a normal name."
2609 Report.Report "INVALID PATTERN" region [] $
2610 Code.toSnippet source region Nothing
2613 "I cannot pattern match with floating point numbers:"
2616 "Equality on floats can be unreliable, so you usually want to check that they\
2617 \ are nearby with some sort of (abs (actual - expected) < 0.001) check."
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