Skip to content

Commit f21ea28

Browse files
authored
Add code action for importing class methods (#1428)
* Add code action for importing class methods * Format ExactPrint * Format CodeAction * Reformat ExactPrint
1 parent 679f1d0 commit f21ea28

File tree

3 files changed

+410
-230
lines changed

3 files changed

+410
-230
lines changed

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

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ suggestAction packageExports ideOptions parsedModule text df annSource tcM har d
153153
, rewrite df annSource $ \_ ps -> suggestExtendImport packageExports ps diag
154154
, rewrite df annSource $ \df ps ->
155155
suggestImportDisambiguation df text ps diag
156+
, rewrite df annSource $ \_ ps -> suggestNewOrExtendImportForClassMethod packageExports ps diag
156157
, suggestFillTypeWildcard diag
157158
, suggestFixConstructorImport text diag
158159
, suggestModuleTypo diag
@@ -769,8 +770,6 @@ suggestExtendImport exportsMap (L _ HsModule {hsmodImports}) Diagnostic{_range=_
769770
= mod_srcspan >>= uncurry (suggestions hsmodImports binding)
770771
| otherwise = []
771772
where
772-
unImportStyle (ImportTopLevel x) = (Nothing, T.unpack x)
773-
unImportStyle (ImportViaParent x y) = (Just $ T.unpack y, T.unpack x)
774773
suggestions decls binding mod srcspan
775774
| range <- case [ x | (x,"") <- readSrcSpan (T.unpack srcspan)] of
776775
[s] -> let x = realSrcSpanToRange s
@@ -1158,6 +1157,39 @@ removeRedundantConstraints mContents Diagnostic{..}
11581157

11591158
-------------------------------------------------------------------------------------------------
11601159

1160+
suggestNewOrExtendImportForClassMethod :: ExportsMap -> ParsedSource -> Diagnostic -> [(T.Text, [Rewrite])]
1161+
suggestNewOrExtendImportForClassMethod packageExportsMap ps Diagnostic {_message}
1162+
| Just [methodName, className] <-
1163+
matchRegexUnifySpaces
1164+
_message
1165+
"‘([^’]*)’ is not a \\(visible\\) method of class ‘([^’]*)’",
1166+
idents <-
1167+
maybe [] (Set.toList . Set.filter (\x -> parent x == Just className)) $
1168+
Map.lookup methodName $ getExportsMap packageExportsMap =
1169+
mconcat $ suggest <$> idents
1170+
| otherwise = []
1171+
where
1172+
suggest identInfo@IdentInfo {moduleNameText}
1173+
| importStyle <- NE.toList $ importStyles identInfo,
1174+
mImportDecl <- findImportDeclByModuleName (hsmodImports $ unLoc ps) (T.unpack moduleNameText) =
1175+
case mImportDecl of
1176+
-- extend
1177+
Just decl ->
1178+
[ ( "Add " <> renderImportStyle style <> " to the import list of " <> moduleNameText,
1179+
[uncurry extendImport (unImportStyle style) decl]
1180+
)
1181+
| style <- importStyle
1182+
]
1183+
-- new
1184+
_ ->
1185+
[ ( "Import " <> moduleNameText <> " with " <> rendered,
1186+
maybeToList $ newUnqualImport (T.unpack moduleNameText) (T.unpack rendered) False ps
1187+
)
1188+
| style <- importStyle,
1189+
let rendered = renderImportStyle style
1190+
]
1191+
<> maybeToList (("Import " <> moduleNameText,) <$> fmap pure (newImportAll (T.unpack moduleNameText) ps))
1192+
11611193
suggestNewImport :: ExportsMap -> ParsedModule -> Diagnostic -> [(T.Text, [TextEdit])]
11621194
suggestNewImport packageExportsMap ParsedModule {pm_parsed_source = L _ HsModule {..}} Diagnostic{_message}
11631195
| msg <- unifySpaces _message
@@ -1451,3 +1483,6 @@ renderImportStyle :: ImportStyle -> T.Text
14511483
renderImportStyle (ImportTopLevel x) = x
14521484
renderImportStyle (ImportViaParent x p) = p <> "(" <> x <> ")"
14531485

1486+
unImportStyle :: ImportStyle -> (Maybe String, String)
1487+
unImportStyle (ImportTopLevel x) = (Nothing, T.unpack x)
1488+
unImportStyle (ImportViaParent x y) = (Just $ T.unpack y, T.unpack x)

0 commit comments

Comments
 (0)