Skip to content

Commit 998c89f

Browse files
committed
Find signatures which are deeply nested
1 parent de0c69d commit 998c89f

File tree

2 files changed

+75
-12
lines changed

2 files changed

+75
-12
lines changed

ghcide/src/Development/IDE/Plugin/CodeAction.hs

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ module Development.IDE.Plugin.CodeAction
1414
, matchRegExMultipleImports
1515
) where
1616

17-
import Bag (isEmptyBag)
17+
import Bag (bagToList,
18+
isEmptyBag)
1819
import Control.Applicative ((<|>))
1920
import Control.Arrow (second,
2021
(>>>))
@@ -161,27 +162,51 @@ findSigOfDecl pred decls =
161162
any (pred . unLoc) idsSig
162163
]
163164

164-
findSigOfDecl' :: Range -> [LHsDecl p] -> Either String (Sig p)
165-
findSigOfDecl' range decls = do
165+
findSigOfDeclRanged :: Range -> [LHsDecl p] -> Either String (Sig p)
166+
findSigOfDeclRanged range decls = do
166167
dec <- findDeclContainingLocE (_start range) decls
167168
case dec of
168-
L _ (SigD _ sig@TypeSig ) -> Right sig
169+
L _ (SigD _ sig@TypeSig {}) -> Right sig
169170
L _ (ValD _ (bind :: HsBind p)) -> findSigOfBind range bind
170-
_ -> Left "Other"
171+
_ -> Left "findSigOfDeclRanged"
171172

172173
findSigOfBind :: Range -> HsBind p -> Either String (Sig p)
173174
findSigOfBind range bind =
174175
case bind of
175176
FunBind {} -> findSigOfLMatch (unLoc $ mg_alts (fun_matches bind))
176-
_ -> Left "Other findSigOfBind"
177+
_ -> Left "findSigOfBind"
177178
where
178-
findSigOfLMatch :: [LMatch p (LHsExpr idR)] -> Either String (Sig p)
179+
findSigOfLMatch :: [LMatch p (LHsExpr p)] -> Either String (Sig p)
179180
findSigOfLMatch ls = do
180181
match <- findDeclContainingLocE (_start range) ls
181-
case unLoc (grhssLocalBinds (m_grhss (unLoc match))) of
182-
HsValBinds _ (ValBinds _ _ lsigs) ->
183-
unLoc <$> findDeclContainingLocE (_start range) lsigs
184-
_ -> Left "Other findSigOfLMatch"
182+
findSigOfGRHSs (m_grhss (unLoc match))
183+
184+
findSigOfGRHSs :: GRHSs p (LHsExpr p) -> Either String (Sig p)
185+
findSigOfGRHSs grhs = do
186+
if _start range `isInsideSrcSpan` (getLoc $ grhssLocalBinds grhs)
187+
then findSigOfBinds range (unLoc (grhssLocalBinds grhs)) -- where clause
188+
else do
189+
grhs <- findDeclContainingLocE (_start range) (grhssGRHSs grhs)
190+
case unLoc grhs of
191+
GRHS _ _ bd -> findSigOfExpr (unLoc bd)
192+
_ -> Left "findSigOfGRHSs"
193+
194+
findSigOfExpr :: HsExpr p -> Either String (Sig p)
195+
findSigOfExpr = go
196+
where
197+
go (HsLet _ binds _) = findSigOfBinds range (unLoc binds)
198+
go _ = Left "findSigOfExpr"
199+
200+
findSigOfBinds :: Range -> HsLocalBinds p -> Either String (Sig p)
201+
findSigOfBinds range = go
202+
where
203+
go (HsValBinds _ (ValBinds _ binds lsigs)) =
204+
case unLoc <$> findDeclContainingLocE (_start range) lsigs of
205+
Right sig' -> Right sig'
206+
Left _ -> do
207+
lHsBindLR <- findDeclContainingLocE (_start range) (bagToList binds)
208+
findSigOfBind range (unLoc lHsBindLR)
209+
go _ = Left "findSigOfBinds"
185210

186211
findDeclContainingLocE :: Position -> [Located a] -> Either String (Located a)
187212
findDeclContainingLocE loc ls =
@@ -1096,7 +1121,7 @@ removeRedundantConstraints df (L _ HsModule {hsmodDecls}) Diagnostic{..}
10961121
| "Redundant constraint" `T.isInfixOf` _message
10971122
, Just typeSignatureName <- findTypeSignatureName _message
10981123
, Right (TypeSig _ _ HsWC{hswc_body = HsIB {hsib_body = sig}})
1099-
<- findSigOfDecl' _range hsmodDecls
1124+
<- findSigOfDeclRanged _range hsmodDecls
11001125
, Just redundantConstraintList <- findRedundantConstraints _message
11011126
, rewrite <- removeConstraint (pred df redundantConstraintList) sig
11021127
= [(actionTitle redundantConstraintList typeSignatureName, rewrite)]

ghcide/test/exe/Main.hs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2631,6 +2631,36 @@ removeRedundantConstraintsTests = let
26312631
, " g _ = ()"
26322632
]
26332633

2634+
typeSignatureNested' :: Maybe T.Text -> T.Text
2635+
typeSignatureNested' mConstraint =
2636+
let constraint = maybe "" (\c -> "" <> c <> " => ") mConstraint
2637+
in T.unlines $ header <>
2638+
[ "f :: Int -> ()"
2639+
, "f ="
2640+
, " let"
2641+
, " g :: Int -> ()"
2642+
, " g = h"
2643+
, " where"
2644+
, " h :: " <> constraint <> "a -> ()"
2645+
, " h _ = ()"
2646+
, " in g"
2647+
]
2648+
2649+
typeSignatureNested'' :: Maybe T.Text -> T.Text
2650+
typeSignatureNested'' mConstraint =
2651+
let constraint = maybe "" (\c -> "" <> c <> " => ") mConstraint
2652+
in T.unlines $ header <>
2653+
[ "f :: Int -> ()"
2654+
, "f = g"
2655+
, " where"
2656+
, " g :: Int -> ()"
2657+
, " g = "
2658+
, " let"
2659+
, " h :: " <> constraint <> "a -> ()"
2660+
, " h _ = ()"
2661+
, " in h"
2662+
]
2663+
26342664
typeSignatureMultipleLines :: T.Text
26352665
typeSignatureMultipleLines = T.unlines $ header <>
26362666
[ "foo :: (Num a, Eq a, Monoid a)"
@@ -2672,6 +2702,14 @@ removeRedundantConstraintsTests = let
26722702
"Remove redundant constraint `Eq a` from the context of the type signature for `g`"
26732703
(typeSignatureNested $ Just "Eq a")
26742704
(typeSignatureNested Nothing)
2705+
, check
2706+
"Remove redundant constraint `Eq a` from the context of the type signature for `h`"
2707+
(typeSignatureNested' $ Just "Eq a")
2708+
(typeSignatureNested' Nothing)
2709+
, check
2710+
"Remove redundant constraint `Eq a` from the context of the type signature for `h`"
2711+
(typeSignatureNested'' $ Just "Eq a")
2712+
(typeSignatureNested'' Nothing)
26752713
, check
26762714
"Remove redundant constraint `Eq a` from the context of the type signature for `foo`"
26772715
(redundantConstraintsForall $ Just "Eq a")

0 commit comments

Comments
 (0)