@@ -8,7 +8,7 @@ module Ide.Plugin.Class.CodeLens where
88import Control.Lens ((^.) )
99import Control.Monad.IO.Class (liftIO )
1010import Data.Aeson
11- import Data.Maybe (mapMaybe )
11+ import Data.Maybe (mapMaybe , maybeToList )
1212import qualified Data.Text as T
1313import Development.IDE
1414import Development.IDE.GHC.Compat
@@ -32,7 +32,8 @@ codeLens state plId CodeLensParams{..} = do
3232 $ runAction " classplugin.TypeCheck" state
3333 $ use TypeCheck nfp
3434
35- InstanceBindTypeSigsResult binds <-
35+ -- All instance binds
36+ InstanceBindTypeSigsResult allBinds <-
3637 handleMaybeM " Unable to get InstanceBindTypeSigsResult"
3738 $ liftIO
3839 $ runAction " classplugin.GetInstanceBindTypeSigs" state
@@ -42,29 +43,39 @@ codeLens state plId CodeLensParams{..} = do
4243
4344 let (hsGroup, _, _, _) = tmrRenamed tmr
4445 tycls = hs_tyclds hsGroup
45- -- class instance decls
46- insts = mapMaybe (getClsInstD . unLoc) $ concatMap group_instds tycls
47- -- Declared instance methods without signatures
48- bindInfos = concatMap getBindSpanWithoutSig insts
49- targetSigs = matchBind bindInfos binds
50- codeLens =
51- (\ x@ (range, title) ->
52- generateLens plId range title
46+ -- declared instance methods without signatures
47+ bindInfos = [ bind
48+ | instds <- map group_instds tycls -- class instance decls
49+ , instd <- instds
50+ , inst <- maybeToList $ getClsInstD (unLoc instd)
51+ , bind <- getBindSpanWithoutSig inst
52+ ]
53+ targetSigs = matchBind bindInfos allBinds
54+ makeLens (range, title) =
55+ generateLens plId range title
5356 $ workspaceEdit pragmaInsertion
54- $ makeEdit x
55- ) <$> mapMaybe getRangeWithSig targetSigs
57+ $ makeEdit range title
58+ codeLens = makeLens <$> mapMaybe getRangeWithSig targetSigs
5659
5760 pure $ List codeLens
5861 where
5962 uri = _textDocument ^. J. uri
6063
6164 -- Match Binds with their signatures
65+ -- We try to give every `InstanceBindTypeSig` a `SrcSpan`,
66+ -- hence we can display signatures for `InstanceBindTypeSig` with span later.
6267 matchBind :: [BindInfo ] -> [InstanceBindTypeSig ] -> [InstanceBindTypeSig ]
63- matchBind binds = map go
68+ matchBind existedBinds allBindWithSigs =
69+ [foldl go bindSig existedBinds | bindSig <- allBindWithSigs]
6470 where
71+ -- | The `bindDefSpan` of the bind is `Nothing` before,
72+ -- we update it with the span where binding occurs.
73+ -- Hence, we can infer the place to display the signature later.
74+ update :: InstanceBindTypeSig -> SrcSpan -> InstanceBindTypeSig
6575 update bind sp = bind {bindDefSpan = Just sp}
66- go sig = foldl go' sig binds
67- go' bindSig bind = case (srcSpanToRange . bindNameSpan) bind of
76+
77+ go :: InstanceBindTypeSig -> BindInfo -> InstanceBindTypeSig
78+ go bindSig bind = case (srcSpanToRange . bindNameSpan) bind of
6879 Nothing -> bindSig
6980 Just range ->
7081 if inRange range (getSrcSpan $ bindName bindSig)
@@ -109,23 +120,12 @@ codeLens state plId CodeLensParams{..} = do
109120 let cmd = mkLspCommand plId typeLensCommandId title (Just [toJSON edit])
110121 in CodeLens range (Just cmd) Nothing
111122
112- makeEdit :: (Range , T. Text ) -> [TextEdit ]
113- makeEdit (range, bind)
114- | indentSize > maxSize =
115- [TextEdit (insertRange (indentSize - 1 )) -- minus one to remove the leading space
116- (" \n "
117- <> T. replicate defaultIndent " "
118- <> bind
119- <> " \n "
120- <> T. replicate (defaultIndent - 1 ) " " )]
121- | otherwise = [TextEdit (insertRange 0 ) (T. replicate indentSize " " <> bind <> " \n " )]
122- where
123- startOfLine = Position (_line (range ^. J. start))
124- insertRange c = Range (startOfLine c) (startOfLine c)
125- maxSize :: Int
126- maxSize = 18 -- Length of the shortest instance like `instance X A where`
127- indentSize :: Num a => a
128- indentSize = fromIntegral $ _character $ range ^. J. start
123+ makeEdit :: Range -> T. Text -> [TextEdit ]
124+ makeEdit range bind =
125+ let startPos = range ^. J. start
126+ insertChar = startPos ^. J. character
127+ insertRange = Range startPos startPos
128+ in [TextEdit insertRange (bind <> " \n " <> T. replicate (fromIntegral insertChar) " " )]
129129
130130codeLensCommandHandler :: CommandFunction IdeState WorkspaceEdit
131131codeLensCommandHandler _ wedit = do
0 commit comments