@@ -49,6 +49,7 @@ import Development.IDE.Core.Service
4949import Development.IDE.Core.Shake hiding (Log )
5050import Development.IDE.GHC.Compat hiding
5151 (ImplicitPrelude )
52+ import qualified Language.LSP.Protocol.Types as TE (TextEdit (.. ))
5253#if !MIN_VERSION_ghc(9,11,0)
5354import Development.IDE.GHC.Compat.Util
5455#endif
@@ -144,6 +145,7 @@ codeAction state _ (CodeActionParams _ _ (TextDocumentIdentifier uri) range _) =
144145 textContents = fmap Rope. toText contents
145146 actions = caRemoveRedundantImports parsedModule textContents allDiags range uri
146147 <> caRemoveInvalidExports parsedModule textContents allDiags range uri
148+ <> caDeleteUnusedBindings parsedModule textContents allDiags range uri
147149 pure $ InL actions
148150
149151-------------------------------------------------------------------------------------------------
@@ -185,7 +187,6 @@ bindingsPluginDescriptor recorder plId = mkExactprintPluginDescriptor recorder $
185187 , wrap suggestImplicitParameter
186188 , wrap suggestNewDefinition
187189 , wrap Development.IDE.Plugin.Plugins.AddArgument. plugin
188- , wrap suggestDeleteUnusedBinding
189190 ]
190191 plId
191192 " Provides various quick fixes for bindings"
@@ -710,6 +711,47 @@ suggestDeleteUnusedBinding
710711 isSameName :: IdP GhcPs -> String -> Bool
711712 isSameName x name = T. unpack (printOutputable x) == name
712713
714+ caDeleteUnusedBindings :: Maybe ParsedModule -> Maybe T. Text -> [Diagnostic ] -> Range -> Uri -> [Command |? CodeAction ]
715+ caDeleteUnusedBindings m contents allDiags contextRange uri
716+ | Just pm <- m,
717+ r <- join $ map (\ d -> repeat d `zip` suggestDeleteUnusedBinding pm contents d) allDiags,
718+ -- `allEdits` contains the representative edits to make.
719+ -- Representative means the edit with a range that subsumes the others,
720+ -- because GHC emits diagnostics for the top level binding *and* the where clause.
721+ allEdits <-
722+ -- take the representative and drop the others
723+ concatMap headToList $
724+ -- deduplicate by creating groups of ranges (same group if any subsumes the other)
725+ groupBy subsumesEither
726+ -- Sort to put related ranges next to each other
727+ (sortOn TE. _range [ e | (_, (_, edits)) <- r, e <- edits]),
728+ caRemoveAll <- removeAll allEdits,
729+ ctxEdits <- [ x | x@ (d, _) <- r, d `diagInRange` contextRange],
730+ not $ null ctxEdits,
731+ caRemoveCtx <- map (\ (d, (title, tedit)) -> removeSingle title tedit d) ctxEdits
732+ = caRemoveCtx ++ [caRemoveAll]
733+ | otherwise = []
734+ where
735+ removeSingle title tedit diagnostic = mkCA title (Just CodeActionKind_QuickFix ) Nothing [diagnostic] WorkspaceEdit {.. } where
736+ _changes = Just $ M. singleton uri tedit
737+ _documentChanges = Nothing
738+ _changeAnnotations = Nothing
739+ removeAll tedit = InR $ CodeAction {.. } where
740+ _changes = Just $ M. singleton uri tedit
741+ _title = " Delete all unused bindings"
742+ _kind = Just CodeActionKind_QuickFix
743+ _diagnostics = Nothing
744+ _documentChanges = Nothing
745+ _edit = Just WorkspaceEdit {.. }
746+ _isPreferred = Just False
747+ _command = Nothing
748+ _disabled = Nothing
749+ _data_ = Nothing
750+ _changeAnnotations = Nothing
751+ headToList [] = []
752+ headToList (x : _) = [x]
753+ subsumesEither (TE. _range -> range1) (TE. _range -> range2) = subRange range1 range2 || subRange range1 range2
754+
713755data ExportsAs = ExportName | ExportPattern | ExportFamily | ExportAll
714756 deriving (Eq )
715757
0 commit comments