-
-
Notifications
You must be signed in to change notification settings - Fork 436
Expand file tree
/
Copy pathDiagnostic.hs
More file actions
89 lines (80 loc) · 3.31 KB
/
Diagnostic.hs
File metadata and controls
89 lines (80 loc) · 3.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
{-# LANGUAGE CPP #-}
module Development.IDE.Plugin.Plugins.Diagnostic (
matchVariableNotInScope,
matchRegexUnifySpaces,
unifySpaces,
matchFoundHole,
diagReportHoleError
)
where
import Control.Lens
import qualified Data.Text as T
import Development.IDE.GHC.Compat (RdrName, Type)
import Development.IDE.GHC.Compat.Error (Hole, _ReportHoleError,
_TcRnMessage,
_TcRnNotInScope,
_TcRnSolverReport, hole_occ,
hole_ty, msgEnvelopeErrorL,
reportContentL)
import Development.IDE.Types.Diagnostics (FileDiagnostic,
_SomeStructuredMessage,
fdStructuredMessageL)
import GHC.Tc.Errors.Types (NotInScopeError)
import Text.Regex.TDFA ((=~~))
unifySpaces :: T.Text -> T.Text
unifySpaces = T.unwords . T.words
-- | Returns Just (the submatches) for the first capture, or Nothing.
matchRegex :: T.Text -> T.Text -> Maybe [T.Text]
matchRegex message regex = case message =~~ regex of
Just (_ :: T.Text, _ :: T.Text, _ :: T.Text, bindings) -> Just bindings
Nothing -> Nothing
-- | 'matchRegex' combined with 'unifySpaces'
--
-- >>> matchRegexUnifySpaces "hello I'm a cow" "he(ll)o"
-- Just ["ll"]
matchRegexUnifySpaces :: T.Text -> T.Text -> Maybe [T.Text]
matchRegexUnifySpaces message = matchRegex (unifySpaces message)
matchFoundHole :: FileDiagnostic -> Maybe (RdrName, Type)
matchFoundHole fd = do
hole <- diagReportHoleError fd
Just (hole_occ hole, hole_ty hole)
matchVariableNotInScope :: FileDiagnostic -> Maybe (RdrName, Maybe Type)
matchVariableNotInScope fd = do
(rdrName, _) <- diagReportNotInScope fd
Just (rdrName, Nothing)
-- | Extract the typed hole information from a diagnostic, if the diagnostic
-- originates from a hole. Returns 'Nothing' for any other kind of diagnostic.
diagReportHoleError :: FileDiagnostic -> Maybe Hole
diagReportHoleError diag = do
solverReport <-
diag
^? fdStructuredMessageL
. _SomeStructuredMessage
. msgEnvelopeErrorL
. _TcRnMessage
. _TcRnSolverReport
. _1
(hole, _) <- solverReport ^? reportContentL . _ReportHoleError
Just hole
-- | Extract the 'NotInScopeError' and the corresponding 'RdrName' from a 'FileDiagnostic'
-- if it represents a not-in-scope error.
diagReportNotInScope :: FileDiagnostic -> Maybe (RdrName, NotInScopeError)
diagReportNotInScope diag = do
#if MIN_VERSION_ghc(9,13,0)
(err, rdrName) <-
diag
^? fdStructuredMessageL
. _SomeStructuredMessage
. msgEnvelopeErrorL
. _TcRnMessage
. _TcRnNotInScope
#else
(err, rdrName, _, _) <-
diag
^? fdStructuredMessageL
. _SomeStructuredMessage
. msgEnvelopeErrorL
. _TcRnMessage
. _TcRnNotInScope
#endif
Just (rdrName, err)