@@ -2,6 +2,7 @@
22{-# LANGUAGE OverloadedStrings #-}
33module Reporting.Error.Syntax
44 ( Error(..)
5+ , toReport
56 --
67 , Module(..)
78 , Exposing(..)
@@ -39,7 +40,7 @@ module Reporting.Error.Syntax
3940 , Number(..)
4041 --
4142 , Space(..)
42− , toReport
43+ , toSpaceReport
4344 )
4445 where
4546
@@ -68,6 +69,9 @@ data Error
6869 | ModuleNameMismatch ModuleName.Raw (A.Located ModuleName.Raw)
6970 | UnexpectedPort A.Region
7071 | NoPorts A.Region
72+ | NoPortsInPackage (A.Located Name.Name)
73+ | NoPortModulesInPackage A.Region
74+ | NoEffectsOutsideKernel A.Region
7175 | ParseError Module
7276
7377
@@ -516,7 +520,7 @@ toReport source err =
516520 ,
517521 D.stack
518522 [ D.reflow $
519− "I need it to match the file path, so I was expecting it to see `"
523+ "I need it to match the file path, so I was expecting to see `"
520524 ++ ModuleName.toChars expectedName
521525 ++ "` here. Make the following change, and you should be all set!"
522526 , D.indent 4 $
@@ -560,10 +564,84 @@ toReport source err =
560564 ]
561565 )
562566
567+ NoPortsInPackage (A.At region _) ->
568+ Report.Report "PACKAGES CANNOT HAVE PORTS" region [] $
569+ Code.toSnippet source region Nothing
570+ (
571+ D.reflow $
572+ "Packages cannot declare any ports, so I am getting stuck here:"
573+ ,
574+ D.stack
575+ [ D.reflow $
576+ "Remove this port declaration."
577+ , noteForPortsInPackage
578+ ]
579+ )
580+
581+ NoPortModulesInPackage region ->
582+ Report.Report "PACKAGES CANNOT HAVE PORTS" region [] $
583+ Code.toSnippet source region Nothing
584+ (
585+ D.reflow $
586+ "Packages cannot declare any ports, so I am getting stuck here:"
587+ ,
588+ D.stack
589+ [ D.fillSep $
590+ ["Remove","the",D.cyan "port","keyword","and","I"
591+ ,"should","be","able","to","continue."
592+ ]
593+ , noteForPortsInPackage
594+ ]
595+ )
596+
597+ NoEffectsOutsideKernel region ->
598+ Report.Report "INVALID EFFECT MODULE" region [] $
599+ Code.toSnippet source region Nothing
600+ (
601+ D.reflow $
602+ "It is not possible to declare an `effect module` outside the @elm organization,\
603+ \ so I am getting stuck here:"
604+ ,
605+ D.stack
606+ [ D.reflow $
607+ "Switch to a normal module declaration."
608+ , D.toSimpleNote $
609+ "Effect modules are designed to allow certain core functionality to be\
610+ \ defined separately from the compiler. So the @elm organization has access to\
611+ \ this so that certain changes, extensions, and fixes can be introduced without\
612+ \ needing to release new Elm binaries. For example, we want to make it possible\
613+ \ to test effects, but this may require changes to the design of effect modules.\
614+ \ By only having them defined in the @elm organization, that kind of design work\
615+ \ can proceed much more smoothly."
616+ ]
617+ )
618+
563619 ParseError modul ->
564620 toParseErrorReport source modul
565621
566622
623+noteForPortsInPackage :: D.Doc
624+noteForPortsInPackage =
625+ D.stack
626+ [ D.toSimpleNote $
627+ "One of the major goals of the package ecosystem is to be completely written\
628+ \ in Elm. This means when you install an Elm package, you can be sure you are safe\
629+ \ from security issues on install and that you are not going to get any runtime\
630+ \ exceptions coming from your new dependency. This design also sets the ecosystem\
631+ \ up to target other platforms more easily (like mobile phones, WebAssembly, etc.)\
632+ \ since no community code explicitly depends on JavaScript even existing."
633+ , D.reflow $
634+ "Given that overall goal, allowing ports in packages would lead to some pretty\
635+ \ surprising behavior. If ports were allowed in packages, you could install a\
636+ \ package but not realize that it brings in an indirect dependency that defines a\
637+ \ port. Now you have a program that does not work and the fix is to realize that\
638+ \ some JavaScript needs to be added for a dependency you did not even know about.\
639+ \ That would be extremely frustrating! \"So why not allow the package author to\
640+ \ include the necessary JS code as well?\" Now we are back in conflict with our\
641+ \ overall goal to keep all community packages free from runtime exceptions."
642+ ]
643+
644+
567645toParseErrorReport :: Code.Source -> Module -> Report.Report
568646toParseErrorReport source modul =
569647 case modul of
@@ -571,64 +649,9 @@ toParseErrorReport source modul =
571649 toSpaceReport source space row col
572650
573651 ModuleBadEnd row col ->
574− case Code.whatIsNext source row col of
575− Code.Keyword keyword ->
576− let
577− region = toKeywordRegion row col keyword
578− in
579− Report.Report "RESERVED WORD" region [] $
580− Code.toSnippet source region Nothing
581− (
582− D.reflow $
583− "I got stuck on this reserved word:"
584− ,
585− D.reflow $
586− "The name `" ++ keyword ++ "` is reserved, so try using a different name?"
587− )
588−
589− Code.Operator op ->
590− let
591− region = toKeywordRegion row col op
592− in
593− Report.Report "UNEXPECTED SYMBOL" region [] $
594− Code.toSnippet source region Nothing
595− (
596− D.reflow $
597− "I ran into an unexpected symbol:"
598− ,
599− D.reflow $
600− "I was not expecting to see a " ++ op ++ " here. Try deleting it? Maybe\
601− \ I can give a better hint from there?"
602− )
603−
604− Code.Close term bracket ->
605− let
606− region = toRegion row col
607− in
608− Report.Report ("UNEXPECTED " ++ map Char.toUpper term) region [] $
609− Code.toSnippet source region Nothing
610− (
611− D.reflow $
612− "I ran into an unexpected " ++ term ++ ":"
613− ,
614− D.reflow $
615− "This " ++ bracket : " does not match up with an earlier open " ++ term ++ ". Try deleting it?"
616− )
617−
618− Code.Other ->
619− let
620− region = toRegion row col
621− in
622− Report.Report "SYNTAX PROBLEM" region [] $
623− Code.toSnippet source region Nothing
624− (
625− D.reflow $
626− "I got stuck here:"
627− ,
628− D.reflow $
629− "Whatever I am running into is confusing me a lot! Normally I can give fairly\
630− \ specific hints, but something is really tripping me up this time."
631− )
652+ if col == 1
653+ then toDeclStartReport source row col
654+ else toWeirdEndReport source row col
632655
633656 ModuleProblem row col ->
634657 let
@@ -774,15 +797,15 @@ toParseErrorReport source modul =
774797 [ D.reflow $
775798 "I am not sure what is going on, but I recommend starting an Elm\
776799 \ file with the following lines:"
777− , D.vcat
800+ , D.indent 4 $ D.vcat $
778801 [ D.fillSep [D.cyan "import","Html"]
779802 , ""
780− , D.fillSep [D.green "main","="]
781− , D.indent 2 $ D.fillSep [D.cyan "Html" <> ".text",D.dullyellow "\"Hello!\""]
803+ , "main ="
804+ , " Html.text " <> D.dullyellow "\"Hello!\""
782805 ]
783806 , D.reflow $
784− "You should be able to copy those lines directly into your file. Check out\
785− \ some of the examples on https://elm-lang.org for more help getting started!"
807+ "You should be able to copy those lines directly into your file. Check out the\
808+ \ examples at <https://elm-lang.org/examples> for more help getting started!"
786809 , D.toSimpleNote $
787810 "This can also happen when something is indented too much!"
788811 ]
@@ -807,11 +830,12 @@ toParseErrorReport source modul =
807830 , D.indent 4 $ D.vcat $
808831 [ D.fillSep [D.cyan "import","Dict"]
809832 , D.fillSep [D.cyan "import","Maybe"]
810− , D.fillSep [D.cyan "import","Html.Attributes"]
811− , D.fillSep [D.cyan "import","Json.Decode"]
833+ , D.fillSep [D.cyan "import","Html.Attributes",D.cyan "as","A"]
834+ , D.fillSep [D.cyan "import","Json.Decode",D.cyan "exposing","(..)"]
812835 ]
813836 , D.reflow $
814837 "Notice that the module names all start with capital letters. That is required!"
838+ , D.reflowLink "Read" "imports" "to learn more."
815839 ]
816840 )
817841
@@ -822,7 +846,7 @@ toParseErrorReport source modul =
822846 let
823847 region = toRegion row col
824848 in
825− Report.Report "EXECTING IMPORT ALIAS" region [] $
849+ Report.Report "EXPECTING IMPORT ALIAS" region [] $
826850 Code.toSnippet source region Nothing
827851 (
828852 D.reflow $
@@ -838,6 +862,7 @@ toParseErrorReport source modul =
838862 ]
839863 , D.reflow $
840864 "Notice that the alias always starts with a capital letter. That is required!"
865+ , D.reflowLink "Read" "imports" "to learn more."
841866 ]
842867 )
843868
@@ -900,6 +925,192 @@ toParseErrorReport source modul =
900925
901926
902927
928+-- WEIRD END
929+
930+
931+toWeirdEndReport :: Code.Source -> Row -> Col -> Report.Report
932+toWeirdEndReport source row col =
933+ case Code.whatIsNext source row col of
934+ Code.Keyword keyword ->
935+ let
936+ region = toKeywordRegion row col keyword
937+ in
938+ Report.Report "RESERVED WORD" region [] $
939+ Code.toSnippet source region Nothing
940+ (
941+ D.reflow $
942+ "I got stuck on this reserved word:"
943+ ,
944+ D.reflow $
945+ "The name `" ++ keyword ++ "` is reserved, so try using a different name?"
946+ )
947+
948+ Code.Operator op ->
949+ let
950+ region = toKeywordRegion row col op
951+ in
952+ Report.Report "UNEXPECTED SYMBOL" region [] $
953+ Code.toSnippet source region Nothing
954+ (
955+ D.reflow $
956+ "I ran into an unexpected symbol:"
957+ ,
958+ D.reflow $
959+ "I was not expecting to see a " ++ op ++ " here. Try deleting it? Maybe\
960+ \ I can give a better hint from there?"
961+ )
962+
963+ Code.Close term bracket ->
964+ let
965+ region = toRegion row col
966+ in
967+ Report.Report ("UNEXPECTED " ++ map Char.toUpper term) region [] $
968+ Code.toSnippet source region Nothing
969+ (
970+ D.reflow $
971+ "I ran into an unexpected " ++ term ++ ":"
972+ ,
973+ D.reflow $
974+ "This " ++ bracket : " does not match up with an earlier open " ++ term ++ ". Try deleting it?"
975+ )
976+
977+ Code.Lower c cs ->
978+ let
979+ region = toKeywordRegion row col (c:cs)
980+ in
981+ Report.Report "UNEXPECTED NAME" region [] $
982+ Code.toSnippet source region Nothing
983+ (
984+ D.reflow $
985+ "I got stuck on this name:"
986+ ,
987+ D.reflow $
988+ "It is confusing me a lot! Normally I can give fairly specific hints, but\
989+ \ something is really tripping me up this time."
990+ )
991+
992+ Code.Upper c cs ->
993+ let
994+ region = toKeywordRegion row col (c:cs)
995+ in
996+ Report.Report "UNEXPECTED NAME" region [] $
997+ Code.toSnippet source region Nothing
998+ (
999+ D.reflow $
1000+ "I got stuck on this name:"
1001+ ,
1002+ D.reflow $
1003+ "It is confusing me a lot! Normally I can give fairly specific hints, but\
1004+ \ something is really tripping me up this time."
1005+ )
1006+
1007+ Code.Other maybeChar ->
1008+ let
1009+ region = toRegion row col
1010+ in
1011+ case maybeChar of
1012+ Just ';' ->
1013+ Report.Report "UNEXPECTED SEMICOLON" region [] $
1014+ Code.toSnippet source region Nothing
1015+ (
1016+ D.reflow $
1017+ "I got stuck on this semicolon:"
1018+ ,
1019+ D.stack
1020+ [ D.reflow $ "Try removing it?"
1021+ , D.toSimpleNote $
1022+ "Some languages require semicolons at the end of each statement. These are\
1023+ \ often called C-like languages, and they usually share a lot of language design\
1024+ \ choices. (E.g. side-effects, for loops, etc.) Elm manages effects with commands\
1025+ \ and subscriptions instead, so there is no special syntax for \"statements\" and\
1026+ \ therefore no need to use semicolons to separate them. I think this will make\
1027+ \ more sense as you work through <https://guide.elm-lang.org> though!"
1028+ ]
1029+ )
1030+
1031+ Just ',' ->
1032+ Report.Report "UNEXPECTED COMMA" region [] $
1033+ Code.toSnippet source region Nothing
1034+ (
1035+ D.reflow $
1036+ "I got stuck on this comma:"
1037+ ,
1038+ D.stack
1039+ [ D.reflow $
1040+ "I do not think I am parsing a list or tuple right now. Try deleting the comma?"
1041+ , D.toSimpleNote $
1042+ "If this is supposed to be part of a list, the problem may be a bit earlier.\
1043+ \ Perhaps the opening [ is missing? Or perhaps some value in the list has an extra\
1044+ \ closing ] that is making me think the list ended earlier? The same kinds of\
1045+ \ things could be going wrong if this is supposed to be a tuple."
1046+ ]
1047+ )
1048+
1049+ Just '`' ->
1050+ Report.Report "UNEXPECTED CHARACTER" region [] $
1051+ Code.toSnippet source region Nothing
1052+ (
1053+ D.reflow $
1054+ "I got stuck on this character:"
1055+ ,
1056+ D.stack
1057+ [ D.reflow $
1058+ "It is not used for anything in Elm syntax. It is used for multi-line strings in\
1059+ \ some languages though, so if you want a string that spans multiple lines, you\
1060+ \ can use Elm's multi-line string syntax like this:"
1061+ , D.dullyellow $ D.indent 4 $ D.vcat $
1062+ [ "\"\"\""
1063+ , "# Multi-line Strings"
1064+ , ""
1065+ , "- start with triple double quotes"
1066+ , "- write whatever you want"
1067+ , "- no need to escape newlines or double quotes"
1068+ , "- end with triple double quotes"
1069+ , "\"\"\""
1070+ ]
1071+ , D.reflow $
1072+ "Otherwise I do not know what is going on! Try removing the character?"
1073+ ]
1074+ )
1075+
1076+ Just '$' ->
1077+ Report.Report "UNEXPECTED SYMBOL" region [] $
1078+ Code.toSnippet source region Nothing
1079+ (
1080+ D.reflow $
1081+ "I got stuck on this dollar sign:"
1082+ ,
1083+ D.reflow $
1084+ "It is not used for anything in Elm syntax. Are you coming from a language where\
1085+ \ dollar signs can be used in variable names? If so, try a name that (1) starts\
1086+ \ with a letter and (2) only contains letters, numbers, and underscores."
1087+ )
1088+
1089+ Just c | elem c ['#','@','!','%','~'] ->
1090+ Report.Report "UNEXPECTED SYMBOL" region [] $
1091+ Code.toSnippet source region Nothing
1092+ (
1093+ D.reflow $
1094+ "I got stuck on this symbol:"
1095+ ,
1096+ D.reflow $
1097+ "It is not used for anything in Elm syntax. Try removing it?"
1098+ )
1099+
1100+ _ ->
1101+ Report.Report "SYNTAX PROBLEM" region [] $
1102+ Code.toSnippet source region Nothing
1103+ (
1104+ D.reflow $
1105+ "I got stuck here:"
1106+ ,
1107+ D.reflow $
1108+ "Whatever I am running into is confusing me a lot! Normally I can give fairly\
1109+ \ specific hints, but something is really tripping me up this time."
1110+ )
1111+
1112+
1113+
9031114-- IMPORTS
9041115
9051116
@@ -925,6 +1136,7 @@ toImportReport source row col =
9251136 ]
9261137 , D.reflow $
9271138 "You are probably trying to import a different module, but try to make it look like one of these examples!"
1139+ , D.reflowLink "Read" "imports" "to learn more."
9281140 ]
9291141 )
9301142
@@ -1231,106 +1443,7 @@ toDeclarationsReport :: Code.Source -> Decl -> Report.Report
12311443toDeclarationsReport source decl =
12321444 case decl of
12331445 DeclStart row col ->
1234− case Code.whatIsNext source row col of
1235− Code.Close term bracket ->
1236− let
1237− region = toRegion row col
1238− in
1239− Report.Report ("STRAY " ++ map Char.toUpper term) region [] $
1240− Code.toSnippet source region Nothing
1241− (
1242− D.reflow $
1243− "I was not expecting to see a " ++ term ++ " here:"
1244− , D.reflow $
1245− "This " ++ bracket : " does not match up with an earlier open " ++ term ++ ". Try deleting it?"
1246− )
1247−
1248− Code.Keyword keyword ->
1249− let
1250− region = toKeywordRegion row col keyword
1251− in
1252− Report.Report "RESERVED WORD" region [] $
1253− Code.toSnippet source region Nothing
1254− (
1255− D.reflow $
1256− "I was not expecting to run into the `" ++ keyword ++ "` keyword here:"
1257− ,
1258− case keyword of
1259− "import" ->
1260− D.reflow $
1261− "It is reserved for declaring imports at the top of your module. If you want\
1262− \ another import, try moving it up top with the other imports. If you want to\
1263− \ define a value or function, try changing the name to something else!"
1264−
1265− "case" ->
1266− D.stack
1267− [ D.reflow $
1268− "It is reserved for writing `case` expressions. Try using a different name?"
1269− , D.toSimpleNote $
1270− "If you are trying to write a `case` expression, it needs to be part of a\
1271− \ definition. So you could write something like this instead:"
1272− , D.vcat $
1273− [ D.indent 0 $ D.fillSep [D.green "getWidth","maybeWidth","="]
1274− , D.indent 2 $ D.fillSep [D.cyan "case","maybeWidth",D.cyan "of"]
1275− , D.indent 4 $ D.fillSep [D.blue "Just","width","->"]
1276− , D.indent 6 $ D.fillSep ["width","+",D.dullyellow "200"]
1277− , ""
1278− , D.indent 4 $ D.fillSep [D.blue "Nothing","->"]
1279− , D.indent 6 $ D.fillSep [D.dullyellow "400"]
1280− ]
1281− , D.reflow $
1282− "This defines a `getWidth` function that we can use elsewhere in our program."
1283− ]
1284−
1285− "if" ->
1286− D.stack
1287− [ D.reflow $
1288− "It is reserved for writing `if` expressions. Try using a different name?"
1289− , D.toSimpleNote $
1290− "If you are trying to write an `if` expression, it needs to be part of a\
1291− \ definition. So you could write something like this instead:"
1292− , D.vcat $
1293− [ D.indent 0 $ D.fillSep [D.green "reviewPowerLevel","powerLevel","="]
1294− , D.indent 2 $ D.fillSep $
1295− [D.cyan "if","powerLevel",">",D.dullyellow "9000"
1296− ,D.cyan "then",D.dullyellow "\"OVER 9000!!!\""
1297− ,D.cyan "else",D.dullyellow "\"not bad\""
1298− ]
1299− ]
1300− , D.reflow $
1301− "This defines a `reviewPowerLevel` function that we can use elsewhere in our program."
1302− ]
1303−
1304− _ ->
1305− D.reflow $
1306− "It is a reserved word. Try changing the name to something else?"
1307− )
1308−
1309− _ ->
1310− let
1311− region = toRegion row col
1312− in
1313− Report.Report "SYNTAX PROBLEM" region [] $
1314− Code.toSnippet source region Nothing
1315− (
1316− D.reflow $
1317− "I was expecting to see a new declaration here:"
1318− ,
1319− D.stack
1320− [ D.reflow $
1321− "I am not sure what is going wrong exactly, but here are a couple valid\
1322− \ declarations for reference:"
1323− , D.vcat
1324− [ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
1325− , D.fillSep [D.green "add","x","y","="]
1326− , D.fillSep [" ","x","+","y"]
1327− ]
1328− , D.fillSep [D.cyan "type",D.green "User","=","Anonymous","|","LoggedIn String"]
1329− , D.reflow $
1330− "Note that all declarations start with lower-case letters in Elm. Capitalization\
1331− \ makes a difference, so be consious of that if you are working from examples!"
1332− ]
1333− )
1446+ toDeclStartReport source row col
13341447
13351448 DeclSpace space row col ->
13361449 toSpaceReport source space row col
@@ -1360,6 +1473,165 @@ toDeclarationsReport source decl =
13601473 )
13611474
13621475
1476+toDeclStartReport :: Code.Source -> Row -> Col -> Report.Report
1477+toDeclStartReport source row col =
1478+ case Code.whatIsNext source row col of
1479+ Code.Close term bracket ->
1480+ let
1481+ region = toRegion row col
1482+ in
1483+ Report.Report ("STRAY " ++ map Char.toUpper term) region [] $
1484+ Code.toSnippet source region Nothing
1485+ (
1486+ D.reflow $
1487+ "I was not expecting to see a " ++ term ++ " here:"
1488+ , D.reflow $
1489+ "This " ++ bracket : " does not match up with an earlier open " ++ term ++ ". Try deleting it?"
1490+ )
1491+
1492+ Code.Keyword keyword ->
1493+ let
1494+ region = toKeywordRegion row col keyword
1495+ in
1496+ Report.Report "RESERVED WORD" region [] $
1497+ Code.toSnippet source region Nothing
1498+ (
1499+ D.reflow $
1500+ "I was not expecting to run into the `" ++ keyword ++ "` keyword here:"
1501+ ,
1502+ case keyword of
1503+ "import" ->
1504+ D.reflow $
1505+ "It is reserved for declaring imports at the top of your module. If you want\
1506+ \ another import, try moving it up top with the other imports. If you want to\
1507+ \ define a value or function, try changing the name to something else!"
1508+
1509+ "case" ->
1510+ D.stack
1511+ [ D.reflow $
1512+ "It is reserved for writing `case` expressions. Try using a different name?"
1513+ , D.toSimpleNote $
1514+ "If you are trying to write a `case` expression, it needs to be part of a\
1515+ \ definition. So you could write something like this instead:"
1516+ , D.indent 4 $ D.vcat $
1517+ [ D.indent 0 $ D.fillSep ["getWidth","maybeWidth","="]
1518+ , D.indent 2 $ D.fillSep [D.cyan "case","maybeWidth",D.cyan "of"]
1519+ , D.indent 4 $ D.fillSep [D.blue "Just","width","->"]
1520+ , D.indent 6 $ D.fillSep ["width","+",D.dullyellow "200"]
1521+ , ""
1522+ , D.indent 4 $ D.fillSep [D.blue "Nothing","->"]
1523+ , D.indent 6 $ D.fillSep [D.dullyellow "400"]
1524+ ]
1525+ , D.reflow $
1526+ "This defines a `getWidth` function that you can use elsewhere in your program."
1527+ ]
1528+
1529+ "if" ->
1530+ D.stack
1531+ [ D.reflow $
1532+ "It is reserved for writing `if` expressions. Try using a different name?"
1533+ , D.toSimpleNote $
1534+ "If you are trying to write an `if` expression, it needs to be part of a\
1535+ \ definition. So you could write something like this instead:"
1536+ , D.indent 4 $ D.vcat $
1537+ [ "greet name ="
1538+ , D.fillSep $
1539+ [" "
1540+ ,D.cyan "if","name","==",D.dullyellow "\"Abraham Lincoln\""
1541+ ,D.cyan "then",D.dullyellow "\"Greetings Mr. President.\""
1542+ ,D.cyan "else",D.dullyellow "\"Hey!\""
1543+ ]
1544+ ]
1545+ , D.reflow $
1546+ "This defines a `reviewPowerLevel` function that you can use elsewhere in your program."
1547+ ]
1548+
1549+ _ ->
1550+ D.reflow $
1551+ "It is a reserved word. Try changing the name to something else?"
1552+ )
1553+
1554+ Code.Upper c cs ->
1555+ let
1556+ region = toRegion row col
1557+ in
1558+ Report.Report "UNEXPECTED CAPITAL LETTER" region [] $
1559+ Code.toSnippet source region Nothing
1560+ (
1561+ D.reflow $
1562+ "Declarations always start with a lower-case letter, so I am getting stuck here:"
1563+ ,
1564+ D.stack
1565+ [ D.fillSep $
1566+ ["Try","a","name","like"
1567+ ,D.green (D.fromChars (Char.toLower c : cs))
1568+ ,"instead?"
1569+ ]
1570+ , D.toSimpleNote $
1571+ "Here are a couple valid declarations for reference:"
1572+ , D.indent 4 $ D.vcat $
1573+ [ "greet : String -> String"
1574+ , "greet name ="
1575+ , " " <> D.dullyellow "\"Hello \"" <> " ++ name ++ " <> D.dullyellow "\"!\""
1576+ , ""
1577+ , D.cyan "type" <> " User = Anonymous | LoggedIn String"
1578+ ]
1579+ , D.reflow $
1580+ "Notice that they always start with a lower-case letter. Capitalization matters!"
1581+ ]
1582+ )
1583+
1584+ Code.Other (Just char) | elem char ['(', '{', '[', '+', '-', '*', '/', '^', '&', '|', '"', '\'', '!', '@', '#', '$', '%'] ->
1585+ let
1586+ region = toRegion row col
1587+ in
1588+ Report.Report "UNEXPECTED SYMBOL" region [] $
1589+ Code.toSnippet source region Nothing
1590+ (
1591+ D.reflow $
1592+ "I am getting stuck because this line starts with the " ++ [char] ++ " symbol:"
1593+ ,
1594+ D.stack
1595+ [ D.reflow $
1596+ "When a line has no spaces at the beginning, I expect it to be a declaration like one of these:"
1597+ , D.indent 4 $ D.vcat $
1598+ [ "greet : String -> String"
1599+ , "greet name ="
1600+ , " " <> D.dullyellow "\"Hello \"" <> " ++ name ++ " <> D.dullyellow "\"!\""
1601+ , ""
1602+ , D.cyan "type" <> " User = Anonymous | LoggedIn String"
1603+ ]
1604+ , D.reflow $
1605+ "If this is not supposed to be a declaration, try adding some spaces before it?"
1606+ ]
1607+ )
1608+
1609+ _ ->
1610+ let
1611+ region = toRegion row col
1612+ in
1613+ Report.Report "WEIRD DECLARATION" region [] $
1614+ Code.toSnippet source region Nothing
1615+ (
1616+ D.reflow $
1617+ "I am trying to parse a declaration, but I am getting stuck here:"
1618+ ,
1619+ D.stack
1620+ [ D.reflow $
1621+ "When a line has no spaces at the beginning, I expect it to be a declaration like one of these:"
1622+ , D.indent 4 $ D.vcat $
1623+ [ "greet : String -> String"
1624+ , "greet name ="
1625+ , " " <> D.dullyellow "\"Hello \"" <> " ++ name ++ " <> D.dullyellow "\"!\""
1626+ , ""
1627+ , D.cyan "type" <> " User = Anonymous | LoggedIn String"
1628+ ]
1629+ , D.reflow $
1630+ "Try to make your declaration look like one of those? Or if this is not\
1631+ \ supposed to be a declaration, try adding some spaces before it?"
1632+ ]
1633+ )
1634+
13631635
13641636-- PORT
13651637
@@ -1486,7 +1758,7 @@ toPortReport source port_ startRow startCol =
14861758 [ D.reflow $
14871759 "I was expecting to see a type next. Here are examples of outgoing and\
14881760 \ incoming ports for reference:"
1489− , D.vcat
1761+ , D.indent 4 $ D.vcat $
14901762 [ D.fillSep [D.cyan "port","send",":","String -> Cmd msg"]
14911763 , D.fillSep [D.cyan "port","receive",":","(String -> msg) -> Sub msg"]
14921764 ]
@@ -1505,7 +1777,7 @@ portNote =
15051777 D.stack
15061778 [ D.toSimpleNote $
15071779 "Here are some example `port` declarations for reference:"
1508− , D.vcat
1780+ , D.indent 4 $ D.vcat $
15091781 [ D.fillSep [D.cyan "port","send",":","String -> Cmd msg"]
15101782 , D.fillSep [D.cyan "port","receive",":","(String -> msg) -> Sub msg"]
15111783 ]
@@ -1635,7 +1907,7 @@ toTypeAliasReport source typeAlias startRow startCol =
16351907 ,
16361908 D.stack
16371909 [ D.reflow $
1638− "I was expecting to see a type variable or an an equals sign next."
1910+ "I was expecting to see a type variable or an equals sign next."
16391911 , typeAliasNote
16401912 ]
16411913 )
@@ -1656,7 +1928,7 @@ toTypeAliasReport source typeAlias startRow startCol =
16561928 ,
16571929 D.stack
16581930 [ D.reflow $
1659− "I was expecting to see a type variable or an an equals sign next."
1931+ "I was expecting to see a type variable or an equals sign next."
16601932 , typeAliasNote
16611933 ]
16621934 )
@@ -1688,8 +1960,8 @@ typeAliasNote =
16881960 [ D.toSimpleNote $
16891961 "Here is an example of a valid `type alias` for reference:"
16901962 , D.vcat $
1691− [ D.indent 0 $ D.fillSep [D.cyan "type",D.cyan "alias",D.green "Person","="]
1692− , D.indent 2 $ D.vcat $
1963+ [ D.indent 4 $ D.fillSep [D.cyan "type",D.cyan "alias","Person","="]
1964+ , D.indent 6 $ D.vcat $
16931965 ["{ name : String"
16941966 ,", age : Int"
16951967 ,", height : Float"
@@ -1763,7 +2035,7 @@ toCustomTypeReport source customType startRow startCol =
17632035 ,
17642036 D.stack
17652037 [ D.reflow $
1766− "I was expecting to see a type variable or an an equals sign next."
2038+ "I was expecting to see a type variable or an equals sign next."
17672039 , customTypeNote
17682040 ]
17692041 )
@@ -1823,7 +2095,7 @@ toCustomTypeReport source customType startRow startCol =
18232095 ,
18242096 D.stack
18252097 [ D.reflow $
1826− "I was expecting to see a type variable or an an equals sign next."
2098+ "I was expecting to see a type variable or an equals sign next."
18272099 , customTypeNote
18282100 ]
18292101 )
@@ -1889,10 +2161,10 @@ customTypeNote =
18892161 [ D.toSimpleNote $
18902162 "Here is an example of a valid `type` declaration for reference:"
18912163 , D.vcat $
1892− [ D.indent 0 $ D.fillSep [D.cyan "type",D.green "Status"]
1893− , D.indent 2 $ D.fillSep ["=","Failure"]
1894− , D.indent 2 $ D.fillSep ["|","Waiting"]
1895− , D.indent 2 $ D.fillSep ["|","Success","String"]
2164+ [ D.indent 4 $ D.fillSep [D.cyan "type","Status"]
2165+ , D.indent 6 $ D.fillSep ["=","Failure"]
2166+ , D.indent 6 $ D.fillSep ["|","Waiting"]
2167+ , D.indent 6 $ D.fillSep ["|","Success","String"]
18962168 ]
18972169 , D.reflow $
18982170 "This defines a new `Status` type with three variants. This could be useful if\
@@ -1923,11 +2195,55 @@ toDeclDefReport source name declDef startRow startCol =
19232195 Report.Report "RESERVED WORD" region [] $
19242196 Code.toSnippet source surroundings (Just region)
19252197 (
1926− D.reflow $
1927− "It looks like you are trying to use `" ++ keyword ++ "` as an argument:"
2198+ D.fillSep
2199+ ["The","name"
2200+ ,"`" <> D.cyan (D.fromChars keyword) <> "`"
2201+ ,"is","reserved","in","Elm,","so","it","cannot"
2202+ ,"be","used","as","an","argument","here:"
2203+ ]
19282204 ,
2205+ D.stack
2206+ [ D.reflow $
2207+ "Try renaming it to something else."
2208+ , case keyword of
2209+ "as" ->
2210+ D.toFancyNote
2211+ ["This","keyword","is","reserved","for","pattern","matches","like"
2212+ ,"((x,y)",D.cyan "as","point)","where","you","want","to","name","a","tuple","and"
2213+ ,"the","values","it","contains."
2214+ ]
2215+
2216+ _ ->
2217+ D.toSimpleNote $
2218+ "The `" ++ keyword ++ "` keyword has a special meaning in Elm, so it can only be used in certain situations."
2219+ ]
2220+ )
2221+
2222+ Code.Operator "->" ->
2223+ let
2224+ surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2225+ region = toWiderRegion row col 2
2226+ in
2227+ Report.Report "MISSING COLON?" region [] $
2228+ Code.toSnippet source surroundings (Just region)
2229+ (
19292230 D.reflow $
1930− "This is a reserved word! Try using some other name?"
2231+ "I was not expecting to see an arrow here:"
2232+ ,
2233+ D.stack
2234+ [ D.fillSep
2235+ ["This","usually","means","a",D.green ":","is","missing","a","bit","earlier","in"
2236+ ,"a","type","annotation.","It","could","be","something","else","though,","so"
2237+ ,"here","is","a","valid","definition","for","reference:"
2238+ ]
2239+ , D.indent 4 $ D.vcat $
2240+ [ "greet : String -> String"
2241+ , "greet name ="
2242+ , " " <> D.dullyellow "\"Hello \"" <> " ++ name ++ " <> D.dullyellow "\"!\""
2243+ ]
2244+ , D.reflow $
2245+ "Try to use that format with your `" ++ Name.toChars name ++ "` definition!"
2246+ ]
19312247 )
19322248
19332249 Code.Operator op ->
@@ -1945,10 +2261,10 @@ toDeclDefReport source name declDef startRow startCol =
19452261 [ D.reflow $
19462262 "I am not sure what is going wrong exactly, so here is a valid\
19472263 \ definition (with an optional type annotation) for reference:"
1948− , D.vcat
1949− [ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
1950− , D.fillSep [D.green "add","x","y","="]
1951− , D.fillSep [" ","x","+","y"]
2264+ , D.indent 4 $ D.vcat $
2265+ [ "greet : String -> String"
2266+ , "greet name ="
2267+ , " " <> D.dullyellow "\"Hello \"" <> " ++ name ++ " <> D.dullyellow "\"!\""
19522268 ]
19532269 , D.reflow $
19542270 "Try to use that format with your `" ++ Name.toChars name ++ "` definition!"
@@ -1970,10 +2286,10 @@ toDeclDefReport source name declDef startRow startCol =
19702286 [ D.reflow $
19712287 "I am not sure what is going wrong exactly, so here is a valid\
19722288 \ definition (with an optional type annotation) for reference:"
1973− , D.vcat
1974− [ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
1975− , D.fillSep [D.green "add","x","y","="]
1976− , D.fillSep [" ","x","+","y"]
2289+ , D.indent 4 $ D.vcat $
2290+ [ "greet : String -> String"
2291+ , "greet name ="
2292+ , " " <> D.dullyellow "\"Hello \"" <> " ++ name ++ " <> D.dullyellow "\"!\""
19772293 ]
19782294 , D.reflow $
19792295 "Try to use that format!"
@@ -2088,10 +2404,10 @@ declDefNote =
20882404 D.stack
20892405 [ D.reflow $
20902406 "Here is a valid definition (with a type annotation) for reference:"
2091− , D.vcat
2092− [ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
2093− , D.fillSep [D.green "add","x","y","="]
2094− , D.fillSep [" ","x","+","y"]
2407+ , D.indent 4 $ D.vcat $
2408+ [ "greet : String -> String"
2409+ , "greet name ="
2410+ , " " <> D.dullyellow "\"Hello \"" <> " ++ name ++ " <> D.dullyellow "\"!\""
20952411 ]
20962412 , D.reflow $
20972413 "The top line (called a \"type annotation\") is optional. You can leave it off\
@@ -2203,25 +2519,40 @@ toExprReport source context expr startRow startCol =
22032519 )
22042520
22052521 OperatorRight op row col ->
2206− let region = toRegion row col in
2522+ let
2523+ surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2524+ region = toRegion row col
2525+ isMath = elem op ["-","+","*","/","^"]
2526+ in
22072527 Report.Report "MISSING EXPRESSION" region [] $
2208− Code.toSnippet source region Nothing
2528+ Code.toSnippet source surroundings (Just region)
22092529 (
22102530 D.reflow $
2211− "I was expecting to see an expression after this " ++ Name.toChars op ++ " operator:"
2531+ "I just saw a " ++ Name.toChars op ++ " "
2532+ ++ (if isMath then "sign" else "operator")
2533+ ++ ", so I am getting stuck here:"
22122534 ,
2213− D.stack
2214− [ D.fillSep $
2215− ["You","can","just","put","anything","for","now,","like"
2216− ,D.dullyellow "42","or",D.dullyellow"\"hello\"" <> "."
2217− ,"Once","there","is","something","there,","I","can","probably"
2218− ,"give","a","more","specific","hint!"
2219− ]
2220− , D.toSimpleNote $
2221− "This can also happen if run into reserved words like `let` or `as` unexpectedly.\
2222− \ Or if I run into operators in unexpected spots. Point is, there are a\
2223− \ couple ways I can get confused and give sort of weird advice!"
2224− ]
2535+ if isMath then
2536+ D.fillSep
2537+ ["I","was","expecting","to","see","an","expression","next."
2538+ ,"Something","like",D.dullyellow "42","or",D.dullyellow "1000"
2539+ ,"that","makes","sense","with","a",D.fromName op,"sign."
2540+ ]
2541+ else if op == "&&" || op == "||" then
2542+ D.fillSep
2543+ ["I","was","expecting","to","see","an","expression","next."
2544+ ,"Something","like",D.dullyellow "True","or",D.dullyellow "False"
2545+ ,"that","makes","sense","with","boolean","logic."
2546+ ]
2547+ else if op == "|>" then
2548+ D.reflow $
2549+ "I was expecting to see a function next."
2550+ else if op == "<|" then
2551+ D.reflow $
2552+ "I was expecting to see an argument next."
2553+ else
2554+ D.reflow $
2555+ "I was expecting to see an expression next."
22252556 )
22262557
22272558 OperatorReserved operator row col ->
@@ -2242,7 +2573,6 @@ toExprReport source context expr startRow startCol =
22422573 InNode NElse r c _ -> (r, c, "an `if` expression")
22432574 InNode NCase r c _ -> (r, c, "a `case` expression")
22442575 InNode NBranch r c _ -> (r, c, "a `case` expression")
2245− -- TODO check if this is actually the best way to get error messages here
22462576
22472577 surroundings = A.Region (A.Position contextRow contextCol) (A.Position row col)
22482578 region = toRegion row col
@@ -2261,7 +2591,7 @@ toExprReport source context expr startRow startCol =
22612591 ,"give","a","more","specific","hint!"
22622592 ]
22632593 , D.toSimpleNote $
2264− "This can also happen if run into reserved words like `let` or `as` unexpectedly.\
2594+ "This can also happen if I run into reserved words like `let` or `as` unexpectedly.\
22652595 \ Or if I run into operators in unexpected spots. Point is, there are a\
22662596 \ couple ways I can get confused and give sort of weird advice!"
22672597 ]
@@ -2407,7 +2737,19 @@ toStringReport source string row col =
24072737 ,"quotes","on","each","end.","Is","the","closing","double"
24082738 ,"quote","missing","in","your","code?"
24092739 ]
2410− , D.link "Note" "Read" "TODO" "if you want a string that spans multiple lines."
2740+ , D.toSimpleNote $
2741+ "For a string that spans multiple lines, you can use the multi-line string\
2742+ \ syntax like this:"
2743+ , D.dullyellow $ D.indent 4 $ D.vcat $
2744+ [ "\"\"\""
2745+ , "# Multi-line Strings"
2746+ , ""
2747+ , "- start with triple double quotes"
2748+ , "- write whatever you want"
2749+ , "- no need to escape newlines or double quotes"
2750+ , "- end with triple double quotes"
2751+ , "\"\"\""
2752+ ]
24112753 ]
24122754 )
24132755
@@ -2423,7 +2765,18 @@ toStringReport source string row col =
24232765 ,
24242766 D.stack
24252767 [ D.reflow "Add a \"\"\" somewhere after this to end the string."
2426− , D.link "Hint" "Read" "TODO" "for more information on strings and multi-line strings."
2768+ , D.toSimpleNote $
2769+ "Here is a valid multi-line string for reference:"
2770+ , D.dullyellow $ D.indent 4 $ D.vcat $
2771+ [ "\"\"\""
2772+ , "# Multi-line Strings"
2773+ , ""
2774+ , "- start with triple double quotes"
2775+ , "- write whatever you want"
2776+ , "- no need to escape newlines or double quotes"
2777+ , "- end with triple double quotes"
2778+ , "\"\"\""
2779+ ]
24272780 ]
24282781 )
24292782
@@ -2656,33 +3009,41 @@ toOperatorReport source context operator row col =
26563009 in
26573010 Report.Report "UNEXPECTED ARROW" region [] $
26583011 Code.toSnippet source region Nothing $
2659− if isWithin NBranch context then
3012+ if isWithin NCase context then
26603013 (
26613014 D.reflow $
2662− "I was not expecting to see an arrow here:"
3015+ "I am parsing a `case` expression right now, but this arrow is confusing me:"
26633016 ,
26643017 D.stack
2665− [
2666− D.reflow $
2667− "I think I am parsing a `case` expression right now, so it makes sense to\
2668− \ see arrows around here. This one is confusing me though!"
2669− ,
2670− D.toSimpleHint $
2671− "I may be getting confused by the indentation. Every pattern in a `case` must be\
2672− \ exactly aligned (with exactly the same amount of indentation) so maybe this arrow\
2673− \ appears after the next `case` pattern (correctly!) but the pattern itself is\
2674− \ indented too far?"
3018+ [ D.reflow "Maybe the `of` keyword is missing on a previous line?"
3019+ , noteForCaseError
26753020 ]
26763021 )
26773022
2678− else
3023+ else if isWithin NBranch context then
26793024 (
26803025 D.reflow $
2681− "I was not expecting an arrow here:"
3026+ "I am parsing a `case` expression right now, but this arrow is confusing me:"
26823027 ,
3028+ D.stack
3029+ [ D.reflow $
3030+ "It makes sense to see arrows around here, so I suspect it is something earlier. Maybe this pattern is indented a bit farther than the previous patterns?"
3031+ , noteForCaseIndentError
3032+ ]
3033+ )
3034+
3035+ else
3036+ (
26833037 D.reflow $
2684− "Arrows should only appear in `case` expressions and anonymous functions. Maybe\
2685− \ you want > or >= instead?"
3038+ "I was partway through parsing an expression when I got stuck on this arrow:"
3039+ ,
3040+ D.stack
3041+ [ "Arrows should only appear in `case` expressions and anonymous functions.\n\
3042+ \Maybe it was supposed to be a > sign instead?"
3043+ , D.toSimpleNote $
3044+ "The syntax for anonymous functions is (\\x -> x + 1) so the arguments all appear\
3045+ \ after the backslash and before the arrow. Maybe a backslash is missing earlier?"
3046+ ]
26863047 )
26873048
26883049 BadEquals ->
@@ -2809,7 +3170,7 @@ toLetReport source context let_ startRow startCol =
28093170 , D.toSimpleNote $
28103171 "This can also happen if you are trying to define another value within the `let` but\
28113172 \ it is not indented enough. Make sure each definition has exactly the same amount of\
2812− \ spaces before it. The should line up exactly!"
3173+ \ spaces before it. They should line up exactly!"
28133174 ]
28143175 )
28153176
@@ -2879,8 +3240,8 @@ toUnfinishLetReport source row col startRow startCol message =
28793240 [ message
28803241 , D.toSimpleNote $
28813242 "Here is an example with a valid `let` expression for reference:"
2882− , D.vcat $
2883− [ D.indent 0 $ D.fillSep [D.green "viewPerson","person","="]
3243+ , D.indent 4 $ D.vcat $
3244+ [ D.indent 0 $ D.fillSep ["viewPerson","person","="]
28843245 , D.indent 2 $ D.fillSep [D.cyan "let"]
28853246 , D.indent 4 $ D.fillSep ["fullName","="]
28863247 , D.indent 6 $ D.fillSep ["person.firstName","++",D.dullyellow "\" \"","++","person.lastName"]
@@ -2957,11 +3318,55 @@ toLetDefReport source name def startRow startCol =
29573318 Report.Report "RESERVED WORD" region [] $
29583319 Code.toSnippet source surroundings (Just region)
29593320 (
2960− D.reflow $
2961− "It looks like you are trying to use `" ++ keyword ++ "` as an argument:"
3321+ D.fillSep
3322+ ["The","name"
3323+ ,"`" <> D.cyan (D.fromChars keyword) <> "`"
3324+ ,"is","reserved","in","Elm,","so","it","cannot"
3325+ ,"be","used","as","an","argument","here:"
3326+ ]
29623327 ,
3328+ D.stack
3329+ [ D.reflow $
3330+ "Try renaming it to something else."
3331+ , case keyword of
3332+ "as" ->
3333+ D.toFancyNote
3334+ ["This","keyword","is","reserved","for","pattern","matches","like"
3335+ ,"((x,y)",D.cyan "as","point)","where","you","want","to","name","a","tuple","and"
3336+ ,"the","values","it","contains."
3337+ ]
3338+
3339+ _ ->
3340+ D.toSimpleNote $
3341+ "The `" ++ keyword ++ "` keyword has a special meaning in Elm, so it can only be used in certain situations."
3342+ ]
3343+ )
3344+
3345+ Code.Operator "->" ->
3346+ let
3347+ surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3348+ region = toWiderRegion row col 2
3349+ in
3350+ Report.Report "MISSING COLON?" region [] $
3351+ Code.toSnippet source surroundings (Just region)
3352+ (
29633353 D.reflow $
2964− "This is a reserved word! Try using some other name?"
3354+ "I was not expecting to see an arrow here:"
3355+ ,
3356+ D.stack
3357+ [ D.fillSep
3358+ ["This","usually","means","a",D.green ":","is","missing","a","bit","earlier","in"
3359+ ,"a","type","annotation.","It","could","be","something","else","though,","so"
3360+ ,"here","is","a","valid","definition","for","reference:"
3361+ ]
3362+ , D.indent 4 $ D.vcat $
3363+ [ "greet : String -> String"
3364+ , "greet name ="
3365+ , " " <> D.dullyellow "\"Hello \"" <> " ++ name ++ " <> D.dullyellow "\"!\""
3366+ ]
3367+ , D.reflow $
3368+ "Try to use that format with your `" ++ Name.toChars name ++ "` definition!"
3369+ ]
29653370 )
29663371
29673372 Code.Operator op ->
@@ -2979,10 +3384,10 @@ toLetDefReport source name def startRow startCol =
29793384 [ D.reflow $
29803385 "I am not sure what is going wrong exactly, so here is a valid\
29813386 \ definition (with an optional type annotation) for reference:"
2982− , D.vcat
2983− [ D.indent 4 $ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
2984− , D.indent 4 $ D.fillSep [D.green "add","x","y","="]
2985− , D.indent 6 $ D.fillSep ["x","+","y"]
3387+ , D.indent 4 $ D.vcat $
3388+ [ "greet : String -> String"
3389+ , "greet name ="
3390+ , " " <> D.dullyellow "\"Hello \"" <> " ++ name ++ " <> D.dullyellow "\"!\""
29863391 ]
29873392 , D.reflow $
29883393 "Try to use that format with your `" ++ Name.toChars name ++ "` definition!"
@@ -3004,10 +3409,10 @@ toLetDefReport source name def startRow startCol =
30043409 [ D.reflow $
30053410 "I am not sure what is going wrong exactly, so here is a valid\
30063411 \ definition (with an optional type annotation) for reference:"
3007− , D.vcat
3008− [ D.indent 4 $ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
3009− , D.indent 4 $ D.fillSep [D.green "add","x","y","="]
3010− , D.indent 4 $ D.fillSep ["x","+","y"]
3412+ , D.indent 4 $ D.vcat $
3413+ [ "greet : String -> String"
3414+ , "greet name ="
3415+ , " " <> D.dullyellow "\"Hello \"" <> " ++ name ++ " <> D.dullyellow "\"!\""
30113416 ]
30123417 , D.reflow $
30133418 "Try to use that format!"
@@ -3097,10 +3502,10 @@ defNote =
30973502 D.stack
30983503 [ D.reflow $
30993504 "Here is a valid definition (with a type annotation) for reference:"
3100− , D.vcat
3101− [ D.indent 4 $ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
3102− , D.indent 4 $ D.fillSep [D.green "add","x","y","="]
3103− , D.indent 6 $ D.fillSep ["x","+","y"]
3505+ , D.indent 4 $ D.vcat $
3506+ [ "greet : String -> String"
3507+ , "greet name ="
3508+ , " " <> D.dullyellow "\"Hello \"" <> " ++ name ++ " <> D.dullyellow "\"!\""
31043509 ]
31053510 , D.reflow $
31063511 "The top line (called a \"type annotation\") is optional. You can leave it off\
@@ -3263,9 +3668,10 @@ toCaseReport source context case_ startRow startCol =
32633668 D.reflow $
32643669 "I am partway through parsing a `case` expression, but I got stuck here:"
32653670 ,
3266− addNoteForCaseIndentError $
3267− D.reflow $
3268− "I was expecting to see an arrow next."
3671+ D.stack
3672+ [ D.reflow "I was expecting to see an arrow next."
3673+ , noteForCaseIndentError
3674+ ]
32693675 )
32703676
32713677 CaseExpr expr row col ->
@@ -3319,28 +3725,33 @@ toUnfinishCaseReport source row col startRow startCol message =
33193725 ,
33203726 D.stack
33213727 [ message
3322− , D.toSimpleNote $
3323− "Here is an example of a valid `case` expression for reference."
3324− , D.vcat $
3325− [ D.indent 4 $ D.fillSep [D.cyan "case","maybeWidth",D.cyan "of"]
3326− , D.indent 6 $ D.fillSep [D.blue "Just","width","->"]
3327− , D.indent 8 $ D.fillSep ["width","+",D.dullyellow "200"]
3328− , ""
3329− , D.indent 6 $ D.fillSep [D.blue "Nothing","->"]
3330− , D.indent 8 $ D.fillSep [D.dullyellow "400"]
3331− ]
3332− , D.reflow $
3333− "Notice the indentation. Each pattern is aligned, and each branch is indented\
3334− \ a bit more than the corresponding pattern. That is important!"
3728+ , noteForCaseError
33353729 ]
33363730 )
33373731
33383732
3339−addNoteForCaseIndentError :: D.Doc -> D.Doc
3340−addNoteForCaseIndentError message =
3341− D.stack $
3342− message
3343− :
3733+noteForCaseError :: D.Doc
3734+noteForCaseError =
3735+ D.stack
3736+ [ D.toSimpleNote $
3737+ "Here is an example of a valid `case` expression for reference."
3738+ , D.vcat $
3739+ [ D.indent 4 $ D.fillSep [D.cyan "case","maybeWidth",D.cyan "of"]
3740+ , D.indent 6 $ D.fillSep [D.blue "Just","width","->"]
3741+ , D.indent 8 $ D.fillSep ["width","+",D.dullyellow "200"]
3742+ , ""
3743+ , D.indent 6 $ D.fillSep [D.blue "Nothing","->"]
3744+ , D.indent 8 $ D.fillSep [D.dullyellow "400"]
3745+ ]
3746+ , D.reflow $
3747+ "Notice the indentation. Each pattern is aligned, and each branch is indented\
3748+ \ a bit more than the corresponding pattern. That is important!"
3749+ ]
3750+
3751+
3752+noteForCaseIndentError :: D.Doc
3753+noteForCaseIndentError =
3754+ D.stack
33443755 [ D.toSimpleNote $
33453756 "Sometimes I get confused by indentation, so try to make your `case` look\
33463757 \ something like this:"
@@ -3353,8 +3764,9 @@ addNoteForCaseIndentError message =
33533764 , D.indent 8 $ D.fillSep [D.dullyellow "400"]
33543765 ]
33553766 , D.reflow $
3356− "Notice the indentation! Each pattern is aligned, and each branch is indented\
3357− \ a bit more than the corresponding pattern. That is important!"
3767+ "Notice the indentation! Patterns are aligned with each other. Same indentation.\
3768+ \ The expressions after each arrow are all indented a bit more than the patterns.\
3769+ \ That is important!"
33583770 ]
33593771
33603772
@@ -3506,23 +3918,43 @@ toIfReport source context if_ startRow startCol =
35063918 )
35073919
35083920 IfIndentElse row col ->
3509− let
3510− surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3511− region = toRegion row col
3512− in
3513− Report.Report "UNFINISHED IF" region [] $
3514− Code.toSnippet source surroundings (Just region)
3515− (
3516− D.reflow $
3517− "I was expecting to see an `else` branch after this:"
3518− ,
3519− D.stack
3520− [ D.reflow $
3521− "I know what to do when the condition is `True`, but not when it is `False`."
3522− , D.fillSep
3523− ["Add","an",D.cyan "else","branch","to","handle","that","scenario!"]
3524− ]
3525− )
3921+ case Code.nextLineStartsWithKeyword "else" source row of
3922+ Just (elseRow, elseCol) ->
3923+ let
3924+ surroundings = A.Region (A.Position startRow startCol) (A.Position elseRow elseCol)
3925+ region = toWiderRegion elseRow elseCol 4
3926+ in
3927+ Report.Report "WEIRD ELSE BRANCH" region [] $
3928+ Code.toSnippet source surroundings (Just region)
3929+ (
3930+ D.reflow $
3931+ "I was partway through an `if` expression when I got stuck here:"
3932+ ,
3933+ D.fillSep $
3934+ ["I","think","this",D.cyan "else","keyword","needs","to","be","indented","more."
3935+ ,"Try","adding","some","spaces","before","it."
3936+ ]
3937+ )
3938+
3939+ Nothing ->
3940+ let
3941+ surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3942+ region = toRegion row col
3943+ in
3944+ Report.Report "UNFINISHED IF" region [] $
3945+ Code.toSnippet source surroundings (Just region)
3946+ (
3947+ D.reflow $
3948+ "I was expecting to see an `else` branch after this:"
3949+ ,
3950+ D.stack
3951+ [ D.fillSep
3952+ ["I","know","what","to","do","when","the","condition","is","True,"
3953+ ,"but","what","happens","when","it","is","False?"
3954+ ,"Add","an",D.cyan "else","branch","to","handle","that","scenario!"
3955+ ]
3956+ ]
3957+ )
35263958
35273959
35283960
@@ -3555,15 +3987,22 @@ toRecordReport source context record startRow startCol =
35553987 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
35563988 region = toRegion row col
35573989 in
3558− Report.Report "UNFINISHED RECORD" region [] $
3990+ Report.Report "PROBLEM IN RECORD" region [] $
35593991 Code.toSnippet source surroundings (Just region)
35603992 (
35613993 D.reflow $
35623994 "I just started parsing a record, but I got stuck here:"
35633995 ,
3564− D.fillSep
3565− ["Records","look","like",D.dullyellow "{ x = 3, y = 4 },"
3566− ,"so","I","was","expecting","to","see","a","field","name","next."
3996+ D.stack
3997+ [ D.fillSep
3998+ ["I","was","expecting","to","see","a","record","field","defined","next,"
3999+ ,"so","I","am","looking","for","a","name","like"
4000+ ,D.dullyellow "userName","or",D.dullyellow "plantHeight" <> "."
4001+ ]
4002+ , D.toSimpleNote $
4003+ "Field names must start with a lower-case letter. After that, you can use\
4004+ \ any sequence of letters, numbers, and underscores."
4005+ , noteForRecordError
35674006 ]
35684007 )
35694008
@@ -3572,7 +4011,7 @@ toRecordReport source context record startRow startCol =
35724011 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
35734012 region = toRegion row col
35744013 in
3575− Report.Report "UNFINISHED RECORD" region [] $
4014+ Report.Report "PROBLEM IN RECORD" region [] $
35764015 Code.toSnippet source surroundings (Just region)
35774016 (
35784017 D.reflow $
@@ -3607,22 +4046,67 @@ toRecordReport source context record startRow startCol =
36074046 \ that is a reserved word. Try using a different name!"
36084047 )
36094048
4049+ Code.Other (Just ',') ->
4050+ let
4051+ surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4052+ region = toRegion row col
4053+ in
4054+ Report.Report "EXTRA COMMA" region [] $
4055+ Code.toSnippet source surroundings (Just region)
4056+ (
4057+ D.reflow $
4058+ "I am partway through parsing a record, but I got stuck here:"
4059+ ,
4060+ D.stack
4061+ [ D.reflow $
4062+ "I am seeing two commas in a row. This is the second one!"
4063+ , D.reflow $
4064+ "Just delete one of the commas and you should be all set!"
4065+ , noteForRecordError
4066+ ]
4067+ )
4068+
4069+ Code.Close _ '}' ->
4070+ let
4071+ surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4072+ region = toRegion row col
4073+ in
4074+ Report.Report "EXTRA COMMA" region [] $
4075+ Code.toSnippet source surroundings (Just region)
4076+ (
4077+ D.reflow $
4078+ "I am partway through parsing a record, but I got stuck here:"
4079+ ,
4080+ D.stack
4081+ [ D.reflow $
4082+ "Trailing commas are not allowed in records. Try deleting the comma that appears\
4083+ \ before this closing curly brace."
4084+ , noteForRecordError
4085+ ]
4086+ )
4087+
36104088 _ ->
36114089 let
36124090 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
36134091 region = toRegion row col
36144092 in
3615− Report.Report "UNFINISHED RECORD" region [] $
4093+ Report.Report "PROBLEM IN RECORD" region [] $
36164094 Code.toSnippet source surroundings (Just region)
36174095 (
36184096 D.reflow $
3619− "I am partway through parsing a record, but I got stuck after that last comma:"
4097+ "I am partway through parsing a record, but I got stuck here:"
36204098 ,
3621− addNoteForRecordError $
3622− D.reflow $
3623− "Trailing commas are not allowed in records, so I was expecting to see another\
3624− \ record field defined next. If you are done defining the record, the fix may\
3625− \ be to delete that last comma?"
4099+ D.stack
4100+ [ D.fillSep
4101+ ["I","was","expecting","to","see","another","record","field","defined","next,"
4102+ ,"so","I","am","looking","for","a","name","like"
4103+ ,D.dullyellow "userName","or",D.dullyellow "plantHeight" <> "."
4104+ ]
4105+ , D.toSimpleNote $
4106+ "Field names must start with a lower-case letter. After that, you can use\
4107+ \ any sequence of letters, numbers, and underscores."
4108+ , noteForRecordError
4109+ ]
36264110 )
36274111
36284112 RecordEquals row col ->
@@ -3630,17 +4114,19 @@ toRecordReport source context record startRow startCol =
36304114 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
36314115 region = toRegion row col
36324116 in
3633− Report.Report "UNFINISHED RECORD" region [] $
4117+ Report.Report "PROBLEM IN RECORD" region [] $
36344118 Code.toSnippet source surroundings (Just region)
36354119 (
36364120 D.reflow $
36374121 "I am partway through parsing a record, but I got stuck here:"
36384122 ,
3639− addNoteForRecordError $
3640− D.fillSep $
3641− ["I","just","saw","a","field","name,","so","I","was","expecting","to","see"
3642− ,"an","equals","sign","next.","So","try","putting","an",D.green "=","sign","here?"
3643− ]
4123+ D.stack
4124+ [ D.fillSep $
4125+ ["I","just","saw","a","field","name,","so","I","was","expecting","to","see"
4126+ ,"an","equals","sign","next.","So","try","putting","an",D.green "=","sign","here?"
4127+ ]
4128+ , noteForRecordError
4129+ ]
36444130 )
36454131
36464132 RecordExpr expr row col ->
@@ -3660,29 +4146,54 @@ toRecordReport source context record startRow startCol =
36604146 D.reflow $
36614147 "I just saw the opening curly brace of a record, but then I got stuck here:"
36624148 ,
3663− addNoteForRecordIndentError $
3664− D.fillSep $
3665− ["I","am","expecting","a","record","like",D.dullyellow "{ x = 3, y = 4 }","here."
3666− ,"Try","defining","some","fields","of","your","own?"
3667− ]
4149+ D.stack
4150+ [ D.fillSep $
4151+ ["I","am","expecting","a","record","like",D.dullyellow "{ x = 3, y = 4 }","here."
4152+ ,"Try","defining","some","fields","of","your","own?"
4153+ ]
4154+ , noteForRecordIndentError
4155+ ]
36684156 )
36694157
36704158 RecordIndentEnd row col ->
3671− let
3672− surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3673− region = toRegion row col
3674− in
3675− Report.Report "UNFINISHED RECORD" region [] $
3676− Code.toSnippet source surroundings (Just region)
3677− (
3678− D.reflow $
3679− "I was expecting to see a closing curly brace next:"
3680− ,
3681− addNoteForRecordIndentError $
3682− D.fillSep $
3683− ["Try","putting","an",D.green "}","and","see","if","that","helps?"
3684− ]
3685− )
4159+ case Code.nextLineStartsWithCloseCurly source row of
4160+ Just (curlyRow, curlyCol) ->
4161+ let
4162+ surroundings = A.Region (A.Position startRow startCol) (A.Position curlyRow curlyCol)
4163+ region = toRegion curlyRow curlyCol
4164+ in
4165+ Report.Report "NEED MORE INDENTATION" region [] $
4166+ Code.toSnippet source surroundings (Just region)
4167+ (
4168+ D.reflow $
4169+ "I was partway through parsing a record, but I got stuck here:"
4170+ ,
4171+ D.stack
4172+ [ D.reflow $
4173+ "I need this curly brace to be indented more. Try adding some spaces before it!"
4174+ , noteForRecordError
4175+ ]
4176+ )
4177+
4178+ Nothing ->
4179+ let
4180+ surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4181+ region = toRegion row col
4182+ in
4183+ Report.Report "UNFINISHED RECORD" region [] $
4184+ Code.toSnippet source surroundings (Just region)
4185+ (
4186+ D.reflow $
4187+ "I was partway through parsing a record, but I got stuck here:"
4188+ ,
4189+ D.stack
4190+ [ D.fillSep $
4191+ ["I","was","expecting","to","see","a","closing","curly","brace","next."
4192+ ,"Try","putting","a",D.green "}","next","and","see","if","that","helps?"
4193+ ]
4194+ , noteForRecordIndentError
4195+ ]
4196+ )
36864197
36874198 RecordIndentField row col ->
36884199 let
@@ -3695,11 +4206,13 @@ toRecordReport source context record startRow startCol =
36954206 D.reflow $
36964207 "I am partway through parsing a record, but I got stuck after that last comma:"
36974208 ,
3698− addNoteForRecordError $
3699− D.reflow $
3700− "Trailing commas are not allowed in records, so the fix may be to\
3701− \ delete that last comma? Or maybe you were in the middle of defining\
3702− \ an additional field?"
4209+ D.stack
4210+ [ D.reflow $
4211+ "Trailing commas are not allowed in records, so the fix may be to\
4212+ \ delete that last comma? Or maybe you were in the middle of defining\
4213+ \ an additional field?"
4214+ , noteForRecordError
4215+ ]
37034216 )
37044217
37054218 RecordIndentEquals row col ->
@@ -3714,10 +4227,12 @@ toRecordReport source context record startRow startCol =
37144227 "I am partway through parsing a record. I just saw a record\
37154228 \ field, so I was expecting to see an equals sign next:"
37164229 ,
3717− addNoteForRecordIndentError $
3718− D.fillSep $
3719− ["Try","putting","an",D.green "=","followed","by","an","expression?"
3720− ]
4230+ D.stack
4231+ [ D.fillSep $
4232+ ["Try","putting","an",D.green "=","followed","by","an","expression?"
4233+ ]
4234+ , noteForRecordIndentError
4235+ ]
37214236 )
37224237
37234238 RecordIndentExpr row col ->
@@ -3731,52 +4246,48 @@ toRecordReport source context record startRow startCol =
37314246 D.reflow $
37324247 "I am partway through parsing a record, and I was expecting to run into an expression next:"
37334248 ,
3734− addNoteForRecordIndentError $
3735− D.fillSep $
3736− ["Try","putting","something","like"
3737− ,D.dullyellow "42","or",D.dullyellow"\"hello\"","for","now?"
3738− ]
4249+ D.stack
4250+ [ D.fillSep $
4251+ ["Try","putting","something","like"
4252+ ,D.dullyellow "42","or",D.dullyellow"\"hello\"","for","now?"
4253+ ]
4254+ , noteForRecordIndentError
4255+ ]
37394256 )
37404257
37414258
3742−addNoteForRecordError :: D.Doc -> D.Doc
3743−addNoteForRecordError normalRecommendation =
4259+noteForRecordError :: D.Doc
4260+noteForRecordError =
37444261 D.stack $
3745− normalRecommendation
3746− :
37474262 [ D.toSimpleNote
37484263 "If you are trying to define a record across multiple lines, I recommend using this format:"
37494264 , D.indent 4 $ D.vcat $
3750− [ "{ name = \"Alice\""
3751− , ", age = 42"
3752− , ", height = 1.75"
4265+ [ "{ name = " <> D.dullyellow "\"Alice\""
4266+ , ", age = " <> D.dullyellow "42"
4267+ , ", height = " <> D.dullyellow "1.75"
37534268 , "}"
37544269 ]
37554270 , D.reflow $
3756− "Notice that each line starts with some indentation. Usually two or four spaces. I\
3757− \ know this style can be jarring for people coming from C-like syntax, but folks generally\
3758− \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
4271+ "Notice that each line starts with some indentation. Usually two or four spaces.\
4272+ \ This is the stylistic convention in the Elm ecosystem."
37594273 ]
37604274
37614275
3762−addNoteForRecordIndentError :: D.Doc -> D.Doc
3763−addNoteForRecordIndentError normalRecommendation =
3764− D.stack $
3765− normalRecommendation
3766− :
4276+noteForRecordIndentError :: D.Doc
4277+noteForRecordIndentError =
4278+ D.stack
37674279 [ D.toSimpleNote
37684280 "I may be confused by indentation. For example, if you are trying to define\
37694281 \ a record across multiple lines, I recommend using this format:"
37704282 , D.indent 4 $ D.vcat $
3771− [ "{ name = \"Alice\""
3772− , ", age = 42"
3773− , ", height = 1.75"
4283+ [ "{ name = " <> D.dullyellow "\"Alice\""
4284+ , ", age = " <> D.dullyellow "42"
4285+ , ", height = " <> D.dullyellow "1.75"
37744286 , "}"
37754287 ]
37764288 , D.reflow $
3777− "Notice that each line starts with some indentation. Usually two or four spaces. I\
3778− \ know this style can be jarring for people coming from C-like syntax, but folks generally\
3779− \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
4289+ "Notice that each line starts with some indentation. Usually two or four spaces.\
4290+ \ This is the stylistic convention in the Elm ecosystem!"
37804291 ]
37814292
37824293
@@ -3965,15 +4476,14 @@ toListReport source context list startRow startCol =
39654476 , D.toSimpleNote
39664477 "I recommend using the following format for lists that span multiple lines:"
39674478 , D.indent 4 $ D.vcat $
3968− [ "[ \"Alice\""
3969− , ", \"Bob\""
3970− , ", \"Chuck\""
4479+ [ "[ " <> D.dullyellow "\"Alice\""
4480+ , ", " <> D.dullyellow "\"Bob\""
4481+ , ", " <> D.dullyellow "\"Chuck\""
39714482 , "]"
39724483 ]
39734484 , D.reflow $
3974− "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
3975− \ This style can be jarring for people coming from C-like syntax, but folks generally\
3976− \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
4485+ "Notice that each line starts with some indentation. Usually two or four spaces.\
4486+ \ This is the stylistic convention in the Elm ecosystem."
39774487 ]
39784488 )
39794489
@@ -4026,15 +4536,14 @@ toListReport source context list startRow startCol =
40264536 "I may be confused by indentation. For example, if you are trying to define\
40274537 \ a list across multiple lines, I recommend using this format:"
40284538 , D.indent 4 $ D.vcat $
4029− [ "[ \"Alice\""
4030− , ", \"Bob\""
4031− , ", \"Chuck\""
4539+ [ "[ " <> D.dullyellow "\"Alice\""
4540+ , ", " <> D.dullyellow "\"Bob\""
4541+ , ", " <> D.dullyellow "\"Chuck\""
40324542 , "]"
40334543 ]
40344544 , D.reflow $
4035− "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
4036− \ This style can be jarring for people coming from C-like syntax, but folks generally\
4037− \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
4545+ "Notice that each line starts with some indentation. Usually two or four spaces.\
4546+ \ This is the stylistic convention in the Elm ecosystem."
40384547 ]
40394548 )
40404549
@@ -4058,15 +4567,14 @@ toListReport source context list startRow startCol =
40584567 "I may be confused by indentation. For example, if you are trying to define\
40594568 \ a list across multiple lines, I recommend using this format:"
40604569 , D.indent 4 $ D.vcat $
4061− [ "[ \"Alice\""
4062− , ", \"Bob\""
4063− , ", \"Chuck\""
4570+ [ "[ " <> D.dullyellow "\"Alice\""
4571+ , ", " <> D.dullyellow "\"Bob\""
4572+ , ", " <> D.dullyellow "\"Chuck\""
40644573 , "]"
40654574 ]
40664575 , D.reflow $
4067− "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
4068− \ This style can be jarring for people coming from C-like syntax, but folks generally\
4069− \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
4576+ "Notice that each line starts with some indentation. Usually two or four spaces.\
4577+ \ This is the stylistic convention in the Elm ecosystem."
40704578 ]
40714579 )
40724580
@@ -4087,15 +4595,14 @@ toListReport source context list startRow startCol =
40874595 , D.toSimpleNote
40884596 "I recommend using the following format for lists that span multiple lines:"
40894597 , D.indent 4 $ D.vcat $
4090− [ "[ \"Alice\""
4091− , ", \"Bob\""
4092− , ", \"Chuck\""
4598+ [ "[ " <> D.dullyellow "\"Alice\""
4599+ , ", " <> D.dullyellow "\"Bob\""
4600+ , ", " <> D.dullyellow "\"Chuck\""
40934601 , "]"
40944602 ]
40954603 , D.reflow $
4096− "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
4097− \ This style can be jarring for people coming from C-like syntax, but folks generally\
4098− \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
4604+ "Notice that each line starts with some indentation. Usually two or four spaces.\
4605+ \ This is the stylistic convention in the Elm ecosystem."
40994606 ]
41004607 )
41014608
@@ -4344,7 +4851,7 @@ toPatternReport source context pattern startRow startCol =
43444851 ,"((" <> D.dullyellow "x" <> "," <> D.dullyellow "y" <> ") " <> D.cyan "as" <> D.dullyellow " point" <> ")"
43454852 ,"so","you","can","refer","to","individual","parts","of","the","tuple","with"
43464853 ,D.dullyellow "x","and",D.dullyellow "y","or","you","refer","to","the","whole"
4347− ,"thing","with",D.dullyellow "point."
4854+ ,"thing","with",D.dullyellow "point" <> "."
43484855 ]
43494856 , D.reflow $
43504857 "So I was expecting to see a variable name after the `as` keyword here. Sometimes\
@@ -4536,7 +5043,7 @@ toPTupleReport source context tuple startRow startCol =
45365043 "I just saw an open parenthesis, but I got stuck here:"
45375044 ,
45385045 D.fillSep
4539− ["I","was","expecting","so","see","a","pattern","next."
5046+ ["I","was","expecting","to","see","a","pattern","next."
45405047 ,"Maybe","it","will","end","up","being","something"
45415048 ,"like",D.dullyellow "(x,y)","or",D.dullyellow "(name, _)" <> "?"
45425049 ]
@@ -4645,7 +5152,7 @@ toPTupleReport source context tuple startRow startCol =
46455152 "I just saw an open parenthesis, but then I got stuck here:"
46465153 ,
46475154 D.fillSep
4648− ["I","was","expecting","so","see","a","pattern","next."
5155+ ["I","was","expecting","to","see","a","pattern","next."
46495156 ,"Maybe","it","will","end","up","being","something"
46505157 ,"like",D.dullyellow "(x,y)","or",D.dullyellow "(name, _)" <> "?"
46515158 ]
@@ -4664,7 +5171,7 @@ toPTupleReport source context tuple startRow startCol =
46645171 ,
46655172 D.stack
46665173 [ D.fillSep
4667− ["I","was","expecting","so","see","a","pattern","next."
5174+ ["I","was","expecting","to","see","a","pattern","next."
46685175 ,"I","am","expecting","the","final","result","to","be","something"
46695176 ,"like",D.dullyellow "(x,y)","or",D.dullyellow "(name, _)" <> "."
46705177 ]
@@ -4968,22 +5475,64 @@ toTRecordReport source context record startRow startCol =
49685475 \ that is a reserved word. Try using a different name!"
49695476 )
49705477
5478+ Code.Other (Just ',') ->
5479+ let
5480+ surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5481+ region = toRegion row col
5482+ in
5483+ Report.Report "EXTRA COMMA" region [] $
5484+ Code.toSnippet source surroundings (Just region)
5485+ (
5486+ D.reflow $
5487+ "I am partway through parsing a record type, but I got stuck here:"
5488+ ,
5489+ D.stack
5490+ [ D.reflow $
5491+ "I am seeing two commas in a row. This is the second one!"
5492+ , D.reflow $
5493+ "Just delete one of the commas and you should be all set!"
5494+ , noteForRecordTypeError
5495+ ]
5496+ )
5497+
5498+ Code.Close _ '}' ->
5499+ let
5500+ surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5501+ region = toRegion row col
5502+ in
5503+ Report.Report "EXTRA COMMA" region [] $
5504+ Code.toSnippet source surroundings (Just region)
5505+ (
5506+ D.reflow $
5507+ "I am partway through parsing a record type, but I got stuck here:"
5508+ ,
5509+ D.stack
5510+ [ D.reflow $
5511+ "Trailing commas are not allowed in record types. Try deleting the comma that\
5512+ \ appears before this closing curly brace."
5513+ , noteForRecordTypeError
5514+ ]
5515+ )
5516+
49715517 _ ->
49725518 let
49735519 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
49745520 region = toRegion row col
49755521 in
4976− Report.Report "UNFINISHED RECORD TYPE" region [] $
5522+ Report.Report "PROBLEM IN RECORD TYPE" region [] $
49775523 Code.toSnippet source surroundings (Just region)
49785524 (
49795525 D.reflow $
4980− "I am partway through parsing a record type, but I got stuck after that last comma:"
5526+ "I am partway through parsing a record type, but I got stuck here:"
49815527 ,
4982− addNoteForRecordTypeError $
4983− D.reflow $
4984− "Trailing commas are not allowed in records, so I was expecting to see another\
4985− \ record field defined next. If you are done defining the record, the fix may\
4986− \ be to delete that last comma?"
5528+ D.stack
5529+ [ D.fillSep
5530+ ["I","was","expecting","to","see","another","record","field","defined","next,"
5531+ ,"so","I","am","looking","for","a","name","like"
5532+ ,D.dullyellow "userName","or",D.dullyellow "plantHeight" <> "."
5533+ ]
5534+ , noteForRecordTypeError
5535+ ]
49875536 )
49885537
49895538 TRecordColon row col ->
@@ -4997,11 +5546,13 @@ toTRecordReport source context record startRow startCol =
49975546 D.reflow $
49985547 "I am partway through parsing a record type, but I got stuck here:"
49995548 ,
5000− addNoteForRecordTypeError $
5001− D.fillSep $
5002− ["I","just","saw","a","field","name,","so","I","was","expecting","to","see"
5003− ,"a","colon","next.","So","try","putting","an",D.green ":","sign","here?"
5004− ]
5549+ D.stack
5550+ [ D.fillSep $
5551+ ["I","just","saw","a","field","name,","so","I","was","expecting","to","see"
5552+ ,"a","colon","next.","So","try","putting","an",D.green ":","sign","here?"
5553+ ]
5554+ , noteForRecordTypeError
5555+ ]
50055556 )
50065557
50075558 TRecordType tipe row col ->
@@ -5021,29 +5572,54 @@ toTRecordReport source context record startRow startCol =
50215572 D.reflow $
50225573 "I just saw the opening curly brace of a record type, but then I got stuck here:"
50235574 ,
5024− addNoteForRecordTypeIndentError $
5025− D.fillSep $
5026− ["I","am","expecting","a","record","like",D.dullyellow "{ name : String, age : Int }","here."
5027− ,"Try","defining","some","fields","of","your","own?"
5028− ]
5575+ D.stack
5576+ [ D.fillSep $
5577+ ["I","am","expecting","a","record","like",D.dullyellow "{ name : String, age : Int }","here."
5578+ ,"Try","defining","some","fields","of","your","own?"
5579+ ]
5580+ , noteForRecordTypeIndentError
5581+ ]
50295582 )
50305583
50315584 TRecordIndentEnd row col ->
5032− let
5033− surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5034− region = toRegion row col
5035− in
5036− Report.Report "UNFINISHED RECORD TYPE" region [] $
5037− Code.toSnippet source surroundings (Just region)
5038− (
5039− D.reflow $
5040− "I was expecting to see a closing curly brace next:"
5041− ,
5042− addNoteForRecordTypeIndentError $
5043− D.fillSep $
5044− ["Try","putting","an",D.green "}","and","see","if","that","helps?"
5045− ]
5046− )
5585+ case Code.nextLineStartsWithCloseCurly source row of
5586+ Just (curlyRow, curlyCol) ->
5587+ let
5588+ surroundings = A.Region (A.Position startRow startCol) (A.Position curlyRow curlyCol)
5589+ region = toRegion curlyRow curlyCol
5590+ in
5591+ Report.Report "NEED MORE INDENTATION" region [] $
5592+ Code.toSnippet source surroundings (Just region)
5593+ (
5594+ D.reflow $
5595+ "I was partway through parsing a record type, but I got stuck here:"
5596+ ,
5597+ D.stack
5598+ [ D.reflow $
5599+ "I need this curly brace to be indented more. Try adding some spaces before it!"
5600+ , noteForRecordTypeError
5601+ ]
5602+ )
5603+
5604+ Nothing ->
5605+ let
5606+ surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5607+ region = toRegion row col
5608+ in
5609+ Report.Report "UNFINISHED RECORD TYPE" region [] $
5610+ Code.toSnippet source surroundings (Just region)
5611+ (
5612+ D.reflow $
5613+ "I was partway through parsing a record type, but I got stuck here:"
5614+ ,
5615+ D.stack
5616+ [ D.fillSep $
5617+ ["I","was","expecting","to","see","a","closing","curly","brace","next."
5618+ ,"Try","putting","a",D.green "}","next","and","see","if","that","helps?"
5619+ ]
5620+ , noteForRecordTypeIndentError
5621+ ]
5622+ )
50475623
50485624 TRecordIndentField row col ->
50495625 let
@@ -5056,11 +5632,13 @@ toTRecordReport source context record startRow startCol =
50565632 D.reflow $
50575633 "I am partway through parsing a record type, but I got stuck after that last comma:"
50585634 ,
5059− addNoteForRecordTypeIndentError $
5060− D.reflow $
5061− "Trailing commas are not allowed in record types, so the fix may be to\
5062− \ delete that last comma? Or maybe you were in the middle of defining\
5063− \ an additional field?"
5635+ D.stack
5636+ [ D.reflow $
5637+ "Trailing commas are not allowed in record types, so the fix may be to\
5638+ \ delete that last comma? Or maybe you were in the middle of defining\
5639+ \ an additional field?"
5640+ , noteForRecordTypeIndentError
5641+ ]
50645642 )
50655643
50665644 TRecordIndentColon row col ->
@@ -5075,10 +5653,12 @@ toTRecordReport source context record startRow startCol =
50755653 "I am partway through parsing a record type. I just saw a record\
50765654 \ field, so I was expecting to see a colon next:"
50775655 ,
5078− addNoteForRecordTypeIndentError $
5079− D.fillSep $
5080− ["Try","putting","an",D.green ":","followed","by","a","type?"
5081− ]
5656+ D.stack
5657+ [ D.fillSep $
5658+ ["Try","putting","an",D.green ":","followed","by","a","type?"
5659+ ]
5660+ , noteForRecordTypeIndentError
5661+ ]
50825662 )
50835663
50845664 TRecordIndentType row col ->
@@ -5092,19 +5672,19 @@ toTRecordReport source context record startRow startCol =
50925672 D.reflow $
50935673 "I am partway through parsing a record type, and I was expecting to run into a type next:"
50945674 ,
5095− addNoteForRecordTypeIndentError $
5096− D.fillSep $
5097− ["Try","putting","something","like"
5098− ,D.dullyellow "Int","or",D.dullyellow "String","for","now?"
5099− ]
5675+ D.stack
5676+ [ D.fillSep $
5677+ ["Try","putting","something","like"
5678+ ,D.dullyellow "Int","or",D.dullyellow "String","for","now?"
5679+ ]
5680+ , noteForRecordTypeIndentError
5681+ ]
51005682 )
51015683
51025684
5103−addNoteForRecordTypeError :: D.Doc -> D.Doc
5104−addNoteForRecordTypeError normalRecommendation =
5685+noteForRecordTypeError :: D.Doc
5686+noteForRecordTypeError =
51055687 D.stack $
5106− normalRecommendation
5107− :
51085688 [ D.toSimpleNote
51095689 "If you are trying to define a record type across multiple lines, I recommend using this format:"
51105690 , D.indent 4 $ D.vcat $
@@ -5114,17 +5694,14 @@ addNoteForRecordTypeError normalRecommendation =
51145694 , "}"
51155695 ]
51165696 , D.reflow $
5117− "Notice that each line starts with some indentation. Usually two or four spaces. I\
5118− \ know this style can be jarring for people coming from C-like syntax, but folks generally\
5119− \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
5697+ "Notice that each line starts with some indentation. Usually two or four spaces.\
5698+ \ This is the stylistic convention in the Elm ecosystem."
51205699 ]
51215700
51225701
5123−addNoteForRecordTypeIndentError :: D.Doc -> D.Doc
5124−addNoteForRecordTypeIndentError normalRecommendation =
5702+noteForRecordTypeIndentError :: D.Doc
5703+noteForRecordTypeIndentError =
51255704 D.stack $
5126− normalRecommendation
5127− :
51285705 [ D.toSimpleNote
51295706 "I may be confused by indentation. For example, if you are trying to define\
51305707 \ a record type across multiple lines, I recommend using this format:"
@@ -5135,9 +5712,8 @@ addNoteForRecordTypeIndentError normalRecommendation =
51355712 , "}"
51365713 ]
51375714 , D.reflow $
5138− "Notice that each line starts with some indentation. Usually two or four spaces. I\
5139− \ know this style can be jarring for people coming from C-like syntax, but folks generally\
5140− \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
5715+ "Notice that each line starts with some indentation. Usually two or four spaces.\
5716+ \ This is the stylistic convention in the Elm ecosystem."
51415717 ]
51425718
51435719
@@ -5189,7 +5765,7 @@ toTTupleReport source context tuple startRow startCol =
51895765 Code.toSnippet source surroundings (Just region)
51905766 (
51915767 D.reflow $
5192− "I was expecting to see a closing parentheses next, but I got stuck here:"
5768+ "I was expecting to see a closing parenthesis next, but I got stuck here:"
51935769 ,
51945770 D.stack
51955771 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps?"]