1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
3module Reporting.Error.Pattern
9import qualified Data.List as List
11import qualified Nitpick.PatternMatches as P
12import Reporting.Doc ((<>))
13import qualified Reporting.Doc as D
14import qualified Reporting.Report as Report
15import qualified Reporting.Render.Code as Code
22toReport :: Code.Source -> P.Error -> Report.Report
25 P.Redundant caseRegion patternRegion index ->
26 Report.Report "REDUNDANT PATTERN" patternRegion [] $
27 Report.toCodeSnippet source caseRegion (Just patternRegion)
30 "The " <> D.intToOrdinal index <> " pattern is redundant:"
33 "Any value with this shape will be handled by a previous\
34 \ pattern, so it should be removed."
37 P.Incomplete region context unhandled ->
40 Report.Report "UNSAFE PATTERN" region [] $
41 Report.toCodeSnippet source region Nothing
43 "This pattern does not cover all possiblities:"
46 [ "Other possibilities include:"
47 , unhandledPatternsToDocBlock unhandled
49 "I would have to crash if I saw one of those! So rather than\
50 \ pattern matching in function arguments, put a `case` in\
51 \ the function body to account for all possibilities."
56 Report.Report "UNSAFE PATTERN" region [] $
57 Report.toCodeSnippet source region Nothing
59 "This pattern does not cover all possible values:"
62 [ "Other possibilities include:"
63 , unhandledPatternsToDocBlock unhandled
65 "I would have to crash if I saw one of those! You can use\
66 \ `let` to deconstruct values only if there is ONE possiblity.\
67 \ Switch to a `case` expression to account for all possibilities."
69 "Are you calling a function that definitely returns values\
70 \ with a very specific shape? Try making the return type of\
71 \ that function more specific!"
76 Report.Report "MISSING PATTERNS" region [] $
77 Report.toCodeSnippet source region Nothing
79 "This `case` does not have branches for all possibilities:"
82 [ "Missing possibilities include:"
83 , unhandledPatternsToDocBlock unhandled
85 "I would have to crash if I saw one of those. Add branches for them!"
87 "If you want to write the code for each branch later, use `Debug.todo` as a placeholder. Read"
89 "for more guidance on this workflow."
98unhandledPatternsToDocBlock :: [P.Pattern] -> D.Doc
99unhandledPatternsToDocBlock unhandledPatterns =
100 D.indent 4 $ D.dullyellow $ D.vcat $
101 map (patternToDoc Unambiguous) unhandledPatterns
111patternToDoc :: Context -> P.Pattern -> D.Doc
112patternToDoc context pattern =
113 case delist pattern [] of
114 NonList P.Anything ->
117 NonList (P.Literal literal) ->
120 "'" <> D.fromUtf8 chr <> "'"
123 "\"" <> D.fromUtf8 str <> "\""
128 NonList (P.Ctor _ "#0" []) ->
131 NonList (P.Ctor _ "#2" [a,b]) ->
132 "( " <> patternToDoc Unambiguous a <>
133 ", " <> patternToDoc Unambiguous b <>
136 NonList (P.Ctor _ "#3" [a,b,c]) ->
137 "( " <> patternToDoc Unambiguous a <>
138 ", " <> patternToDoc Unambiguous b <>
139 ", " <> patternToDoc Unambiguous c <>
142 NonList (P.Ctor _ name args) ->
145 D.hsep (D.fromName name : map (patternToDoc Arg) args)
147 if context == Arg && length args > 0 then
148 "(" <> ctorDoc <> ")"
155 FiniteList entries ->
156 let entryDocs = map (patternToDoc Unambiguous) entries in
157 "[" <> D.hcat (List.intersperse "," entryDocs) <> "]"
159 Conses conses finalPattern ->
163 (\hd tl -> patternToDoc Head hd <> " :: " <> tl)
164 (patternToDoc Unambiguous finalPattern)
167 if context == Unambiguous then
170 "(" <> consDoc <> ")"
174 = FiniteList [P.Pattern]
175 | Conses [P.Pattern] P.Pattern
179delist :: P.Pattern -> [P.Pattern] -> Structure
180delist pattern revEntries =
183 FiniteList revEntries
185 P.Ctor _ "::" [hd,tl] ->
186 delist tl (hd:revEntries)
194 Conses (reverse revEntries) pattern
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list