on master help sign in
Do a better job with missing fields

Fixes https://github.com/elm-lang/error-message-catalog/issues/63

commit8c8e70a5f6937416a750c52232c396fb30a604d7 authorEvan Czaplicki <evancz@users.noreply.github.com> dateWed 10 Aug 2016, 00:03 (10 years ago) parent4d800cd
4 files changed+117−35
src/Reporting/Error/Helpers.hs+9−4 src/Reporting/Error/Type.hs+98−24 src/Reporting/Render/Type.hs+3−3 src/Type/Unify.hs+7−4
src/Reporting/Error/Helpers.hs+9−4
@@ -3,7 +3,7 @@ module Reporting.Error.Helpers
33 ( (|>)
44 , functionName, hintLink, stack, reflowParagraph
55 , commaSep, capitalize, ordinalize, drawCycle
6− , findPotentialTypos, vetTypos
6+ , findPotentialTypos, findTypoPairs, vetTypos
77 , nearbyNames, distance, maybeYouWant
88 )
99 where
@@ -132,11 +132,16 @@ drawCycle strings =
132132-- FIND TYPOS
133133
134134
135−findPotentialTypos :: [String] -> [String] -> [(String, String)]
136−findPotentialTypos leftOnly rightOnly =
135+findPotentialTypos :: [String] -> String -> [String]
136+findPotentialTypos knownNames badName =
137+ filter ((==1) . distance badName) knownNames
138+
139+
140+findTypoPairs :: [String] -> [String] -> [(String, String)]
141+findTypoPairs leftOnly rightOnly =
137142 let
138143 veryNear leftName =
139− map ((,) leftName) (filter ((==1) . distance leftName) rightOnly)
144+ map ((,) leftName) (findPotentialTypos rightOnly leftName)
140145 in
141146 concatMap veryNear leftOnly
142147
src/Reporting/Error/Type.hs+98−24
@@ -39,7 +39,7 @@ data Mismatch = MismatchInfo
3939
4040data Reason
4141 = BadFields [(String, Maybe Reason)]
42− | MessyFields [String] [String]
42+ | MessyFields [String] [String] [String]
4343 | IntFloat
4444 | TooLongComparableTuple Int
4545 | MissingArgs Int
@@ -591,8 +591,8 @@ flipReason reason =
591591 BadFields fields ->
592592 BadFields (map (second (fmap flipReason)) fields)
593593
594− MessyFields leftOnly rightOnly ->
595− MessyFields rightOnly leftOnly
594+ MessyFields both left right ->
595+ MessyFields both right left
596596
597597 IntFloat ->
598598 IntFloat
@@ -667,10 +667,8 @@ reasonToStringHelp reason =
667667 ++ Help.commaSep (map fst fields) ++ " fields. "
668668 ++ badFieldElaboration
669669
670− MessyFields leftOnly rightOnly ->
671− do let typos = Help.findPotentialTypos leftOnly rightOnly
672− _ <- Help.vetTypos typos
673− misspellingMessage typos
670+ MessyFields both leftOnly rightOnly ->
671+ messyFieldsHelp both leftOnly rightOnly
674672
675673 IntFloat ->
676674 go $
@@ -741,28 +739,104 @@ toHint str =
741739 fillSep (hintDoc : map text (words str))
742740
743741
744−misspellingMessage :: [(String,String)] -> Maybe (String, [Doc])
745−misspellingMessage typos =
746− if null typos then
747− Nothing
742+messyFieldsHelp :: [String] -> [String] -> [String] -> Maybe (String, [Doc])
743+messyFieldsHelp both leftOnly rightOnly =
744+ case (leftOnly, rightOnly) of
745+ ([], [missingField]) ->
746+ oneMissingField both missingField
747+
748+ ([missingField], []) ->
749+ oneMissingField both missingField
750+
751+ ([], missingFields) ->
752+ manyMissingFields both missingFields
753+
754+ (missingFields, []) ->
755+ manyMissingFields both missingFields
756+
757+ _ ->
758+ let
759+ typoPairs =
760+ case Help.findTypoPairs leftOnly rightOnly of
761+ [] ->
762+ Help.findTypoPairs (both ++ leftOnly) (both ++ rightOnly)
763+
764+ pairs ->
765+ pairs
766+ in
767+ if null typoPairs then
768+ Just
769+ ( "The record fields do not match up. One has "
770+ ++ Help.commaSep leftOnly ++ ". The other has "
771+ ++ Help.commaSep rightOnly ++ "."
772+ , []
773+ )
774+
775+ else
776+ Just
777+ ( "The record fields do not match up. Maybe you made one of these typos?"
778+ , typoDocs "<->" typoPairs
779+ )
780+
781+
782+oneMissingField :: [String] -> String -> Maybe (String, [Doc])
783+oneMissingField knownFields missingField =
784+ case Help.findPotentialTypos knownFields missingField of
785+ [] ->
786+ Just
787+ ( "Looks like a record is missing the `" ++ missingField ++ "` field."
788+ , []
789+ )
790+
791+ [typo] ->
792+ Just
793+ ( "Looks like a record is missing the `" ++ missingField
794+ ++ "` field. Maybe it is a typo?"
795+ , typoDocs "->" [(missingField, typo)]
796+ )
797+
798+ typos ->
799+ Just
800+ ( "Looks like a record is missing the `" ++ missingField
801+ ++ "` field. It is close to names like "
802+ ++ Help.commaSep typos ++ " so maybe it is a typo?"
803+ , []
804+ )
805+
748806
749− else
750− let
751− maxLen =
752− maximum (map (length . fst) typos)
753− in
807+manyMissingFields :: [String] -> [String] -> Maybe (String, [Doc])
808+manyMissingFields knownFields missingFields =
809+ case Help.findTypoPairs missingFields knownFields of
810+ [] ->
754811 Just
755− ( "I compared the record fields and found some potential typos."
756− , text "" : map (pad maxLen) typos
812+ ( "Looks like a record is missing these fields: "
813+ ++ Help.commaSep missingFields
814+ , []
757815 )
758816
817+ typoPairs ->
818+ Just
819+ ( "Looks like a record is missing these fields: " ++ Help.commaSep missingFields
820+ ++ ". Potential typos include:"
821+ , typoDocs "->" typoPairs
822+ )
823+
824+
825+typoDocs :: String -> [(String, String)] -> [Doc]
826+typoDocs arrow typoPairs =
827+ let
828+ maxLen =
829+ maximum (map (length . fst) typoPairs)
830+ in
831+ text "" : map (padTypo arrow maxLen) typoPairs
832+
759833
760−pad :: Int -> (String, String) -> Doc
761−pad maxLen (leftField, rightField) =
762− text (replicate (maxLen - length leftField) ' ')
763− <> dullyellow (text leftField)
764− <+> text "<->"
765− <+> dullyellow (text rightField)
834+padTypo :: String -> Int -> (String, String) -> Doc
835+padTypo arrow maxLen (missingField, knownField) =
836+ text (replicate (maxLen - length missingField) ' ')
837+ <> dullyellow (text missingField)
838+ <+> text arrow
839+ <+> dullyellow (text knownField)
766840
767841
768842
src/Reporting/Render/Type.hs+3−3
@@ -327,8 +327,8 @@ unzipDiffs diffPairs =
327327analyzeFields :: [String] -> [String] -> ( [(Doc, Doc)], [(Doc, Doc)] )
328328analyzeFields leftOnly rightOnly =
329329 let
330− potentialTypos =
331− Help.findPotentialTypos leftOnly rightOnly
330+ typoPairs =
331+ Help.findTypoPairs leftOnly rightOnly
332332
333333 mkField func name =
334334 ( func (text name), text "..." )
@@ -336,7 +336,7 @@ analyzeFields leftOnly rightOnly =
336336 mkFieldWith counts name =
337337 mkField (if Set.member name counts then dullyellow else id) name
338338 in
339− case Help.vetTypos potentialTypos of
339+ case Help.vetTypos typoPairs of
340340 Just (leftTypos, rightTypos) ->
341341 ( map (mkFieldWith leftTypos) leftOnly
342342 , map (mkFieldWith rightTypos) rightOnly
src/Type/Unify.hs+7−4
@@ -623,11 +623,12 @@ unifyRecord context firstStructure secondStructure =
623623 do let (RecordStructure expFields expVar expStruct) = firstStructure
624624 let (RecordStructure actFields actVar actStruct) = secondStructure
625625
626+ let sharedFields = Map.intersectionWith (,) expFields actFields
627+
626628 -- call after unifying extension, make sure record shape matches before
627629 -- looking into whether the particular field types match.
628630 let unifySharedFields otherFields ext =
629− do let sharedFields = Map.intersectionWith (,) expFields actFields
630− unifySharedFieldsHelp context sharedFields
631+ do unifySharedFieldsHelp context sharedFields
631632 let allFields = Map.union (Map.map fst sharedFields) otherFields
632633 merge context (Structure (Record1 allFields ext))
633634
@@ -640,10 +641,12 @@ unifyRecord context firstStructure secondStructure =
640641 unifySharedFields Map.empty expVar
641642
642643 (Empty, _, _, False) ->
643− mismatch context (Just (Error.MessyFields (Map.keys uniqueExpFields) (Map.keys uniqueActFields)))
644+ mismatch context $ Just $
645+ Error.MessyFields (Map.keys sharedFields) (Map.keys uniqueExpFields) (Map.keys uniqueActFields)
644646
645647 (_, False, Empty, _) ->
646− mismatch context (Just (Error.MessyFields (Map.keys uniqueExpFields) (Map.keys uniqueActFields)))
648+ mismatch context $ Just $
649+ Error.MessyFields (Map.keys sharedFields) (Map.keys uniqueExpFields) (Map.keys uniqueActFields)
647650
648651 (_, False, _, True) ->
649652 do subRecord <- fresh context (Structure (Record1 uniqueExpFields expVar))