@@ -118,17 +118,20 @@ import GHC (AddEpAnn (Ad
118118#if MIN_VERSION_ghc(9,9,0) && !MIN_VERSION_ghc(9,11,0)
119119import 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)
127128import 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
0 commit comments