@@ -10,11 +10,11 @@ module Reporting.Error.Type
1010 )
1111 where
1212
13−import Control.Arrow (first, second)
13+import Control.Arrow (second)
1414import qualified Data.Map as Map
15−import qualified Data.Maybe as Maybe
1615import qualified Data.Text as Text
1716import Data.Text (Text)
17+import Data.Monoid ((<>))
1818
1919import qualified AST.Helpers as Help
2020import qualified AST.Type as Type
@@ -24,8 +24,8 @@ import qualified Reporting.Render.Type as RenderType
2424import qualified Reporting.Report as Report
2525import qualified Reporting.Helpers as Help
2626import Reporting.Helpers
27− ( Doc, (<>), (<+>), capitalize, dullyellow, functionName
28− , i2t, indent, ordinalize, reflowParagraph, stack, text, toHint, vcat
27+ ( Doc, (<+>), capitalize, dullyellow, functionName, i2t
28+ , indent, ordinalize, reflowParagraph, stack, text
2929 )
3030
3131
@@ -34,30 +34,32 @@ import Reporting.Helpers
3434
3535
3636data Error
37− = Mismatch Mismatch
38− | BadMain Type.Canonical
39− | BadFlags Type.Canonical (Maybe Text)
40− | InfiniteType (Either Hint Text) Type.Canonical
37+ = Mismatch Mismatch
38+ | BadMain Type.Canonical
39+ | BadFlags Type.Canonical (Maybe Text)
40+ | InfiniteType (Either Hint Text) Type.Canonical
4141
4242
43−data Mismatch = MismatchInfo
43+data Mismatch =
44+ MismatchInfo
4445 { _hint :: Hint
4546 , _leftType :: Type.Canonical
4647 , _rightType :: Type.Canonical
48+ , _decoders :: Bool
4749 , _reason :: Maybe Reason
4850 }
4951
5052
5153data Reason
52− = BadFields [(Text, Maybe Reason)]
53− | MessyFields [Text] [Text] [Text]
54− | IntFloat
55− | TooLongComparableTuple Int
56− | MissingArgs Int
57− | RigidClash Text Text
58− | NotPartOfSuper Type.Super
59− | RigidVarTooGeneric Text SpecificThing
60− | RigidSuperTooGeneric Type.Super Text SpecificThing
54+ = BadFields [(Text, Maybe Reason)]
55+ | MessyFields [Text] [Text] [Text]
56+ | IntFloat
57+ | TooLongComparableTuple Int
58+ | MissingArgs Int
59+ | RigidClash Text Text
60+ | NotPartOfSuper Type.Super
61+ | RigidVarTooGeneric Text SpecificThing
62+ | RigidSuperTooGeneric Type.Super Text SpecificThing
6163
6264
6365data SpecificThing
@@ -68,39 +70,39 @@ data SpecificThing
6870
6971
7072data Hint
71− = CaseBranch Int Region.Region
72− | Case
73− | IfCondition
74− | IfBranches
75− | MultiIfBranch Int Region.Region
76− | If
77− | List
78− | ListElement Int Region.Region
79− | BinopLeft Var.Canonical Region.Region
80− | BinopRight Var.Canonical Region.Region
81− | Binop Var.Canonical
82− | Function (Maybe Var.Canonical)
83− | UnexpectedArg (Maybe Var.Canonical) Int Int Region.Region
84− | FunctionArity (Maybe Var.Canonical) Int Int Region.Region
85− | ReturnType Text Int Int Region.Region
86− | Instance Text
87− | Literal Text
88− | Pattern Pattern
89− | Shader
90− | Lambda
91− | Access (Maybe Text) Text
92− | Record
93− -- effect manager problems
94− | Manager Text
95− | State Text
96− | SelfMsg
73+ = CaseBranch Int Region.Region
74+ | Case
75+ | IfCondition
76+ | IfBranches
77+ | MultiIfBranch Int Region.Region
78+ | If
79+ | List
80+ | ListElement Int Region.Region
81+ | BinopLeft Var.Canonical Region.Region
82+ | BinopRight Var.Canonical Region.Region
83+ | Binop Var.Canonical
84+ | Function (Maybe Var.Canonical)
85+ | UnexpectedArg (Maybe Var.Canonical) Int Int Region.Region
86+ | FunctionArity (Maybe Var.Canonical) Int Int Region.Region
87+ | ReturnType Text Int Int Region.Region
88+ | Instance Text
89+ | Literal Text
90+ | Pattern Pattern
91+ | Shader
92+ | Lambda
93+ | Access (Maybe Text) Text
94+ | Record
95+ -- effect manager problems
96+ | Manager Text
97+ | State Text
98+ | SelfMsg
9799
98100
99101data Pattern
100− = PVar Text
101− | PAlias Text
102− | PCtor Var.Canonical
103− | PRecord
102+ = PVar Text
103+ | PAlias Text
104+ | PCtor Var.Canonical
105+ | PRecord
104106
105107
106108
@@ -155,17 +157,18 @@ toReport localizer err =
155157
156158
157159mismatchToReport :: RenderType.Localizer -> Mismatch -> Report.Report
158−mismatchToReport localizer (MismatchInfo hint leftType rightType maybeReason) =
160+mismatchToReport localizer (MismatchInfo hint leftType rightType decoders maybeReason) =
159161 let
160162 report =
161163 Report.report "TYPE MISMATCH"
162164
163165 typicalHints =
164− Maybe.maybeToList (reasonToString =<< maybeReason)
166+ maybe id (:) (reasonToDoc <$> maybeReason) $
167+ if decoders then [ jsonDecoderHint ] else []
165168
166169 cmpHint leftWords rightWords extraHints =
167170 comparisonHint localizer leftType rightType leftWords rightWords
168− (typicalHints <> map toHint extraHints)
171+ (typicalHints <> map Help.toSimpleHint extraHints)
169172 in
170173 case hint of
171174 CaseBranch branchNumber region ->
@@ -548,6 +551,8 @@ mismatchToReport localizer (MismatchInfo hint leftType rightType maybeReason) =
548551
549552
550553
554+-- COMPARISON HINT
555+
551556
552557comparisonHint
553558 :: RenderType.Localizer
@@ -573,6 +578,17 @@ comparisonHint localizer leftType rightType leftWords rightWords finalHints =
573578
574579
575580
581+-- JSON DECODER HINT
582+
583+
584+jsonDecoderHint :: Doc
585+jsonDecoderHint =
586+ Help.toSimpleHint $
587+ "New to JSON decoders? They are tough at first, so DEFINITELY learn more here: "
588+ <> Help.hintLink "json-decoders"
589+
590+
591+
576592-- BINOP HINTS
577593
578594
@@ -709,62 +725,64 @@ flipReason reason =
709725 RigidSuperTooGeneric super name specific
710726
711727
712−reasonToString :: Reason -> Maybe Doc
713−reasonToString reason =
714− let
715− (fields, maybeDeepReason) =
716− collectFields reason
717−
718− maybeDocs =
719− reasonToStringHelp =<< maybeDeepReason
720−
721− starter =
722− case fields of
723− [] ->
724− Nothing
728+reasonToDoc :: Reason -> Doc
729+reasonToDoc reason =
730+ case collectFields reason of
731+ Nothing ->
732+ let
733+ (firstLine, details) =
734+ reasonToDocHelp reason
735+ in
736+ Help.vcat $ Help.toSimpleHint firstLine : map (indent 4) details
725737
726− [field] ->
727− Just $ "Problem in the `" <> field <> "` field. "
738+ Just (fields, maybeDeepReason) ->
739+ let
740+ recordHint elaboration =
741+ [ "Problem", "in", "the", dullyellow (text (Text.intercalate "." fields)) <> "field." ]
742+ ++
743+ map text (Text.words elaboration)
744+ in
745+ case reasonToDocHelp <$> maybeDeepReason of
746+ Nothing ->
747+ Help.toFancyHint (recordHint badFieldElaboration)
728748
729− _ ->
730− Just $ "Problem at `" <> Text.intercalate "." fields <> "`. "
731− in
732− case (starter, maybeDocs) of
733− (Nothing, Nothing) ->
734− Nothing
749+ Just (firstLine, details) ->
750+ Help.vcat $ Help.toFancyHint (recordHint firstLine) : map (indent 4) details
735751
736− (Just msg, Nothing) ->
737− Just $ toHint (msg <> badFieldElaboration)
738752
739− (_, Just (firstLine, docs)) ->
740− Just $ vcat $
741− toHint (maybe firstLine (<> firstLine) starter)
742− : map (indent 4) docs
743753
754+-- COLLECT FIELDS
744755
745756
746−collectFields :: Reason -> ([Text], Maybe Reason)
757+collectFields :: Reason -> Maybe ([Text], Maybe Reason)
747758collectFields reason =
748759 case reason of
749− BadFields [(field, Nothing)] ->
750− ([field], Nothing)
760+ BadFields [(field, maybeReason)] ->
761+ Just (collectFieldsHelp [field] maybeReason)
762+
763+ _ ->
764+ Nothing
751765
752− BadFields [(field, Just subReason)] ->
753− first (field:) (collectFields subReason)
766+
767+collectFieldsHelp :: [Text] -> Maybe Reason -> ([Text], Maybe Reason)
768+collectFieldsHelp revFields maybeReason =
769+ case maybeReason of
770+ Just (BadFields [(field, deeperReason)]) ->
771+ collectFieldsHelp (field : revFields) deeperReason
754772
755773 _ ->
756− ([], Just reason)
774+ ( reverse revFields, maybeReason )
757775
758776
759−reasonToStringHelp :: Reason -> Maybe (Text, [Doc])
760−reasonToStringHelp reason =
777+reasonToDocHelp :: Reason -> (Text, [Doc])
778+reasonToDocHelp reason =
761779 let
762− go msg =
763− Just (msg, [])
780+ simpleDoc msg =
781+ ( msg, [] )
764782 in
765783 case reason of
766784 BadFields fields ->
767− go $
785+ simpleDoc $
768786 "I am seeing issues with the "
769787 <> Help.commaSep (map fst fields) <> " fields. "
770788 <> badFieldElaboration
@@ -773,22 +791,22 @@ reasonToStringHelp reason =
773791 messyFieldsHelp both leftOnly rightOnly
774792
775793 IntFloat ->
776− go $
794+ simpleDoc $
777795 "Elm does not automatically convert between Ints and Floats. Use\
778796 \ `toFloat` and `round` to do specific conversions.\
779797 \ <http://package.elm-lang.org/packages/elm-lang/core/latest/Basics#toFloat>"
780798
781799 TooLongComparableTuple len ->
782− go $
800+ simpleDoc $
783801 "Although tuples are comparable, this is currently only supported\
784802 \ for tuples with 6 or fewer entries, not " <> i2t len <> "."
785803
786804 MissingArgs num ->
787− go $
805+ simpleDoc $
788806 "It looks like a function needs " <> Help.moreArgs num <> "."
789807
790808 RigidClash name1 name2 ->
791− go $
809+ simpleDoc $
792810 "Your type annotation uses `" <> name1 <> "` and `" <> name2 <>
793811 "` as DIFFERENT type variables. By using separate names, you are\
794812 \ claiming the values can be different, but the code suggests that\
@@ -798,31 +816,31 @@ reasonToStringHelp reason =
798816 <> Help.hintLink "type-annotations"
799817
800818 NotPartOfSuper Type.Number ->
801− go "Only ints and floats are numbers."
819+ simpleDoc "Only ints and floats are numbers."
802820
803821 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."
805823
806824 NotPartOfSuper Type.Appendable ->
807− go "Only strings and lists are appendable."
825+ simpleDoc "Only strings and lists are appendable."
808826
809827 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."
811829
812830 RigidVarTooGeneric name specific ->
813− go $ rigidTooGenericHelp "ANY type of value" name specific
831+ simpleDoc $ rigidTooGenericHelp "ANY type of value" name specific
814832
815833 RigidSuperTooGeneric Type.Number name specific ->
816− go $ rigidTooGenericHelp "BOTH Ints and Floats" name specific
834+ simpleDoc $ rigidTooGenericHelp "BOTH Ints and Floats" name specific
817835
818836 RigidSuperTooGeneric Type.Comparable name specific ->
819− go $ rigidTooGenericHelp "ANY comparable value" name specific
837+ simpleDoc $ rigidTooGenericHelp "ANY comparable value" name specific
820838
821839 RigidSuperTooGeneric Type.Appendable name specific ->
822− go $ rigidTooGenericHelp "BOTH Strings and Lists" name specific
840+ simpleDoc $ rigidTooGenericHelp "BOTH Strings and Lists" name specific
823841
824842 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
826844
827845
828846rigidTooGenericHelp :: Text -> Text -> SpecificThing -> Text
@@ -869,11 +887,11 @@ specificThingToText specific =
869887badFieldElaboration :: Text
870888badFieldElaboration =
871889 "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.\
873891 \ So the problem may actually be a weird interaction with previous fields."
874892
875893
876−messyFieldsHelp :: [Text] -> [Text] -> [Text] -> Maybe (Text, [Doc])
894+messyFieldsHelp :: [Text] -> [Text] -> [Text] -> (Text, [Doc])
877895messyFieldsHelp both leftOnly rightOnly =
878896 case (leftOnly, rightOnly) of
879897 ([], [missingField]) ->
@@ -899,62 +917,55 @@ messyFieldsHelp both leftOnly rightOnly =
899917 pairs
900918 in
901919 if null typoPairs then
902− Just
903− ( "The record fields do not match up. One has "
904− <> Help.commaSep leftOnly <> ". The other has "
905− <> Help.commaSep rightOnly <> "."
906− , []
907− )
920+ ( "The record fields do not match up. One has "
921+ <> Help.commaSep leftOnly <> ". The other has "
922+ <> Help.commaSep rightOnly <> "."
923+ , []
924+ )
908925
909926 else
910− Just
911− ( "The record fields do not match up. Maybe you made one of these typos?"
912− , typoDocs "<->" typoPairs
913− )
927+ ( "The record fields do not match up. Maybe you made one of these typos?"
928+ , typoDocs "<->" typoPairs
929+ )
914930
915931
916−oneMissingField :: [Text] -> Text -> Maybe (Text, [Doc])
932+oneMissingField :: [Text] -> Text -> ( Text, [Doc] )
917933oneMissingField knownFields missingField =
918934 case Help.findPotentialTypos knownFields missingField of
919935 [] ->
920− Just
921− ( "Looks like a record is missing the `" <> missingField <> "` field."
922− , []
923− )
936+ ( "Looks like a record is missing the `" <> missingField <> "` field."
937+ , []
938+ )
924939
925940 [typo] ->
926− Just
927− ( "Looks like a record is missing the `" <> missingField
928− <> "` field. Maybe it is a typo?"
929− , typoDocs "->" [(missingField, typo)]
930− )
941+ ( "Looks like a record is missing the `" <> missingField
942+ <> "` field. Maybe it is a typo?"
943+ , typoDocs "->" [(missingField, typo)]
944+ )
931945
932946 typos ->
933− Just
934− ( "Looks like a record is missing the `" <> missingField
935− <> "` field. It is close to names like "
936− <> Help.commaSep typos <> " so maybe it is a typo?"
937− , []
938− )
947+ ( "Looks like a record is missing the `" <> missingField
948+ <> "` field. It is close to names like "
949+ <> Help.commaSep typos <> " so maybe it is a typo?"
950+ , []
951+ )
939952
940953
941−manyMissingFields :: [Text] -> [Text] -> Maybe (Text, [Doc])
954+manyMissingFields :: [Text] -> [Text] -> (Text, [Doc])
942955manyMissingFields knownFields missingFields =
943956 case Help.findTypoPairs missingFields knownFields of
944957 [] ->
945− Just
946− ( "Looks like a record is missing these fields: "
947− <> Help.commaSep missingFields
948− , []
949− )
958+ ( "Looks like a record is missing these fields: "
959+ <> Help.commaSep missingFields
960+ , []
961+ )
950962
951963 typoPairs ->
952− Just
953− ( "Looks like a record is missing these fields: "
954− <> Help.commaSep missingFields
955− <> ". Potential typos include:"
956− , typoDocs "->" typoPairs
957− )
964+ ( "Looks like a record is missing these fields: "
965+ <> Help.commaSep missingFields
966+ <> ". Potential typos include:"
967+ , typoDocs "->" typoPairs
968+ )
958969
959970
960971typoDocs :: Text -> [(Text, Text)] -> [Doc]