@@ -10,11 +10,11 @@ module Reporting.Error.Type
13−import Control.Arrow (first, second)
13+import Control.Arrow (second)
14import qualified Data.Map as Map
14import qualified Data.Map as Map
15−import qualified Data.Maybe as Maybe
16import qualified Data.Text as Text
15import qualified Data.Text as Text
17import Data.Text (Text)
16import Data.Text (Text)
17+import Data.Monoid ((<>))
19import qualified AST.Helpers as Help
19import qualified AST.Helpers as Help
20import qualified AST.Type as Type
20import qualified AST.Type as Type
@@ -24,8 +24,8 @@ import qualified Reporting.Render.Type as RenderType
24import qualified Reporting.Report as Report
24import qualified Reporting.Report as Report
25import qualified Reporting.Helpers as Help
25import qualified Reporting.Helpers as Help
26import Reporting.Helpers
26import Reporting.Helpers
27− ( Doc, (<>), (<+>), capitalize, dullyellow, functionName
27+ ( Doc, (<+>), capitalize, dullyellow, functionName, i2t
28− , i2t, indent, ordinalize, reflowParagraph, stack, text, toHint, vcat
28+ , indent, ordinalize, reflowParagraph, stack, text
@@ -34,30 +34,32 @@ import Reporting.Helpers
37− = Mismatch Mismatch
37+ = Mismatch Mismatch
38− | BadMain Type.Canonical
38+ | BadMain Type.Canonical
39− | BadFlags Type.Canonical (Maybe Text)
39+ | BadFlags Type.Canonical (Maybe Text)
40− | InfiniteType (Either Hint Text) Type.Canonical
40+ | InfiniteType (Either Hint Text) Type.Canonical
43−data Mismatch = MismatchInfo
43+data Mismatch =
44 { _hint :: Hint
45 { _hint :: Hint
45 , _leftType :: Type.Canonical
46 , _leftType :: Type.Canonical
46 , _rightType :: Type.Canonical
47 , _rightType :: Type.Canonical
47 , _reason :: Maybe Reason
49 , _reason :: Maybe Reason
51data Reason
53data Reason
52− = BadFields [(Text, Maybe Reason)]
54+ = BadFields [(Text, Maybe Reason)]
53− | MessyFields [Text] [Text] [Text]
55+ | MessyFields [Text] [Text] [Text]
54− | IntFloat
56+ | IntFloat
55− | TooLongComparableTuple Int
57+ | TooLongComparableTuple Int
56− | MissingArgs Int
58+ | MissingArgs Int
57− | RigidClash Text Text
59+ | RigidClash Text Text
58− | NotPartOfSuper Type.Super
60+ | NotPartOfSuper Type.Super
59− | RigidVarTooGeneric Text SpecificThing
61+ | RigidVarTooGeneric Text SpecificThing
60− | RigidSuperTooGeneric Type.Super Text SpecificThing
62+ | RigidSuperTooGeneric Type.Super Text SpecificThing
63data SpecificThing
65data SpecificThing
@@ -68,39 +70,39 @@ data SpecificThing
71− = CaseBranch Int Region.Region
73+ = CaseBranch Int Region.Region
73− | IfCondition
75+ | IfCondition
74− | IfBranches
76+ | IfBranches
75− | MultiIfBranch Int Region.Region
77+ | MultiIfBranch Int Region.Region
78− | ListElement Int Region.Region
80+ | ListElement Int Region.Region
79− | BinopLeft Var.Canonical Region.Region
81+ | BinopLeft Var.Canonical Region.Region
80− | BinopRight Var.Canonical Region.Region
82+ | BinopRight Var.Canonical Region.Region
81− | Binop Var.Canonical
83+ | Binop Var.Canonical
82− | Function (Maybe Var.Canonical)
84+ | Function (Maybe Var.Canonical)
83− | UnexpectedArg (Maybe Var.Canonical) Int Int Region.Region
85+ | UnexpectedArg (Maybe Var.Canonical) Int Int Region.Region
84− | FunctionArity (Maybe Var.Canonical) Int Int Region.Region
86+ | FunctionArity (Maybe Var.Canonical) Int Int Region.Region
85− | ReturnType Text Int Int Region.Region
87+ | ReturnType Text Int Int Region.Region
86− | Instance Text
88+ | Instance Text
87− | Literal Text
89+ | Literal Text
88− | Pattern Pattern
90+ | Pattern Pattern
91− | Access (Maybe Text) Text
93+ | Access (Maybe Text) Text
93− -- effect manager problems
95+ -- effect manager problems
94− | Manager Text
96+ | Manager Text
95− | State Text
97+ | State Text
96− | SelfMsg
98+ | SelfMsg
99data Pattern
101data Pattern
100− = PVar Text
102+ = PVar Text
101− | PAlias Text
103+ | PAlias Text
102− | PCtor Var.Canonical
104+ | PCtor Var.Canonical
103− | PRecord
105+ | PRecord
@@ -155,17 +157,18 @@ toReport localizer err =
157mismatchToReport :: RenderType.Localizer -> Mismatch -> Report.Report
159mismatchToReport :: RenderType.Localizer -> Mismatch -> Report.Report
158−mismatchToReport localizer (MismatchInfo hint leftType rightType maybeReason) =
160+mismatchToReport localizer (MismatchInfo hint leftType rightType decoders maybeReason) =
161 Report.report "TYPE MISMATCH"
163 Report.report "TYPE MISMATCH"
163 typicalHints =
165 typicalHints =
164− Maybe.maybeToList (reasonToString =<< maybeReason)
166+ maybe id (:) (reasonToDoc <$> maybeReason) $
167+ if decoders then [ jsonDecoderHint ] else []
166 cmpHint leftWords rightWords extraHints =
169 cmpHint leftWords rightWords extraHints =
167 comparisonHint localizer leftType rightType leftWords rightWords
170 comparisonHint localizer leftType rightType leftWords rightWords
168− (typicalHints <> map toHint extraHints)
171+ (typicalHints <> map Help.toSimpleHint extraHints)
170 case hint of
173 case hint of
171 CaseBranch branchNumber region ->
174 CaseBranch branchNumber region ->
@@ -548,6 +551,8 @@ mismatchToReport localizer (MismatchInfo hint leftType rightType maybeReason) =
552comparisonHint
557comparisonHint
553 :: RenderType.Localizer
558 :: RenderType.Localizer
@@ -573,6 +578,17 @@ comparisonHint localizer leftType rightType leftWords rightWords finalHints =
584+jsonDecoderHint :: Doc
587+ "New to JSON decoders? They are tough at first, so DEFINITELY learn more here: "
588+ <> Help.hintLink "json-decoders"
576-- BINOP HINTS
592-- BINOP HINTS
@@ -709,62 +725,64 @@ flipReason reason =
709 RigidSuperTooGeneric super name specific
725 RigidSuperTooGeneric super name specific
712−reasonToString :: Reason -> Maybe Doc
728+reasonToDoc :: Reason -> Doc
713−reasonToString reason =
729+reasonToDoc reason =
715− (fields, maybeDeepReason) =
716− collectFields reason
730+ case collectFields reason of
719− reasonToStringHelp =<< maybeDeepReason
733+ (firstLine, details) =
720−
734+ reasonToDocHelp reason
722− case fields of
736+ Help.vcat $ Help.toSimpleHint firstLine : map (indent 4) details
726− [field] ->
738+ Just (fields, maybeDeepReason) ->
740+ recordHint elaboration =
727− Just $ "Problem in the `" <> field <> "` field. "
741+ [ "Problem", "in", "the", dullyellow (text (Text.intercalate "." fields)) <> "field." ]
743+ map text (Text.words elaboration)
745+ case reasonToDocHelp <$> maybeDeepReason of
747+ Help.toFancyHint (recordHint badFieldElaboration)
729− _ ->
749+ Just (firstLine, details) ->
730− Just $ "Problem at `" <> Text.intercalate "." fields <> "`. "
750+ Help.vcat $ Help.toFancyHint (recordHint firstLine) : map (indent 4) details
732− case (starter, maybeDocs) of
733− (Nothing, Nothing) ->
736− (Just msg, Nothing) ->
737− Just $ toHint (msg <> badFieldElaboration)
739− (_, Just (firstLine, docs)) ->
741− toHint (maybe firstLine (<> firstLine) starter)
742− : map (indent 4) docs
746−collectFields :: Reason -> ([Text], Maybe Reason)
757+collectFields :: Reason -> Maybe ([Text], Maybe Reason)
747collectFields reason =
758collectFields reason =
748 case reason of
759 case reason of
749− BadFields [(field, Nothing)] ->
760+ BadFields [(field, maybeReason)] ->
761+ Just (collectFieldsHelp [field] maybeReason)
750− ([field], Nothing)
764+ Nothing
767+collectFieldsHelp :: [Text] -> Maybe Reason -> ([Text], Maybe Reason)
768+collectFieldsHelp revFields maybeReason =
752− BadFields [(field, Just subReason)] ->
770+ Just (BadFields [(field, deeperReason)]) ->
753− first (field:) (collectFields subReason)
771+ collectFieldsHelp (field : revFields) deeperReason
756− ([], Just reason)
774+ ( reverse revFields, maybeReason )
759−reasonToStringHelp :: Reason -> Maybe (Text, [Doc])
777+reasonToDocHelp :: Reason -> (Text, [Doc])
760−reasonToStringHelp reason =
778+reasonToDocHelp reason =
762− go msg =
780+ simpleDoc msg =
763− Just (msg, [])
781+ ( msg, [] )
765 case reason of
783 case reason of
766 BadFields fields ->
784 BadFields fields ->
767− go $
785+ simpleDoc $
768 "I am seeing issues with the "
786 "I am seeing issues with the "
769 <> Help.commaSep (map fst fields) <> " fields. "
787 <> Help.commaSep (map fst fields) <> " fields. "
770 <> badFieldElaboration
788 <> badFieldElaboration
@@ -773,22 +791,22 @@ reasonToStringHelp reason =
773 messyFieldsHelp both leftOnly rightOnly
791 messyFieldsHelp both leftOnly rightOnly
775 IntFloat ->
793 IntFloat ->
776− go $
794+ simpleDoc $
777 "Elm does not automatically convert between Ints and Floats. Use\
795 "Elm does not automatically convert between Ints and Floats. Use\
778 \ `toFloat` and `round` to do specific conversions.\
796 \ `toFloat` and `round` to do specific conversions.\
779 \ <http://package.elm-lang.org/packages/elm-lang/core/latest/Basics#toFloat>"
797 \ <http://package.elm-lang.org/packages/elm-lang/core/latest/Basics#toFloat>"
781 TooLongComparableTuple len ->
799 TooLongComparableTuple len ->
782− go $
800+ simpleDoc $
783 "Although tuples are comparable, this is currently only supported\
801 "Although tuples are comparable, this is currently only supported\
784 \ for tuples with 6 or fewer entries, not " <> i2t len <> "."
802 \ for tuples with 6 or fewer entries, not " <> i2t len <> "."
786 MissingArgs num ->
804 MissingArgs num ->
787− go $
805+ simpleDoc $
788 "It looks like a function needs " <> Help.moreArgs num <> "."
806 "It looks like a function needs " <> Help.moreArgs num <> "."
790 RigidClash name1 name2 ->
808 RigidClash name1 name2 ->
791− go $
809+ simpleDoc $
792 "Your type annotation uses `" <> name1 <> "` and `" <> name2 <>
810 "Your type annotation uses `" <> name1 <> "` and `" <> name2 <>
793 "` as DIFFERENT type variables. By using separate names, you are\
811 "` as DIFFERENT type variables. By using separate names, you are\
794 \ claiming the values can be different, but the code suggests that\
812 \ claiming the values can be different, but the code suggests that\
@@ -798,31 +816,31 @@ reasonToStringHelp reason =
798 <> Help.hintLink "type-annotations"
816 <> Help.hintLink "type-annotations"
800 NotPartOfSuper Type.Number ->
818 NotPartOfSuper Type.Number ->
801− go "Only ints and floats are numbers."
819+ simpleDoc "Only ints and floats are numbers."
803 NotPartOfSuper Type.Comparable ->
821 NotPartOfSuper Type.Comparable ->
804− go "Only ints, floats, chars, strings, lists, and tuples are comparable."
822+ simpleDoc "Only ints, floats, chars, strings, lists, and tuples are comparable."
806 NotPartOfSuper Type.Appendable ->
824 NotPartOfSuper Type.Appendable ->
807− go "Only strings and lists are appendable."
825+ simpleDoc "Only strings and lists are appendable."
809 NotPartOfSuper Type.CompAppend ->
827 NotPartOfSuper Type.CompAppend ->
810− go "Only strings and lists are both comparable and appendable."
828+ simpleDoc "Only strings and lists are both comparable and appendable."
812 RigidVarTooGeneric name specific ->
830 RigidVarTooGeneric name specific ->
813− go $ rigidTooGenericHelp "ANY type of value" name specific
831+ simpleDoc $ rigidTooGenericHelp "ANY type of value" name specific
815 RigidSuperTooGeneric Type.Number name specific ->
833 RigidSuperTooGeneric Type.Number name specific ->
816− go $ rigidTooGenericHelp "BOTH Ints and Floats" name specific
834+ simpleDoc $ rigidTooGenericHelp "BOTH Ints and Floats" name specific
818 RigidSuperTooGeneric Type.Comparable name specific ->
836 RigidSuperTooGeneric Type.Comparable name specific ->
819− go $ rigidTooGenericHelp "ANY comparable value" name specific
837+ simpleDoc $ rigidTooGenericHelp "ANY comparable value" name specific
821 RigidSuperTooGeneric Type.Appendable name specific ->
839 RigidSuperTooGeneric Type.Appendable name specific ->
822− go $ rigidTooGenericHelp "BOTH Strings and Lists" name specific
840+ simpleDoc $ rigidTooGenericHelp "BOTH Strings and Lists" name specific
824 RigidSuperTooGeneric Type.CompAppend name specific ->
842 RigidSuperTooGeneric Type.CompAppend name specific ->
825− go $ rigidTooGenericHelp "Strings and ANY comparable List" name specific
843+ simpleDoc $ rigidTooGenericHelp "Strings and ANY comparable List" name specific
828rigidTooGenericHelp :: Text -> Text -> SpecificThing -> Text
846rigidTooGenericHelp :: Text -> Text -> SpecificThing -> Text
@@ -869,11 +887,11 @@ specificThingToText specific =
869badFieldElaboration :: Text
887badFieldElaboration :: Text
870badFieldElaboration =
888badFieldElaboration =
871 "I always figure out field types in alphabetical order. If a field\
889 "I always figure out field types in alphabetical order. If a field\
872− \ seems fine, I assume it is \"correct\" in subsequent checks.\
890+ \ seems fine, I assume it is “correct” in subsequent checks.\
873 \ So the problem may actually be a weird interaction with previous fields."
891 \ So the problem may actually be a weird interaction with previous fields."
876−messyFieldsHelp :: [Text] -> [Text] -> [Text] -> Maybe (Text, [Doc])
894+messyFieldsHelp :: [Text] -> [Text] -> [Text] -> (Text, [Doc])
877messyFieldsHelp both leftOnly rightOnly =
895messyFieldsHelp both leftOnly rightOnly =
878 case (leftOnly, rightOnly) of
896 case (leftOnly, rightOnly) of
879 ([], [missingField]) ->
897 ([], [missingField]) ->
@@ -899,62 +917,55 @@ messyFieldsHelp both leftOnly rightOnly =
901 if null typoPairs then
919 if null typoPairs then
903− ( "The record fields do not match up. One has "
920+ ( "The record fields do not match up. One has "
904− <> Help.commaSep leftOnly <> ". The other has "
921+ <> Help.commaSep leftOnly <> ". The other has "
905− <> Help.commaSep rightOnly <> "."
922+ <> Help.commaSep rightOnly <> "."
911− ( "The record fields do not match up. Maybe you made one of these typos?"
927+ ( "The record fields do not match up. Maybe you made one of these typos?"
912− , typoDocs "<->" typoPairs
928+ , typoDocs "<->" typoPairs
916−oneMissingField :: [Text] -> Text -> Maybe (Text, [Doc])
932+oneMissingField :: [Text] -> Text -> ( Text, [Doc] )
917oneMissingField knownFields missingField =
933oneMissingField knownFields missingField =
918 case Help.findPotentialTypos knownFields missingField of
934 case Help.findPotentialTypos knownFields missingField of
921− ( "Looks like a record is missing the `" <> missingField <> "` field."
936+ ( "Looks like a record is missing the `" <> missingField <> "` field."
925 [typo] ->
940 [typo] ->
927− ( "Looks like a record is missing the `" <> missingField
941+ ( "Looks like a record is missing the `" <> missingField
928− <> "` field. Maybe it is a typo?"
942+ <> "` field. Maybe it is a typo?"
929− , typoDocs "->" [(missingField, typo)]
943+ , typoDocs "->" [(missingField, typo)]
934− ( "Looks like a record is missing the `" <> missingField
947+ ( "Looks like a record is missing the `" <> missingField
935− <> "` field. It is close to names like "
948+ <> "` field. It is close to names like "
936− <> Help.commaSep typos <> " so maybe it is a typo?"
949+ <> Help.commaSep typos <> " so maybe it is a typo?"
941−manyMissingFields :: [Text] -> [Text] -> Maybe (Text, [Doc])
954+manyMissingFields :: [Text] -> [Text] -> (Text, [Doc])
942manyMissingFields knownFields missingFields =
955manyMissingFields knownFields missingFields =
943 case Help.findTypoPairs missingFields knownFields of
956 case Help.findTypoPairs missingFields knownFields of
946− ( "Looks like a record is missing these fields: "
958+ ( "Looks like a record is missing these fields: "
947− <> Help.commaSep missingFields
959+ <> Help.commaSep missingFields
951 typoPairs ->
963 typoPairs ->
953− ( "Looks like a record is missing these fields: "
964+ ( "Looks like a record is missing these fields: "
954− <> Help.commaSep missingFields
965+ <> Help.commaSep missingFields
955− <> ". Potential typos include:"
966+ <> ". Potential typos include:"
956− , typoDocs "->" typoPairs
967+ , typoDocs "->" typoPairs
960typoDocs :: Text -> [(Text, Text)] -> [Doc]
971typoDocs :: Text -> [(Text, Text)] -> [Doc]