1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
3module Reporting.Error.Pattern
9import qualified Data.List as List
11import qualified Elm.String as ES
12import qualified Nitpick.PatternMatches as P
13import Reporting.Doc ((<>))
14import qualified Reporting.Doc as D
15import qualified Reporting.Report as Report
16import qualified Reporting.Render.Code as Code
23toReport :: Code.Source -> P.Error -> Report.Report
26 P.Redundant caseRegion patternRegion index ->
27 Report.Report "REDUNDANT PATTERN" patternRegion [] $
28 Code.toSnippet source caseRegion (Just patternRegion)
31 "The " <> D.intToOrdinal index <> " pattern is redundant:"
34 "Any value with this shape will be handled by a previous\
35 \ pattern, so it should be removed."
38 P.Incomplete region context unhandled ->
41 Report.Report "UNSAFE PATTERN" region [] $
42 Code.toSnippet source region Nothing
44 "This pattern does not cover all possiblities:"
47 [ "Other possibilities include:"
48 , unhandledPatternsToDocBlock unhandled
50 "I would have to crash if I saw one of those! So rather than\
51 \ pattern matching in function arguments, put a `case` in\
52 \ the function body to account for all possibilities."
57 Report.Report "UNSAFE PATTERN" region [] $
58 Code.toSnippet source region Nothing
60 "This pattern does not cover all possible values:"
63 [ "Other possibilities include:"
64 , unhandledPatternsToDocBlock unhandled
66 "I would have to crash if I saw one of those! You can use\
67 \ `let` to deconstruct values only if there is ONE possiblity.\
68 \ Switch to a `case` expression to account for all possibilities."
70 "Are you calling a function that definitely returns values\
71 \ with a very specific shape? Try making the return type of\
72 \ that function more specific!"
77 Report.Report "MISSING PATTERNS" region [] $
78 Code.toSnippet source region Nothing
80 "This `case` does not have branches for all possibilities:"
83 [ "Missing possibilities include:"
84 , unhandledPatternsToDocBlock unhandled
86 "I would have to crash if I saw one of those. Add branches for them!"
88 "If you want to write the code for each branch later, use `Debug.todo` as a placeholder. Read"
90 "for more guidance on this workflow."
99unhandledPatternsToDocBlock :: [P.Pattern] -> D.Doc
100unhandledPatternsToDocBlock unhandledPatterns =
101 D.indent 4 $ D.dullyellow $ D.vcat $
102 map (patternToDoc Unambiguous) unhandledPatterns
112patternToDoc :: Context -> P.Pattern -> D.Doc
113patternToDoc context pattern =
114 case delist pattern [] of
115 NonList P.Anything ->
118 NonList (P.Literal literal) ->
121 "'" <> D.fromChars (ES.toChars chr) <> "'"
124 "\"" <> D.fromChars (ES.toChars str) <> "\""
129 NonList (P.Ctor _ "#0" []) ->
132 NonList (P.Ctor _ "#2" [a,b]) ->
133 "( " <> patternToDoc Unambiguous a <>
134 ", " <> patternToDoc Unambiguous b <>
137 NonList (P.Ctor _ "#3" [a,b,c]) ->
138 "( " <> patternToDoc Unambiguous a <>
139 ", " <> patternToDoc Unambiguous b <>
140 ", " <> patternToDoc Unambiguous c <>
143 NonList (P.Ctor _ name args) ->
146 D.hsep (D.fromName name : map (patternToDoc Arg) args)
148 if context == Arg && length args > 0 then
149 "(" <> ctorDoc <> ")"
156 FiniteList entries ->
157 let entryDocs = map (patternToDoc Unambiguous) entries in
158 "[" <> D.hcat (List.intersperse "," entryDocs) <> "]"
160 Conses conses finalPattern ->
164 (\hd tl -> patternToDoc Head hd <> " :: " <> tl)
165 (patternToDoc Unambiguous finalPattern)
168 if context == Unambiguous then
171 "(" <> consDoc <> ")"
175 = FiniteList [P.Pattern]
176 | Conses [P.Pattern] P.Pattern
180delist :: P.Pattern -> [P.Pattern] -> Structure
181delist pattern revEntries =
184 FiniteList revEntries
186 P.Ctor _ "::" [hd,tl] ->
187 delist tl (hd:revEntries)
195 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