@@ -72,7 +72,6 @@ import Outputable (Outputable,
72
72
showSDocUnsafe )
73
73
import RdrName (GlobalRdrElt (.. ),
74
74
lookupGlobalRdrEnv )
75
- import Safe (atMay )
76
75
import SrcLoc (realSrcSpanEnd ,
77
76
realSrcSpanStart )
78
77
import TcRnTypes (ImportAvails (.. ),
@@ -162,6 +161,32 @@ findSigOfDecl pred decls =
162
161
any (pred . unLoc) idsSig
163
162
]
164
163
164
+ findSigOfDecl' :: Range -> [LHsDecl p ] -> Either String (Sig p )
165
+ findSigOfDecl' range decls = do
166
+ dec <- findDeclContainingLocE (_start range) decls
167
+ case dec of
168
+ L _ (SigD _ sig@ TypeSig ) -> Right sig
169
+ L _ (ValD _ (bind :: HsBind p )) -> findSigOfBind range bind
170
+ _ -> Left " Other"
171
+
172
+ findSigOfBind :: Range -> HsBind p -> Either String (Sig p )
173
+ findSigOfBind range bind =
174
+ case bind of
175
+ FunBind {} -> findSigOfLMatch (unLoc $ mg_alts (fun_matches bind))
176
+ _ -> Left " Other findSigOfBind"
177
+ where
178
+ findSigOfLMatch :: [LMatch p (LHsExpr idR )] -> Either String (Sig p )
179
+ findSigOfLMatch ls = do
180
+ 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"
185
+
186
+ findDeclContainingLocE :: Position -> [Located a ] -> Either String (Located a )
187
+ findDeclContainingLocE loc ls =
188
+ maybe (Left " findDeclContainingLoc" ) Right $ findDeclContainingLoc loc ls
189
+
165
190
findInstanceHead :: (Outputable (HsType p )) => DynFlags -> String -> [LHsDecl p ] -> Maybe (LHsType p )
166
191
findInstanceHead df instanceHead decls =
167
192
listToMaybe
@@ -173,6 +198,7 @@ findInstanceHead df instanceHead decls =
173
198
findDeclContainingLoc :: Position -> [Located a ] -> Maybe (Located a )
174
199
findDeclContainingLoc loc = find (\ (L l _) -> loc `isInsideSrcSpan` l)
175
200
201
+
176
202
-- Single:
177
203
-- This binding for ‘mod’ shadows the existing binding
178
204
-- imported from ‘Prelude’ at haskell-language-server/ghcide/src/Development/IDE/Plugin/CodeAction.hs:10:8-40
@@ -1020,10 +1046,6 @@ suggestImplicitParameter (L _ HsModule {hsmodDecls}) Diagnostic {_message, _rang
1020
1046
findTypeSignatureName :: T. Text -> Maybe T. Text
1021
1047
findTypeSignatureName t = matchRegexUnifySpaces t " ([^ ]+) :: " <&> head
1022
1048
1023
- findTypeSignatureLine :: T. Text -> T. Text -> Int
1024
- findTypeSignatureLine contents typeSignatureName =
1025
- T. splitOn (typeSignatureName <> " :: " ) contents & head & T. lines & length
1026
-
1027
1049
-- | Suggests a constraint for a type signature with any number of existing constraints.
1028
1050
suggestFunctionConstraint :: DynFlags -> ParsedSource -> Diagnostic -> T. Text -> [(T. Text , Rewrite )]
1029
1051
@@ -1062,31 +1084,26 @@ suggestFunctionConstraint df (L _ HsModule {hsmodDecls}) Diagnostic {..} missing
1062
1084
<> " ` to the context of the type signature for `" <> typeSignatureName <> " `"
1063
1085
1064
1086
-- | Suggests the removal of a redundant constraint for a type signature.
1065
- removeRedundantConstraints :: Maybe T. Text -> Diagnostic -> [(T. Text , TextEdit )]
1066
- removeRedundantConstraints mContents Diagnostic {.. }
1087
+ removeRedundantConstraints :: DynFlags -> ParsedSource -> Diagnostic -> [(T. Text , Rewrite )]
1088
+ removeRedundantConstraints df ( L _ HsModule {hsmodDecls}) Diagnostic {.. }
1067
1089
-- • Redundant constraint: Eq a
1068
1090
-- • In the type signature for:
1069
1091
-- foo :: forall a. Eq a => a -> a
1070
1092
-- • Redundant constraints: (Monoid a, Show a)
1071
1093
-- • In the type signature for:
1072
1094
-- foo :: forall a. (Num a, Monoid a, Eq a, Show a) => a -> Bool
1073
- | Just contents <- mContents
1074
1095
-- Account for both "Redundant constraint" and "Redundant constraints".
1075
- , True <- " Redundant constraint" `T.isInfixOf` _message
1096
+ | " Redundant constraint" `T.isInfixOf` _message
1076
1097
, Just typeSignatureName <- findTypeSignatureName _message
1098
+ , Right (TypeSig _ _ HsWC {hswc_body = HsIB {hsib_body = sig}})
1099
+ <- findSigOfDecl' _range hsmodDecls
1077
1100
, Just redundantConstraintList <- findRedundantConstraints _message
1078
- , Just constraints <- findConstraints contents typeSignatureName
1079
- = let constraintList = parseConstraints constraints
1080
- newConstraints = buildNewConstraints constraintList redundantConstraintList
1081
- typeSignatureLine = findTypeSignatureLine contents typeSignatureName
1082
- typeSignatureFirstChar = T. length $ typeSignatureName <> " :: "
1083
- startOfConstraint = Position typeSignatureLine typeSignatureFirstChar
1084
- endOfConstraint = Position typeSignatureLine $
1085
- typeSignatureFirstChar + T. length (constraints <> " => " )
1086
- range = Range startOfConstraint endOfConstraint
1087
- in [(actionTitle redundantConstraintList typeSignatureName, TextEdit range newConstraints)]
1101
+ , rewrite <- removeConstraint (pred df redundantConstraintList) sig
1102
+ = [(actionTitle redundantConstraintList typeSignatureName, rewrite)]
1088
1103
| otherwise = []
1089
1104
where
1105
+ pred df list a = showSDoc df (ppr a) `elem` (T. unpack <$> list)
1106
+
1090
1107
parseConstraints :: T. Text -> [T. Text ]
1091
1108
parseConstraints t = t
1092
1109
& (T. strip >>> stripConstraintsParens >>> T. splitOn " ," )
@@ -1106,32 +1123,13 @@ removeRedundantConstraints mContents Diagnostic{..}
1106
1123
& (`matchRegexUnifySpaces` " Redundant constraints?: (.+)" )
1107
1124
<&> (head >>> parseConstraints)
1108
1125
1109
- -- If the type signature is not formatted as expected (arbitrary number of spaces,
1110
- -- line feeds...), just fail.
1111
- findConstraints :: T. Text -> T. Text -> Maybe T. Text
1112
- findConstraints contents typeSignatureName = do
1113
- constraints <- contents
1114
- & T. splitOn (typeSignatureName <> " :: " )
1115
- & (`atMay` 1 )
1116
- >>= (T. splitOn " => " >>> (`atMay` 0 ))
1117
- guard $ not $ " \n " `T.isInfixOf` constraints || T. strip constraints /= constraints
1118
- return constraints
1119
-
1120
1126
formatConstraints :: [T. Text ] -> T. Text
1121
1127
formatConstraints [] = " "
1122
1128
formatConstraints [constraint] = constraint
1123
1129
formatConstraints constraintList = constraintList
1124
1130
& T. intercalate " , "
1125
1131
& \ cs -> " (" <> cs <> " )"
1126
1132
1127
- formatConstraintsWithArrow :: [T. Text ] -> T. Text
1128
- formatConstraintsWithArrow [] = " "
1129
- formatConstraintsWithArrow cs = cs & formatConstraints & (<> " => " )
1130
-
1131
- buildNewConstraints :: [T. Text ] -> [T. Text ] -> T. Text
1132
- buildNewConstraints constraintList redundantConstraintList =
1133
- formatConstraintsWithArrow $ constraintList \\ redundantConstraintList
1134
-
1135
1133
actionTitle :: [T. Text ] -> T. Text -> T. Text
1136
1134
actionTitle constraintList typeSignatureName =
1137
1135
" Remove redundant constraint" <> (if length constraintList == 1 then " " else " s" ) <> " `"
0 commit comments