Skip to content

Commit ecf65d7

Browse files
committed
Remove unused function haddock comment
* Tweak unused binding test * Refactor findRelatedSigSpan to avoid inner let * Use epaLocationRealSrcSpan * Revert unused annotated type * Fixup for GHC 9.10 * Just give up for GHC=<9.8 * Add comments
1 parent ca4534a commit ecf65d7

2 files changed

Lines changed: 59 additions & 26 deletions

File tree

plugins/hls-refactor-plugin/src/Development/IDE/Plugin/CodeAction.hs

Lines changed: 56 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -118,17 +118,20 @@ import GHC (AddEpAnn (Ad
118118
#if MIN_VERSION_ghc(9,9,0) && !MIN_VERSION_ghc(9,11,0)
119119
import GHC (AddEpAnn (AddEpAnn),
120120
AnnsModule (am_main),
121+
EpAnnComments (..),
121122
EpaLocation,
122123
EpaLocation' (..),
123124
HasLoc (..))
124125
#endif
125126

126127
#if MIN_VERSION_ghc(9,11,0)
127128
import GHC (AnnsModule (am_where),
129+
EpAnnComments (..),
128130
EpToken (..),
129131
EpaLocation,
130132
EpaLocation' (..),
131133
HasLoc (..))
134+
import GHC.Parser.Annotation (epaLocationRealSrcSpan)
132135
#endif
133136

134137

@@ -141,7 +144,7 @@ codeAction state _ (CodeActionParams _ _ (TextDocumentIdentifier uri) range _) =
141144
liftIO $ do
142145
let mbFile = toNormalizedFilePath' <$> uriToFilePath uri
143146
allDiags <- atomically $ fmap fdLspDiagnostic . filter (\d -> mbFile == Just (fdFilePath d)) <$> getDiagnostics state
144-
(join -> parsedModule) <- runAction "GhcideCodeActions.getParsedModule" state $ getParsedModule `traverse` mbFile
147+
(join -> parsedModule) <- runAction "GhcideCodeActions.getParsedModule" state $ getParsedModuleWithComments `traverse` mbFile
145148
let
146149
textContents = fmap Rope.toText contents
147150
actions = caRemoveRedundantImports parsedModule textContents allDiags range uri
@@ -601,29 +604,25 @@ suggestDeleteUnusedBinding
601604
-- Foo.hs:4:1: warning: [-Wunused-binds] Defined but not used: ‘f’
602605
| Just [name] <- matchRegexUnifySpaces _message ".*Defined but not used: ‘([^ ]+)’"
603606
, Just indexedContent <- indexedByPosition . T.unpack <$> contents
604-
= let edits = flip TextEdit "" <$> relatedRanges indexedContent (T.unpack name)
607+
= let edits = flip TextEdit "" <$> mergeRanges (sortOn _start $ relatedRanges indexedContent (T.unpack name))
605608
in ([("Delete ‘" <> name <> "", edits) | not (null edits)])
606609
| otherwise = []
607610
where
611+
hsmodSigs = [L l sig | L l (SigD _ sig) <- hsmodDecls]
608612
relatedRanges indexedContent name =
609613
concatMap (findRelatedSpans indexedContent name . reLoc) hsmodDecls
610614
toRange = realSrcSpanToRange
611615
extendForSpaces = extendToIncludePreviousNewlineIfPossible
612616

613617
findRelatedSpans :: PositionIndexedString -> String -> Located (HsDecl GhcPs) -> [Range]
614-
findRelatedSpans
615-
indexedContent
616-
name
617-
(L (RealSrcSpan l _) (ValD _ (extractNameAndMatchesFromFunBind -> Just (lname, matches)))) =
618-
case lname of
618+
findRelatedSpans indexedContent name decl = case decl of
619+
(L (RealSrcSpan l _) (ValD _ (extractNameAndMatchesFromFunBind -> Just (lname, matches))))
620+
-> case lname of
619621
(L nLoc _name) | isTheBinding nLoc ->
620-
let findSig (L (RealSrcSpan l _) (SigD _ sig)) = findRelatedSigSpan indexedContent name l sig
621-
findSig _ = []
622-
in
623-
extendForSpaces indexedContent (toRange l) :
624-
concatMap (findSig . reLoc) hsmodDecls
622+
extendForSpaces indexedContent (toRange l)
623+
: concatMap (findRelatedSigSpan' indexedContent name) hsmodSigs
625624
_ -> concatMap (findRelatedSpanForMatch indexedContent name) matches
626-
findRelatedSpans _ _ _ = []
625+
_ -> []
627626

628627
extractNameAndMatchesFromFunBind
629628
:: HsBind GhcPs
@@ -635,13 +634,23 @@ suggestDeleteUnusedBinding
635634
} = Just (reLoc lname, matches)
636635
extractNameAndMatchesFromFunBind _ = Nothing
637636

638-
findRelatedSigSpan :: PositionIndexedString -> String -> RealSrcSpan -> Sig GhcPs -> [Range]
639-
findRelatedSigSpan indexedContent name l sig =
640-
let maybeSpan = findRelatedSigSpan1 name sig
641-
in case maybeSpan of
642-
Just (_span, True) -> pure $ extendForSpaces indexedContent $ toRange l -- a :: Int
643-
Just (RealSrcSpan span _, False) -> pure $ toRange span -- a, b :: Int, a is unused
644-
_ -> []
637+
-- | For given name, find the span of related type signature.
638+
findRelatedSigSpan' :: PositionIndexedString -> String -> LSig GhcPs -> [Range]
639+
findRelatedSigSpan' indexedContent name = \case
640+
#if MIN_VERSION_ghc(9,9,0)
641+
(L (EpAnn sigSpan _ c) sig) ->
642+
let l = epaLocationRealSrcSpan sigSpan
643+
in case findRelatedSigSpan1 name sig of
644+
-- On GHC 9.10+ this will include Haddock comments.
645+
Just (_span, True) -> pure . extendForSpaces indexedContent . toRange $ l `withCommentSpan` c
646+
#else
647+
(reLoc -> L (RealSrcSpan l _) sig) ->
648+
case findRelatedSigSpan1 name sig of
649+
Just (_span, True) -> pure . extendForSpaces indexedContent . toRange $ l
650+
#endif
651+
Just (RealSrcSpan span _, False) -> pure $ toRange span
652+
_ -> []
653+
_ -> []
645654

646655
-- Second of the tuple means there is only one match
647656
findRelatedSigSpan1 :: String -> Sig GhcPs -> Maybe (SrcSpan, Bool)
@@ -712,10 +721,8 @@ suggestDeleteUnusedBinding
712721
lsigs
713722
(L (locA -> (RealSrcSpan l _)) (extractNameAndMatchesFromFunBind -> Just (lname, matches))) =
714723
if isTheBinding (getLoc lname)
715-
then
716-
let findSig (L (RealSrcSpan l _) sig) = findRelatedSigSpan indexedContent name l sig
717-
findSig _ = []
718-
in extendForSpaces indexedContent (toRange l) : concatMap (findSig . reLoc) lsigs
724+
then extendForSpaces indexedContent (toRange l)
725+
: concatMap (findRelatedSigSpan' indexedContent name) lsigs
719726
else concatMap (findRelatedSpanForMatch indexedContent name) matches
720727
findRelatedSpanForHsBind _ _ _ _ = []
721728

@@ -2126,3 +2133,28 @@ matchRegExMultipleImports message = do
21262133
_ -> Nothing
21272134
imps <- regExImports imports
21282135
return (binding, imps)
2136+
2137+
#if MIN_VERSION_ghc(9,9,0)
2138+
-- | Expand signature span to include Haddock.
2139+
withCommentSpan :: RealSrcSpan -> EpAnnComments -> RealSrcSpan
2140+
withCommentSpan idL = foldl' combineRealSrcSpans idL . map commsSrc . commsToList
2141+
where
2142+
commsSrc :: GenLocated (EpaLocation' a) e -> RealSrcSpan
2143+
commsSrc (L l _) = epaLocationRealSrcSpan l
2144+
commsToList :: EpAnnComments -> [LEpaComment]
2145+
commsToList = \case
2146+
EpaComments prior -> prior
2147+
EpaCommentsBalanced prior following -> prior <> following
2148+
#endif
2149+
2150+
#if MIN_VERSION_ghc(9,9,0) && !MIN_VERSION_ghc(9,11,0)
2151+
-- | Used in the parser only, extract the 'RealSrcSpan' from an
2152+
-- 'EpaLocation'. The parser will never insert a 'DeltaPos', so the
2153+
-- partial function is safe.
2154+
--
2155+
-- GHC compatibility note:
2156+
-- EpaLocation' exists since 9.10, but this function was updated in 9.12
2157+
epaLocationRealSrcSpan :: EpaLocation' a -> RealSrcSpan
2158+
epaLocationRealSrcSpan (EpaSpan (RealSrcSpan r _)) = r
2159+
epaLocationRealSrcSpan _ = panic "epaLocationRealSrcSpan"
2160+
#endif

plugins/hls-refactor-plugin/test/Main.hs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2538,8 +2538,9 @@ deleteUnusedDefinitionTests = testGroup "delete unused definition action"
25382538
[ "{-# OPTIONS_GHC -Wunused-top-binds #-}"
25392539
, "module A (some) where"
25402540
, ""
2541-
, "-- | docs for f"
2541+
, "-- | line docs for f"
25422542
, "f :: Int"
2543+
-- TODO: , "-- ^ trailing docs for f"
25432544
, "f = 1"
25442545
, ""
25452546
, "some = ()"
@@ -2557,7 +2558,7 @@ deleteUnusedDefinitionTests = testGroup "delete unused definition action"
25572558
[ "{-# OPTIONS_GHC -Wunused-top-binds #-}"
25582559
, "module A (some) where"
25592560
, ""
2560-
, "{-| docs for f"
2561+
, "{-| block docs for f"
25612562
, "-}"
25622563
, "f :: Int"
25632564
, "f = 1"

0 commit comments

Comments
 (0)