on master help sign in
Detect record field typos and make hints prettier
66fb7eeEvan Czaplicki
src/Reporting/Error/Type.hs+68−42
@@ -2,7 +2,10 @@
2module Reporting.Error.Type where
2module Reporting.Error.Type where
3
3
4import qualified Data.Maybe as Maybe
4import qualified Data.Maybe as Maybe
5−import Text.PrettyPrint.ANSI.Leijen (Doc, (<+>), equals, indent, text)
5+import Text.PrettyPrint.ANSI.Leijen
6+ ( Doc, (<>), (<+>), colon, dullyellow, equals
7+ , fillSep, hang, indent, text, underline, vcat
8+ )
6
9
7import qualified AST.Type as Type
10import qualified AST.Type as Type
8import qualified AST.Variable as Var
11import qualified AST.Variable as Var
@@ -111,11 +114,11 @@ mismatchToReport localizer (MismatchInfo hint leftType rightType maybeReason) =
111 report =
114 report =
112 Report.report "TYPE MISMATCH"
115 Report.report "TYPE MISMATCH"
113
116
114− reasonHints =
115− Maybe.maybeToList (fmap reasonToString maybeReason)
116−
117 cmpHint leftWords rightWords extraHints =
117 cmpHint leftWords rightWords extraHints =
118− comparisonHint localizer leftType rightType leftWords rightWords (extraHints ++ reasonHints)
118+ comparisonHint localizer leftType rightType leftWords rightWords
119+ ( map toHint extraHints
120+ ++ Maybe.maybeToList (fmap reasonToString maybeReason)
121+ )
119 in
122 in
120 case hint of
123 case hint of
121 CaseBranch branchNumber region ->
124 CaseBranch branchNumber region ->
@@ -377,7 +380,7 @@ comparisonHint
377 -> Type.Canonical
380 -> Type.Canonical
378 -> String
381 -> String
379 -> String
382 -> String
380− -> [String]
383+ -> [Doc]
381 -> Doc
384 -> Doc
382comparisonHint localizer leftType rightType leftWords rightWords finalHints =
385comparisonHint localizer leftType rightType leftWords rightWords finalHints =
383 let
386 let
@@ -391,7 +394,11 @@ comparisonHint localizer leftType rightType leftWords rightWords finalHints =
391 , indent 4 rightDoc
394 , indent 4 rightDoc
392 ]
395 ]
393 ++
396 ++
394− map Help.reflowParagraph finalHints
397+ finalHints
398+
399+
400+
401+-- MISMATCH HELPERS
395
402
396
403
397ordinalPair :: Int -> String
404ordinalPair :: Int -> String
@@ -399,33 +406,44 @@ ordinalPair number =
399 Help.ordinalize (number -1 ) ++ " and " ++ Help.ordinalize number
406 Help.ordinalize (number -1 ) ++ " and " ++ Help.ordinalize number
400
407
401
408
409+prettyName :: Var.Canonical -> String
410+prettyName (Var.Canonical _ opName) =
411+ Help.functionName opName
402
412
403−-- MISMTACH REASONS
404
413
414+funcName :: Maybe Var.Canonical -> String
415+funcName maybeVar =
416+ case maybeVar of
417+ Nothing ->
418+ "this function"
405
419
406−reasonToString :: Reason -> String
420+ Just var ->
407−reasonToString reason =
421+ "function " ++ prettyName var
408− case reason of
409− MessyFields expecteds [] ->
410− genericMissingFieldsMessage "former" expecteds
411
422
412− MessyFields [] actuals ->
413− genericMissingFieldsMessage "latter" actuals
414
423
415− MessyFields expecteds actuals ->
416− case concatMap (similarNames actuals) expecteds of
417− [] ->
418− "These records look pretty different."
419
424
420− [(ex,ac)] ->
425+-- MISMTACH REASONS
421− "Looks like a misspelling between field " ++ ex ++ " and " ++ ac ++ "."
422
426
423− potentialTypos ->
427+
424− "There are some potential typos in the record field names.\n"
428+reasonToString :: Reason -> Doc
425− ++ concatMap (\(ex,ac) -> "\n " ++ ex ++ " <=> " ++ ac) potentialTypos
429+reasonToString reason =
430+ case reason of
431+ MessyFields leftOnly rightOnly ->
432+ let
433+ maybeMessage =
434+ do let typos = RenderType.findPotentialTypos leftOnly rightOnly
435+ RenderType.vetTypos typos
436+ misspellingMessage typos
437+ in
438+ case maybeMessage of
439+ Just doc ->
440+ doc
441+
442+ Nothing ->
443+ error "TODO"
426
444
427 NotRecord ->
445 NotRecord ->
428− "A record cannot be merged with other types of values."
446+ toHint "A record cannot be merged with other types of values."
429
447
430 TooLongComparableTuple len ->
448 TooLongComparableTuple len ->
431 error "TODO"
449 error "TODO"
@@ -434,30 +452,38 @@ reasonToString reason =
434 error "TODO"
452 error "TODO"
435
453
436
454
437−similarNames :: [String] -> String -> [(String,String)]
455+hintDoc :: Doc
438−similarNames otherKeys key =
456+hintDoc =
439− map ((,) key) (filter (\key' -> Help.distance key key' == 1) otherKeys)
457+ underline (text "Hint") <> colon
440
458
441
459
442−genericMissingFieldsMessage :: String -> [String] -> String
460+toHint :: String -> Doc
443−genericMissingFieldsMessage latterOrFormer fields =
461+toHint str =
444− "A record in the " ++ latterOrFormer ++ " type is missing field"
462+ fillSep (hintDoc : map text (words str))
445− ++ Help.commaSep fields
446
463
447
464
448−prettyName :: Var.Canonical -> String
465+misspellingMessage :: [(String,String)] -> Maybe Doc
449−prettyName (Var.Canonical _ opName) =
466+misspellingMessage typos =
450− Help.functionName opName
467+ if null typos then
468+ Nothing
451
469
470+ else
471+ let
472+ maxLen =
473+ maximum (map (length . fst) typos)
474+ in
475+ Just $ hang 4 $ vcat $
476+ toHint "I compared the record fields and found some potential typos."
477+ : text ""
478+ : map (pad maxLen) typos
452
479
453−funcName :: Maybe Var.Canonical -> String
454−funcName maybeVar =
455− case maybeVar of
456− Nothing ->
457− "this function"
458
480
459− Just var ->
481+pad :: Int -> (String, String) -> Doc
460− "function " ++ prettyName var
482+pad maxLen (leftField, rightField) =
483+ text (replicate (maxLen - length leftField) ' ')
484+ <> dullyellow (text leftField)
485+ <+> text "<->"
486+ <+> dullyellow (text rightField)
461
487
462
488
463
489
src/Reporting/Render/Type.hs+3−1
@@ -5,6 +5,8 @@ module Reporting.Render.Type
5 , toDoc
5 , toDoc
6 , diffToDocs
6 , diffToDocs
7 , Style(..)
7 , Style(..)
8+ , findPotentialTypos
9+ , vetTypos
8 )
10 )
9 where
11 where
10
12
@@ -13,7 +15,7 @@ import qualified Data.Map as Map
13import qualified Data.Set as Set
15import qualified Data.Set as Set
14import Text.PrettyPrint.ANSI.Leijen
16import Text.PrettyPrint.ANSI.Leijen
15 ( Doc, (<>), (<+>), cat, colon, comma, dullyellow, equals, hang, hsep
17 ( Doc, (<>), (<+>), cat, colon, comma, dullyellow, equals, hang, hsep
16− , indent, lbrace, lparen, parens, rbrace, rparen, sep, space, text, vcat
18+ , lbrace, lparen, parens, rbrace, rparen, sep, space, text, vcat
17 )
19 )
18
20
19import qualified AST.Helpers as Help
21import qualified AST.Helpers as Help