1
1
{-# LANGUAGE GADTs #-}
2
+ {-# LANGUAGE LambdaCase #-}
2
3
{-# LANGUAGE OverloadedLists #-}
3
4
{-# LANGUAGE RecordWildCards #-}
4
5
{-# LANGUAGE ViewPatterns #-}
5
6
6
7
module Ide.Plugin.Class.CodeAction where
7
8
9
+ import Control.Arrow ((>>>) )
8
10
import Control.Lens hiding (List , use )
9
11
import Control.Monad.Error.Class (MonadError (throwError ))
10
12
import Control.Monad.Extra
@@ -23,11 +25,14 @@ import Data.Maybe (isNothing, listToMaybe,
23
25
import qualified Data.Set as Set
24
26
import qualified Data.Text as T
25
27
import Development.IDE
26
- import Development.IDE.Core.Compile (sourceTypecheck )
27
28
import Development.IDE.Core.FileStore (getVersionedTextDoc )
28
29
import Development.IDE.Core.PluginUtils
29
30
import Development.IDE.Core.PositionMapping (fromCurrentRange )
30
31
import Development.IDE.GHC.Compat
32
+ import Development.IDE.GHC.Compat.Error (TcRnMessage (.. ),
33
+ _TcRnMessage ,
34
+ flatTcRnMessage ,
35
+ msgEnvelopeErrorL )
31
36
import Development.IDE.GHC.Compat.Util
32
37
import Development.IDE.Spans.AtPoint (pointCommand )
33
38
import Ide.Plugin.Class.ExactPrint
@@ -80,21 +85,23 @@ addMethodPlaceholders _ state _ param@AddMinimalMethodsParams{..} = do
80
85
-- This implementation is ad-hoc in a sense that the diagnostic detection mechanism is
81
86
-- sensitive to the format of diagnostic messages from GHC.
82
87
codeAction :: Recorder (WithPriority Log ) -> PluginMethodHandler IdeState Method_TextDocumentCodeAction
83
- codeAction recorder state plId (CodeActionParams _ _ docId _ context ) = do
88
+ codeAction recorder state plId (CodeActionParams _ _ docId caRange _ ) = do
84
89
verTxtDocId <- liftIO $ runAction " classplugin.codeAction.getVersionedTextDoc" state $ getVersionedTextDoc docId
85
90
nfp <- getNormalizedFilePathE (verTxtDocId ^. L. uri)
86
- actions <- join <$> mapM (mkActions nfp verTxtDocId) methodDiags
87
- pure $ InL actions
91
+ activeDiagnosticsInRange (shakeExtras state) nfp caRange
92
+ >>= \ case
93
+ Nothing -> pure $ InL []
94
+ Just fileDiags -> do
95
+ actions <- join <$> mapM (mkActions nfp verTxtDocId) (methodDiags fileDiags)
96
+ pure $ InL actions
88
97
where
89
- diags = context ^. L. diagnostics
90
-
91
- ghcDiags = filter (\ d -> d ^. L. source == Just sourceTypecheck) diags
92
- methodDiags = filter (\ d -> isClassMethodWarning (d ^. L. message)) ghcDiags
98
+ methodDiags fileDiags =
99
+ filter (\ d -> isClassMethodWarning (d ^. fdStructuredMessageL)) fileDiags
93
100
94
101
mkActions
95
102
:: NormalizedFilePath
96
103
-> VersionedTextDocumentIdentifier
97
- -> Diagnostic
104
+ -> FileDiagnostic
98
105
-> ExceptT PluginError (HandlerM Ide.Plugin.Config. Config ) [Command |? CodeAction ]
99
106
mkActions docPath verTxtDocId diag = do
100
107
(HAR {hieAst = ast}, pmap) <- runActionE " classplugin.findClassIdentifier.GetHieAst" state
@@ -117,7 +124,7 @@ codeAction recorder state plId (CodeActionParams _ _ docId _ context) = do
117
124
$ fmap (second (filter (\ (bind, _) -> bind `notElem` implemented)))
118
125
$ mkMethodGroups hsc gblEnv range sigs cls
119
126
where
120
- range = diag ^. L. range
127
+ range = diag ^. fdLspDiagnosticL . L. range
121
128
122
129
mkMethodGroups :: HscEnv -> TcGblEnv -> Range -> [InstanceBindTypeSig ] -> Class -> [MethodGroup ]
123
130
mkMethodGroups hsc gblEnv range sigs cls = minimalDef <> [allClassMethods]
@@ -203,8 +210,15 @@ isClassNodeIdentifier :: Identifier -> IdentifierDetails a -> Bool
203
210
isClassNodeIdentifier (Right i) ident | ' C' : ' :' : _ <- unpackFS $ occNameFS $ occName i = (isNothing . identType) ident && Use `Set.member` identInfo ident
204
211
isClassNodeIdentifier _ _ = False
205
212
206
- isClassMethodWarning :: T. Text -> Bool
207
- isClassMethodWarning = T. isPrefixOf " • No explicit implementation for"
213
+ isClassMethodWarning :: StructuredMessage -> Bool
214
+ isClassMethodWarning message = case message ^? _SomeStructuredMessage . msgEnvelopeErrorL . _TcRnMessage of
215
+ Nothing -> False
216
+ Just tcRnMessage -> isGhcClassMethodWarning tcRnMessage
217
+
218
+ isGhcClassMethodWarning :: TcRnMessage -> Bool
219
+ isGhcClassMethodWarning = flatTcRnMessage >>> \ case
220
+ TcRnUnsatisfiedMinimalDef {} -> True
221
+ _ -> False
208
222
209
223
isInstanceValBind :: ContextInfo -> Bool
210
224
isInstanceValBind (ValBind InstanceBind _ _) = True
0 commit comments