@@ -10,6 +10,7 @@ module Reporting.Error.Syntax
1010 where
1111
1212import qualified Data.Set as Set
13+import qualified Data.Text as Text
1314import Data.Text (Text)
1415
1516import qualified Reporting.Render.Type as RenderType
@@ -91,15 +92,23 @@ data Theory
9192 | EndOfFile
9293 | FreshLine NextDecl
9394 | BadSpace
94− deriving (Eq, Ord, Show)
95+ deriving (Eq, Ord)
9596
9697
97−data Next = Expr | ElseBranch | Arg | Pattern | Type | Listing | Exposing
98− deriving (Eq, Ord, Show)
98+data Next
99+ = Expr
100+ | AfterOpExpr Text
101+ | ElseBranch
102+ | Arg
103+ | Pattern
104+ | Type
105+ | Listing
106+ | Exposing
107+ deriving (Eq, Ord)
99108
100109
101110data NextDecl = ModuleDecl | DocCommentDecl | ImportDecl | OtherDecl
102− deriving (Eq, Ord, Show)
111+ deriving (Eq, Ord)
103112
104113
105114data Context
@@ -523,31 +532,32 @@ problemToReport problem =
523532 BadOp op context ->
524533 case op of
525534 HasType ->
526− badOp context "the \"has type\" operator (:)"
535+ badOp context "the \"has type\" operator" "(:)"
527536 "type annotations and record types"
528537 "Maybe you want :: instead? Or maybe your indentation is a bit off?"
529538
530539 Equals ->
531− badOp context "an equals sign (=)"
540+ badOp context "an equals sign" "(=)"
532541 "definitions"
533542 "Maybe you want == instead? Or maybe your indentation is a bit off?"
534543
535544 Arrow ->
536545 if isCaseRelated context then
537546 parseReport
538− "I am parsing a case expression, but this arrow (->) is out of place."
547+ "I ran into a stray arrow (->) while parsing this `case` expression."
539548 ( reflowParagraph $
540− "Each branch in a case expression needs to start on the same\
541− \ column, so maybe this branch is indented too much?"
549+ "All branches in a `case` must be indented the exact\
550+ \ same amount, so the patterns are vertically\
551+ \ aligned. Maybe this branch is indented too much?"
542552 )
543553
544554 else
545− badOp context "an arrow (->)"
555+ badOp context "an arrow" "(->)"
546556 "cases expressions and anonymous functions"
547557 "Maybe you want > or >= instead?"
548558
549559 Pipe ->
550− badOp context "a vertical bar (|)"
560+ badOp context "a vertical bar" "(|)"
551561 "type declarations"
552562 "Maybe you want || instead?"
553563
@@ -561,75 +571,85 @@ problemToReport problem =
561571 )
562572
563573 Theories context allTheories ->
564− case Set.toList (Set.fromList allTheories) of
565− [] ->
566− parseReport
567− "Something went wrong when parsing this code."
568− ( reflowParagraph $
569− "I do not have any suggestions though, and I suspect there is some\
570− \ sort of bug. Can you get it down to an <http://sscce.org> and\
571− \ share it at <https://github.com/elm-lang/error-message-catalog/issues>?\
572− \ That way we can figure out how to give better advice!"
573− )
574+ let
575+ starter =
576+ "I got confused while trying to parse "
577+ <> contextToText "your code" "" context
578+ <> "."
579+ in
580+ parseReport starter $
581+ case Set.toList (Set.fromList allTheories) of
582+ [] ->
583+ Help.stack
584+ [ reflowParagraph $
585+ "I do not have any suggestions though!"
586+ , reflowParagraph $
587+ "Can you get it down to a <http://sscce.org> and share it at\
588+ \ <https://github.com/elm-lang/error-message-catalog/issues>?\
589+ \ That way we can figure out how to give better advice!"
590+ ]
574591
575− [theory] ->
576− parseReport
577− "I got confused while trying to parse your code."
578− ( reflowParagraph $
579− contextToText context
580− <> " right now, so I was expecting "
581− <> theoryToText theory
582− )
592+ [theory] ->
593+ reflowParagraph $
594+ "I was expecting to see "
595+ <> addPeriod (theoryToText context theory)
583596
584− theories ->
585− parseReport
586− "I got confused while trying to parse your code."
587− ( Help.vcat $
588− [ reflowParagraph $
589− contextToText context <> ", so I was expecting:"
597+ theories ->
598+ Help.vcat $
599+ [ text "I was expecting:"
590600 , text ""
591601 ]
592− ++ map (bullet . theoryToText) theories
593− )
602+ ++ map (bullet . theoryToText context) theories
594603
595604
596605bullet :: Text -> Help.Doc
597606bullet point =
598− Help.indent 2 (reflowParagraph point)
607+ Help.hang 4 (" - " <> reflowParagraph point)
608+
599609
610+addPeriod :: Text -> Text
611+addPeriod msg =
612+ if Text.last msg `elem` ['`', ')', '.', '!', '?'] then
613+ msg
614+ else
615+ msg <> "."
600616
601−badOp :: [Context] -> Text -> Text -> Text -> Report.Report
602−badOp context opName setting hint =
617+
618+badOp :: [Context] -> Text -> Text -> Text -> Text -> Report.Report
619+badOp context opName op setting hint =
603620 parseReport ("I was not expecting " <> opName <> " here.") $
604− reflowParagraph $
605− "It should only appear in " <> setting <> ", but "
606− <> contextToText context <> ". " <> hint
621+ Help.stack
622+ [ reflowParagraph $
623+ "A " <> op <> " should only appear in " <> setting
624+ <> contextToText "" ", but I think I am parsing " context <> "."
625+ , reflowParagraph hint
626+ ]
607627
608628
609−contextToText :: [Context] -> Text
610−contextToText contextStack =
629+contextToText :: Text -> Text -> [Context] -> Text
630+contextToText defaultText prefixText contextStack =
611631 case contextStack of
612632 [] ->
613− "I am in between top-level declarations right now."
633+ defaultText
614634
615635 context : rest ->
616636 let anchor = getAnchor rest in
617− "I think I am parsing " <>
637+ prefixText <>
618638 case context of
619639 ExprIf -> "an `if`" <> anchor
620640 ExprLet -> "a `let`" <> anchor
621641 ExprFunc -> "an anonymous function" <> anchor
622642 ExprCase -> "a `case`" <> anchor
623643 ExprList -> "a list" <> anchor
624− ExprTuple -> "a tuple" <> anchor
644+ ExprTuple -> "a expression (in parentheses)" <> anchor
625645 ExprRecord -> "a record" <> anchor
626− Definition name -> "the definition of `" <> name <> "`"
627− Annotation name -> "the type annotation for `" <> name <> "`"
628− TypeTuple -> "a tuple type" <> anchor
646+ Definition name -> name <> "'s definition"
647+ Annotation name -> name <> "'s type annotation"
648+ TypeTuple -> "a type (in parentheses)" <> anchor
629649 TypeRecord -> "a record type" <> anchor
630− PatternList -> "a pattern" <> anchor
631− PatternTuple -> "a pattern" <> anchor
632− PatternRecord -> "a pattern" <> anchor
650+ PatternList -> "a list pattern" <> anchor
651+ PatternTuple -> "a pattern (in parentheses)" <> anchor
652+ PatternRecord -> "a record pattern" <> anchor
633653 Module -> "a module declaration"
634654 Import -> "an import"
635655 DocComment -> "a documentation comment"
@@ -643,8 +663,8 @@ getAnchor :: [Context] -> Text
643663getAnchor context =
644664 case context of
645665 [] -> ""
646− Definition name : _ -> " in the definition of `" <> name <> "`"
647− Annotation name : _ -> " in the type annotation for `" <> name <> "`"
666+ Definition name : _ -> " in " <> name <> "'s definition"
667+ Annotation name : _ -> " in " <> name <> "'s type annotation"
648668 _ : rest -> getAnchor rest
649669
650670
@@ -656,20 +676,20 @@ isCaseRelated context =
656676 _ : rest -> isCaseRelated rest
657677
658678
659−theoryToText :: Theory -> Text
660−theoryToText theory =
679+theoryToText :: [Context] -> Theory -> Text
680+theoryToText context theory =
661681 case theory of
662682 Keyword keyword ->
663683 "the `" <> keyword <> "` keyword"
664684
665685 Symbol symbol ->
666686 case symbol of
667− "=" -> "an equals sign (=)"
687+ "=" -> equalsTheory context
668688 "->" -> "an arrow (->) followed by an expression"
669689 ":" -> "the \"has type\" symbol (:) followed by a type"
670690 "," -> "a comma"
671− "|" -> "a vertical bar (|)"
672− "::" -> "the cons operator (::)"
691+ "|" -> barTheory context
692+ "::" -> "the cons operator (::) followed by more list elements"
673693 "." -> "a dot (.)"
674694 "-" -> "a minus sign (-)"
675695 "_" -> "an underscore"
@@ -688,7 +708,7 @@ theoryToText theory =
688708 "an upper-case variable, like `Maybe` or `Just`"
689709
690710 InfixOp ->
691− "an infix operator, like + or =="
711+ "an infix operator, like (+) or (==)"
692712
693713 Digit ->
694714 "a digit from 0 to 9"
@@ -697,10 +717,10 @@ theoryToText theory =
697717 "the end of the file"
698718
699719 BadSpace ->
700− "more indentation"
720+ badSpace context
701721
702722 FreshLine nextDecl ->
703− "a fresh line with no indentation for " <>
723+ "a fresh line (without any leading spaces) for " <>
704724 case nextDecl of
705725 ModuleDecl -> "an `import`"
706726 DocCommentDecl -> "an `import`"
@@ -710,9 +730,75 @@ theoryToText theory =
710730 Expecting next ->
711731 case next of
712732 Expr -> "an expression, like x or 42"
713− ElseBranch -> "an `else` branch. An `if` must handle both possibilities!"
733+ AfterOpExpr op -> "an expression after that (" <> op <> ") operator, like x or 42"
734+ ElseBranch -> "an `else` branch. An `if` must handle both possibilities."
714735 Arg -> "an argument, like `name` or `total`"
715736 Pattern -> "a pattern, like `name` or (Just x)"
716737 Type -> "a type, like Int or (List String)"
717738 Listing -> "a list of exposed values and types, like (..) or (x,y,z)"
718739 Exposing -> "something like `exposing (..)`"
740+
741+
742+equalsTheory :: [Context] -> Text
743+equalsTheory context =
744+ case context of
745+ [] ->
746+ "an equals sign (=)"
747+
748+ first : rest ->
749+ case first of
750+ ExprRecord -> "an equals sign (=) followed by an expression"
751+ Definition name -> "an equals sign (=) followed by " <> name <> "'s definition"
752+ TypeUnion -> "an equals sign (=) followed by the first union type constructor"
753+ TypeAlias -> "an equals sign (=) followed by the aliased type"
754+ _ -> equalsTheory rest
755+
756+
757+barTheory :: [Context] -> Text
758+barTheory context =
759+ case context of
760+ [] ->
761+ "a vertical bar (|)"
762+
763+ first : rest ->
764+ case first of
765+ ExprRecord -> "a vertical bar (|) followed by the record fields you want to update"
766+ TypeRecord -> "a vertical bar (|) followed by some record field types"
767+ TypeUnion -> "a vertical bar (|) followed by more union type constructors"
768+ _ -> barTheory rest
769+
770+
771+badSpace :: [Context] -> Text
772+badSpace context =
773+ case context of
774+ [] ->
775+ "more indentation? I was not done with that last thing yet."
776+
777+ first : rest ->
778+ case first of
779+ ExprIf -> "the end of that `if`" <> badSpaceEnd
780+ ExprLet -> "the end of that `let`" <> badSpaceEnd
781+ ExprFunc -> badSpace rest
782+ ExprCase -> "more of that `case`" <> badSpaceEnd
783+ ExprList -> "the end of that list" <> badSpaceEnd
784+ ExprTuple -> "a closing paren" <> badSpaceEnd
785+ ExprRecord -> "the end of that record" <> badSpaceEnd
786+ Definition name -> "the rest of " <> name <> "'s definition" <> badSpaceEnd
787+ Annotation name -> "the rest of " <> name <> "'s type annotation" <> badSpaceEnd
788+ TypeTuple -> "a closing paren" <> badSpaceEnd
789+ TypeRecord -> "the end of that record" <> badSpaceEnd
790+ PatternList -> "the end of that list" <> badSpaceEnd
791+ PatternTuple -> "a closing paren" <> badSpaceEnd
792+ PatternRecord -> "the end of that record" <> badSpaceEnd
793+ Module -> "something like `module Main exposing (..)`"
794+ Import -> "something like `import Html exposing (..)`"
795+ DocComment -> badSpace rest
796+ TypeUnion -> "more of that union type" <> badSpaceEnd
797+ TypeAlias -> "more of that type alias" <> badSpaceEnd
798+ Infix -> "more of that infix declaration" <> badSpaceEnd
799+ Port -> "more of that port declaration" <> badSpaceEnd
800+
801+
802+badSpaceEnd :: Text
803+badSpaceEnd =
804+ ". Maybe you forgot some code? Or you need more indentation?"