@@ -79,14 +79,14 @@ import GHC.Exts (fromList)
79
79
import qualified GHC.LanguageExtensions as Lang
80
80
import Ide.Logger hiding
81
81
(group )
82
- import Ide.PluginUtils (extractTextInRange ,
82
+ import Ide.PluginUtils (extendToFullLines ,
83
+ extractTextInRange ,
83
84
subRange )
84
85
import Ide.Types
85
86
import Language.LSP.Protocol.Message (Method (.. ),
86
87
SMethod (.. ))
87
88
import Language.LSP.Protocol.Types (ApplyWorkspaceEditParams (.. ),
88
89
CodeAction (.. ),
89
- CodeActionContext (CodeActionContext , _diagnostics ),
90
90
CodeActionKind (CodeActionKind_QuickFix ),
91
91
CodeActionParams (CodeActionParams ),
92
92
Command ,
@@ -110,16 +110,16 @@ import Text.Regex.TDFA ((=~), (=~~))
110
110
111
111
-- | Generate code actions.
112
112
codeAction :: PluginMethodHandler IdeState 'Method_TextDocumentCodeAction
113
- codeAction state _ (CodeActionParams _ _ (TextDocumentIdentifier uri) _range CodeActionContext {_diagnostics = xs} ) = do
113
+ codeAction state _ (CodeActionParams _ _ (TextDocumentIdentifier uri) range _ ) = do
114
114
contents <- lift $ LSP. getVirtualFile $ toNormalizedUri uri
115
115
liftIO $ do
116
116
let text = virtualFileText <$> contents
117
117
mbFile = toNormalizedFilePath' <$> uriToFilePath uri
118
- diag <- atomically $ fmap (\ (_, _, d) -> d) . filter (\ (p, _, _) -> mbFile == Just p) <$> getDiagnostics state
118
+ allDiags <- atomically $ fmap (\ (_, _, d) -> d) . filter (\ (p, _, _) -> mbFile == Just p) <$> getDiagnostics state
119
119
(join -> parsedModule) <- runAction " GhcideCodeActions.getParsedModule" state $ getParsedModule `traverse` mbFile
120
120
let
121
- actions = caRemoveRedundantImports parsedModule text diag xs uri
122
- <> caRemoveInvalidExports parsedModule text diag xs uri
121
+ actions = caRemoveRedundantImports parsedModule text allDiags range uri
122
+ <> caRemoveInvalidExports parsedModule text allDiags range uri
123
123
pure $ InL actions
124
124
125
125
-------------------------------------------------------------------------------------------------
@@ -438,19 +438,25 @@ suggestRemoveRedundantImport ParsedModule{pm_parsed_source = L _ HsModule{hsmod
438
438
= [(" Remove import" , [TextEdit (extendToWholeLineIfPossible contents _range) " " ])]
439
439
| otherwise = []
440
440
441
+ diagInRange :: Diagnostic -> Range -> Bool
442
+ diagInRange Diagnostic {_range = dr} r = dr `subRange` extendedRange
443
+ where
444
+ -- Ensures the range captures full lines. Makes it easier to trigger the correct
445
+ -- "remove redundant" code actions from anywhere on the offending line.
446
+ extendedRange = extendToFullLines r
441
447
442
448
-- Note [Removing imports is preferred]
443
449
-- It's good to prefer the remove imports code action because an unused import
444
450
-- is likely to be removed and less likely the warning will be disabled.
445
451
-- Therefore actions to remove a single or all redundant imports should be
446
452
-- preferred, so that the client can prioritize them higher.
447
- caRemoveRedundantImports :: Maybe ParsedModule -> Maybe T. Text -> [Diagnostic ] -> [ Diagnostic ] -> Uri -> [Command |? CodeAction ]
448
- caRemoveRedundantImports m contents digs ctxDigs uri
453
+ caRemoveRedundantImports :: Maybe ParsedModule -> Maybe T. Text -> [Diagnostic ] -> Range -> Uri -> [Command |? CodeAction ]
454
+ caRemoveRedundantImports m contents allDiags contextRange uri
449
455
| Just pm <- m,
450
- r <- join $ map (\ d -> repeat d `zip` suggestRemoveRedundantImport pm contents d) digs ,
456
+ r <- join $ map (\ d -> repeat d `zip` suggestRemoveRedundantImport pm contents d) allDiags ,
451
457
allEdits <- [ e | (_, (_, edits)) <- r, e <- edits],
452
458
caRemoveAll <- removeAll allEdits,
453
- ctxEdits <- [ x | x@ (d, _) <- r, d `elem` ctxDigs ],
459
+ ctxEdits <- [ x | x@ (d, _) <- r, d `diagInRange` contextRange ],
454
460
not $ null ctxEdits,
455
461
caRemoveCtx <- map (\ (d, (title, tedit)) -> removeSingle title tedit d) ctxEdits
456
462
= caRemoveCtx ++ [caRemoveAll]
@@ -474,18 +480,18 @@ caRemoveRedundantImports m contents digs ctxDigs uri
474
480
_data_ = Nothing
475
481
_changeAnnotations = Nothing
476
482
477
- caRemoveInvalidExports :: Maybe ParsedModule -> Maybe T. Text -> [Diagnostic ] -> [ Diagnostic ] -> Uri -> [Command |? CodeAction ]
478
- caRemoveInvalidExports m contents digs ctxDigs uri
483
+ caRemoveInvalidExports :: Maybe ParsedModule -> Maybe T. Text -> [Diagnostic ] -> Range -> Uri -> [Command |? CodeAction ]
484
+ caRemoveInvalidExports m contents allDiags contextRange uri
479
485
| Just pm <- m,
480
486
Just txt <- contents,
481
487
txt' <- indexedByPosition $ T. unpack txt,
482
- r <- mapMaybe (groupDiag pm) digs ,
488
+ r <- mapMaybe (groupDiag pm) allDiags ,
483
489
r' <- map (\ (t,d,rs) -> (t,d,extend txt' rs)) r,
484
490
caRemoveCtx <- mapMaybe removeSingle r',
485
491
allRanges <- nubOrd $ [ range | (_,_,ranges) <- r, range <- ranges],
486
492
allRanges' <- extend txt' allRanges,
487
493
Just caRemoveAll <- removeAll allRanges',
488
- ctxEdits <- [ x | x@ (_, d, _) <- r, d `elem` ctxDigs ],
494
+ ctxEdits <- [ x | x@ (_, d, _) <- r, d `diagInRange` contextRange ],
489
495
not $ null ctxEdits
490
496
= caRemoveCtx ++ [caRemoveAll]
491
497
| otherwise = []
0 commit comments