Skip to content

Commit 6667423

Browse files
committed
Revert "Migrate hls-class-plugin to use StructuredMessage"
This reverts commit 51515ff.
1 parent 51515ff commit 6667423

File tree

2 files changed

+48
-38
lines changed

2 files changed

+48
-38
lines changed

plugins/hls-class-plugin/src/Ide/Plugin/Class/CodeAction.hs

Lines changed: 45 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,10 @@
11
{-# LANGUAGE GADTs #-}
2-
{-# LANGUAGE LambdaCase #-}
32
{-# LANGUAGE OverloadedLists #-}
43
{-# LANGUAGE RecordWildCards #-}
54
{-# LANGUAGE ViewPatterns #-}
65

7-
module Ide.Plugin.Class.CodeAction (
8-
addMethodPlaceholders,
9-
codeAction,
10-
) where
6+
module Ide.Plugin.Class.CodeAction where
117

12-
import Control.Arrow ((>>>))
138
import Control.Lens hiding (List, use)
149
import Control.Monad.Error.Class (MonadError (throwError))
1510
import Control.Monad.Extra
@@ -18,6 +13,8 @@ import Control.Monad.Trans.Class (lift)
1813
import Control.Monad.Trans.Except (ExceptT)
1914
import Control.Monad.Trans.Maybe
2015
import Data.Aeson hiding (Null)
16+
import Data.Bifunctor (second)
17+
import Data.Either.Extra (rights)
2118
import Data.List
2219
import Data.List.Extra (nubOrdOn)
2320
import qualified Data.Map.Strict as Map
@@ -26,14 +23,11 @@ import Data.Maybe (isNothing, listToMaybe,
2623
import qualified Data.Set as Set
2724
import qualified Data.Text as T
2825
import Development.IDE
26+
import Development.IDE.Core.Compile (sourceTypecheck)
2927
import Development.IDE.Core.FileStore (getVersionedTextDoc)
3028
import Development.IDE.Core.PluginUtils
3129
import Development.IDE.Core.PositionMapping (fromCurrentRange)
3230
import Development.IDE.GHC.Compat
33-
import Development.IDE.GHC.Compat.Error (TcRnMessage (..),
34-
_TcRnMessage,
35-
stripTcRnMessageContext,
36-
msgEnvelopeErrorL)
3731
import Development.IDE.GHC.Compat.Util
3832
import Development.IDE.Spans.AtPoint (pointCommand)
3933
import Ide.Plugin.Class.ExactPrint
@@ -86,25 +80,23 @@ addMethodPlaceholders _ state _ param@AddMinimalMethodsParams{..} = do
8680
-- This implementation is ad-hoc in a sense that the diagnostic detection mechanism is
8781
-- sensitive to the format of diagnostic messages from GHC.
8882
codeAction :: Recorder (WithPriority Log) -> PluginMethodHandler IdeState Method_TextDocumentCodeAction
89-
codeAction recorder state plId (CodeActionParams _ _ docId caRange _) = do
83+
codeAction recorder state plId (CodeActionParams _ _ docId _ context) = do
9084
verTxtDocId <- liftIO $ runAction "classplugin.codeAction.getVersionedTextDoc" state $ getVersionedTextDoc docId
9185
nfp <- getNormalizedFilePathE (verTxtDocId ^. L.uri)
92-
activeDiagnosticsInRange (shakeExtras state) nfp caRange
93-
>>= \case
94-
Nothing -> pure $ InL []
95-
Just fileDiags -> do
96-
actions <- join <$> mapM (mkActions nfp verTxtDocId) (methodDiags fileDiags)
97-
pure $ InL actions
86+
actions <- join <$> mapM (mkActions nfp verTxtDocId) methodDiags
87+
pure $ InL actions
9888
where
99-
methodDiags fileDiags =
100-
mapMaybe (\d -> (d,) <$> isClassMethodWarning (d ^. fdStructuredMessageL)) fileDiags
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
10193

10294
mkActions
10395
:: NormalizedFilePath
10496
-> VersionedTextDocumentIdentifier
105-
-> (FileDiagnostic, ClassMinimalDef)
97+
-> Diagnostic
10698
-> ExceptT PluginError (HandlerM Ide.Plugin.Config.Config) [Command |? CodeAction]
107-
mkActions docPath verTxtDocId (diag, classMinDef) = do
99+
mkActions docPath verTxtDocId diag = do
108100
(HAR {hieAst = ast}, pmap) <- runActionE "classplugin.findClassIdentifier.GetHieAst" state
109101
$ useWithStaleE GetHieAst docPath
110102
instancePosition <- handleMaybe (PluginInvalidUserState "fromCurrentRange") $
@@ -116,19 +108,21 @@ codeAction recorder state plId (CodeActionParams _ _ docId caRange _) = do
116108
$ useE GetInstanceBindTypeSigs docPath
117109
(tmrTypechecked -> gblEnv ) <- runActionE "classplugin.codeAction.TypeCheck" state $ useE TypeCheck docPath
118110
(hscEnv -> hsc) <- runActionE "classplugin.codeAction.GhcSession" state $ useE GhcSession docPath
119-
logWith recorder Debug (LogImplementedMethods cls classMinDef)
111+
implemented <- findImplementedMethods ast instancePosition
112+
logWith recorder Info (LogImplementedMethods cls implemented)
120113
pure
121114
$ concatMap mkAction
122115
$ nubOrdOn snd
123116
$ filter ((/=) mempty . snd)
124-
$ mkMethodGroups hsc gblEnv range sigs classMinDef
117+
$ fmap (second (filter (\(bind, _) -> bind `notElem` implemented)))
118+
$ mkMethodGroups hsc gblEnv range sigs cls
125119
where
126-
range = diag ^. fdLspDiagnosticL . L.range
120+
range = diag ^. L.range
127121

128-
mkMethodGroups :: HscEnv -> TcGblEnv -> Range -> [InstanceBindTypeSig] -> ClassMinimalDef -> [MethodGroup]
129-
mkMethodGroups hsc gblEnv range sigs classMinDef = minimalDef <> [allClassMethods]
122+
mkMethodGroups :: HscEnv -> TcGblEnv -> Range -> [InstanceBindTypeSig] -> Class -> [MethodGroup]
123+
mkMethodGroups hsc gblEnv range sigs cls = minimalDef <> [allClassMethods]
130124
where
131-
minimalDef = minDefToMethodGroups hsc gblEnv range sigs classMinDef
125+
minimalDef = minDefToMethodGroups hsc gblEnv range sigs $ classMinimalDef cls
132126
allClassMethods = ("all missing methods", makeMethodDefinitions hsc gblEnv range sigs)
133127

134128
mkAction :: MethodGroup -> [Command |? CodeAction]
@@ -169,6 +163,25 @@ codeAction recorder state plId (CodeActionParams _ _ docId caRange _) = do
169163
<=< nodeChildren
170164
)
171165

166+
findImplementedMethods
167+
:: HieASTs a
168+
-> Position
169+
-> ExceptT PluginError (HandlerM Ide.Plugin.Config.Config) [T.Text]
170+
findImplementedMethods asts instancePosition = do
171+
pure
172+
$ concat
173+
$ pointCommand asts instancePosition
174+
$ map (T.pack . getOccString) . rights . findInstanceValBindIdentifiers
175+
176+
-- | Recurses through the given AST to find identifiers which are
177+
-- 'InstanceValBind's.
178+
findInstanceValBindIdentifiers :: HieAST a -> [Identifier]
179+
findInstanceValBindIdentifiers ast =
180+
let valBindIds = Map.keys
181+
. Map.filter (any isInstanceValBind . identInfo)
182+
$ getNodeIds ast
183+
in valBindIds <> concatMap findInstanceValBindIdentifiers (nodeChildren ast)
184+
172185
findClassFromIdentifier docPath (Right name) = do
173186
(hscEnv -> hscenv, _) <- runActionE "classplugin.findClassFromIdentifier.GhcSessionDeps" state
174187
$ useWithStaleE GhcSessionDeps docPath
@@ -190,15 +203,12 @@ isClassNodeIdentifier :: Identifier -> IdentifierDetails a -> Bool
190203
isClassNodeIdentifier (Right i) ident | 'C':':':_ <- unpackFS $ occNameFS $ occName i = (isNothing . identType) ident && Use `Set.member` identInfo ident
191204
isClassNodeIdentifier _ _ = False
192205

193-
isClassMethodWarning :: StructuredMessage -> Maybe ClassMinimalDef
194-
isClassMethodWarning message = case message ^? _SomeStructuredMessage . msgEnvelopeErrorL . _TcRnMessage of
195-
Nothing -> Nothing
196-
Just tcRnMessage -> isUnsatisfiedMinimalDefWarning tcRnMessage
206+
isClassMethodWarning :: T.Text -> Bool
207+
isClassMethodWarning = T.isPrefixOf "• No explicit implementation for"
197208

198-
isUnsatisfiedMinimalDefWarning :: TcRnMessage -> Maybe ClassMinimalDef
199-
isUnsatisfiedMinimalDefWarning = stripTcRnMessageContext >>> \case
200-
TcRnUnsatisfiedMinimalDef classMinDef -> Just classMinDef
201-
_ -> Nothing
209+
isInstanceValBind :: ContextInfo -> Bool
210+
isInstanceValBind (ValBind InstanceBind _ _) = True
211+
isInstanceValBind _ = False
202212

203213
type MethodSignature = T.Text
204214
type MethodName = T.Text

plugins/hls-class-plugin/src/Ide/Plugin/Class/Types.hs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,15 +112,15 @@ instance NFData InstanceBindLensResult where
112112
type instance RuleResult GetInstanceBindLens = InstanceBindLensResult
113113

114114
data Log
115-
= LogImplementedMethods Class ClassMinimalDef
115+
= LogImplementedMethods Class [T.Text]
116116
| LogShake Shake.Log
117117

118118
instance Pretty Log where
119119
pretty = \case
120120
LogImplementedMethods cls methods ->
121-
pretty ("The following methods are missing" :: String)
121+
pretty ("Detected implemented methods for class" :: String)
122122
<+> pretty (show (getOccString cls) <> ":") -- 'show' is used here to add quotes around the class name
123-
<+> pretty (showSDocUnsafe $ ppr methods)
123+
<+> pretty methods
124124
LogShake log -> pretty log
125125

126126
data BindInfo = BindInfo

0 commit comments

Comments
 (0)