@@ -9,6 +9,9 @@ module Ide.Plugin.Literals (
9
9
, getSrcSpan
10
10
) where
11
11
12
+ import Data.Generics (mkQ )
13
+ import Data.Maybe (catMaybes , mapMaybe ,
14
+ maybeToList )
12
15
import Data.Set (Set )
13
16
import qualified Data.Set as S
14
17
import Data.Text (Text )
@@ -18,7 +21,7 @@ import Development.IDE.GHC.Util (unsafePrintSDoc)
18
21
import Development.IDE.Graph.Classes (NFData (rnf ))
19
22
import qualified GHC.Generics as GHC
20
23
import Generics.SYB (Data , Typeable , cast ,
21
- everything )
24
+ everything , listify )
22
25
23
26
-- data type to capture what type of literal we are dealing with
24
27
-- provides location and possibly source text (for OverLits) as well as it's value
@@ -46,72 +49,33 @@ getSrcSpan = \case
46
49
FracLiteral ss _ _ -> ss
47
50
48
51
-- | Find all literals in a Parsed Source File
49
- collectLiterals :: (Data ast , Typeable ast ) => ast -> [Literal ]
50
- collectLiterals = S. toList . collectLiterals'
51
-
52
- collectLiterals' :: (Data ast , Typeable ast ) => ast -> Set Literal
53
- collectLiterals' = everything (<>) (mkQ2 (S. empty :: Set Literal ) traverseLExpr traverseLPat)
54
-
55
- -- Located Patterns for whatever reason don't get picked up when using `(mkQ (S.empty :: Set Literal) traverseLExpr)
56
- -- as such we need to explicit traverse those in order to pull out any literals
57
- mkQ2 :: (Typeable a , Typeable b , Typeable c ) => r -> (b -> r ) -> (c -> r ) -> a -> r
58
- mkQ2 def left right datum = case cast datum of
59
- Just datum' -> left datum'
60
- Nothing -> maybe def right (cast datum)
61
-
62
- traverseLPat :: GenLocated SrcSpan (Pat GhcPs ) -> Set Literal
63
- traverseLPat (L sSpan pat) = traversePat sSpan pat
64
-
65
- traversePat :: SrcSpan -> Pat GhcPs -> Set Literal
66
- traversePat sSpan = \ case
67
- LitPat _ lit -> getLiteralAsList sSpan lit
68
- NPat _ (L olSpan overLit) sexpr1 sexpr2 -> getOverLiteralAsList olSpan overLit
69
- <> collectLiterals' sexpr1
70
- <> collectLiterals' sexpr2
71
- NPlusKPat _ _ (L olSpan loverLit) overLit sexpr1 sexpr2 -> getOverLiteralAsList olSpan loverLit
72
- <> getOverLiteralAsList sSpan overLit
73
- <> collectLiterals' sexpr1
74
- <> collectLiterals' sexpr2
75
- ast -> collectLiterals' ast
76
-
77
- traverseLExpr :: GenLocated SrcSpan (HsExpr GhcPs ) -> Set Literal
78
- traverseLExpr (L sSpan hsExpr) = traverseExpr sSpan hsExpr
79
-
80
- traverseExpr :: SrcSpan -> HsExpr GhcPs -> Set Literal
81
- traverseExpr sSpan = \ case
82
- HsOverLit _ overLit -> getOverLiteralAsList sSpan overLit
83
- HsLit _ lit -> getLiteralAsList sSpan lit
84
- expr -> collectLiterals' expr
52
+ collectLiterals' :: (Data ast , Typeable ast ) => ast -> [Literal ]
53
+ collectLiterals' = mapMaybe getLiteral . listify isReal
54
+ where
55
+ isReal :: GenLocated SrcSpan (HsExpr GhcPs ) -> Bool
56
+ isReal (L (RealSrcSpan _ _) lit) = case lit of
57
+ HsLit {} -> True
58
+ HsOverLit {} -> True
59
+ _ -> False
60
+ isReal _ = False
85
61
86
- getLiteralAsList :: SrcSpan -> HsLit GhcPs -> Set Literal
87
- getLiteralAsList sSpan lit = case sSpan of
88
- RealSrcSpan rss _ -> getLiteralAsList' lit rss
89
- _ -> S. empty
90
-
91
- getLiteralAsList' :: HsLit GhcPs -> RealSrcSpan -> Set Literal
92
- getLiteralAsList' lit = maybe S. empty S. singleton . flip getLiteral lit
93
-
94
- -- Translate from Hs Type to our Literal type
95
- getLiteral :: RealSrcSpan -> HsLit GhcPs -> Maybe Literal
96
- getLiteral sSpan = \ case
97
- HsInt _ val -> fromIntegralLit sSpan val
98
- HsRat _ val _ -> fromFractionalLit sSpan val
99
- _ -> Nothing
100
-
101
- getOverLiteralAsList :: SrcSpan -> HsOverLit GhcPs -> Set Literal
102
- getOverLiteralAsList sSpan lit = case sSpan of
103
- RealSrcSpan rss _ -> getOverLiteralAsList' lit rss
104
- _ -> S. empty
105
-
106
- getOverLiteralAsList' :: HsOverLit GhcPs -> RealSrcSpan -> Set Literal
107
- getOverLiteralAsList' lit sSpan = maybe S. empty S. singleton (getOverLiteral sSpan lit)
108
-
109
- getOverLiteral :: RealSrcSpan -> HsOverLit GhcPs -> Maybe Literal
110
- getOverLiteral sSpan OverLit {.. } = case ol_val of
111
- HsIntegral il -> fromIntegralLit sSpan il
112
- HsFractional fl -> fromFractionalLit sSpan fl
113
- _ -> Nothing
114
- getOverLiteral _ _ = Nothing
62
+ collectLiterals :: (Data ast , Typeable ast ) => ast -> [Literal ]
63
+ collectLiterals = everything (<>) (mkQ ([] :: [Literal ]) (maybeToList . getLiteral))
64
+
65
+ -- | Translate from HsLit and HsOverLit Types to our Literal Type
66
+ getLiteral :: GenLocated SrcSpan (HsExpr GhcPs ) -> Maybe Literal
67
+ getLiteral (L (UnhelpfulSpan _) _) = Nothing
68
+ getLiteral (L (RealSrcSpan sSpan _ ) lit) = case lit of
69
+ -- only want
70
+ HsLit _ lit -> case lit of
71
+ HsInt _ val -> fromIntegralLit sSpan val
72
+ HsRat _ val _ -> fromFractionalLit sSpan val
73
+ _ -> Nothing
74
+ HsOverLit _ OverLit {.. } -> case ol_val of
75
+ HsIntegral il -> fromIntegralLit sSpan il
76
+ HsFractional fl -> fromFractionalLit sSpan fl
77
+ _ -> Nothing
78
+ _ -> Nothing
115
79
116
80
fromIntegralLit :: RealSrcSpan -> IntegralLit -> Maybe Literal
117
81
fromIntegralLit s (IL txt _ val) = fmap (\ txt' -> IntLiteral s txt' val) (fromSourceText txt)
0 commit comments