Skip to content

Commit d603ec4

Browse files
committed
Show more types: each type as one signature help
1 parent 471958f commit d603ec4

File tree

2 files changed

+46
-36
lines changed

2 files changed

+46
-36
lines changed

plugins/hls-signature-help-plugin/src/Ide/Plugin/SignatureHelp.hs

Lines changed: 43 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ module Ide.Plugin.SignatureHelp (descriptor) where
55

66
import Control.Arrow ((>>>))
77
import Data.Bifunctor (bimap)
8+
import Data.Function ((&))
89
import qualified Data.Map.Strict as M
9-
import Data.Maybe (mapMaybe)
1010
import qualified Data.Set as S
1111
import Data.Text (Text)
1212
import qualified Data.Text as T
@@ -34,10 +34,12 @@ import Development.IDE.GHC.Compat (ContextInfo (Use),
3434
mkRealSrcLoc,
3535
mkRealSrcSpan,
3636
nodeChildren, nodeSpan,
37-
ppr, recoverFullType,
37+
nodeType, ppr,
38+
recoverFullType,
3839
smallestContainingSatisfying,
3940
sourceNodeInfo)
4041
import Development.IDE.GHC.Compat.Util (LexicalFastString (LexicalFastString))
42+
import GHC.Core.Map.Type (deBruijnize)
4143
import GHC.Data.Maybe (rightToMaybe)
4244
import GHC.Types.SrcLoc (isRealSubspanOf)
4345
import Ide.Plugin.Error (getNormalizedFilePathE)
@@ -86,28 +88,30 @@ signatureHelpProvider ideState _pluginId (SignatureHelpParams (TextDocumentIdent
8688
hieAst
8789
( \span hieAst -> do
8890
let functionNode = getLeftMostNode hieAst
89-
functionName <- getNodeName span functionNode
90-
functionType <- getNodeType hieKind span functionNode
91+
(functionName, functionTypes) <- getNodeNameAndTypes hieKind functionNode
9192
argumentNumber <- getArgumentNumber span hieAst
92-
Just (functionName, functionType, argumentNumber)
93+
Just (functionName, functionTypes, argumentNumber)
9394
)
9495
case results of
9596
-- TODO(@linj) what does non-singleton list mean?
96-
[(functionName, functionType, argumentNumber)] ->
97-
pure $ InL $ mkSignatureHelp functionName functionType (fromIntegral argumentNumber - 1)
97+
[(functionName, functionTypes, argumentNumber)] ->
98+
pure $ InL $ mkSignatureHelp (fromIntegral argumentNumber - 1) functionName functionTypes
9899
_ -> pure $ InR Null
99100

100-
mkSignatureHelp :: Name -> Text -> UInt -> SignatureHelp
101-
mkSignatureHelp functionName functionType argumentNumber =
101+
mkSignatureHelp :: UInt -> Name -> [Text] -> SignatureHelp
102+
mkSignatureHelp argumentNumber functionName functionTypes =
103+
SignatureHelp
104+
(mkSignatureInformation argumentNumber functionName <$> functionTypes)
105+
(Just 0)
106+
(Just $ InL argumentNumber)
107+
108+
mkSignatureInformation :: UInt -> Name -> Text -> SignatureInformation
109+
mkSignatureInformation argumentNumber functionName functionType =
102110
let functionNameLabelPrefix = printOutputable (ppr functionName) <> " :: "
103-
in SignatureHelp
104-
[ SignatureInformation
105-
(functionNameLabelPrefix <> functionType)
106-
Nothing
107-
(Just $ mkArguments (fromIntegral $ T.length functionNameLabelPrefix) functionType)
108-
(Just $ InL argumentNumber)
109-
]
110-
(Just 0)
111+
in SignatureInformation
112+
(functionNameLabelPrefix <> functionType)
113+
Nothing
114+
(Just $ mkArguments (fromIntegral $ T.length functionNameLabelPrefix) functionType)
111115
(Just $ InL argumentNumber)
112116

113117
-- TODO(@linj) can type string be a multi-line string?
@@ -154,27 +158,33 @@ getLeftMostNode thisNode =
154158
[] -> thisNode
155159
leftChild: _ -> getLeftMostNode leftChild
156160

157-
getNodeName :: RealSrcSpan -> HieAST a -> Maybe Name
158-
getNodeName _span hieAst =
161+
getNodeNameAndTypes :: forall a. HieKind a -> HieAST a -> Maybe (Name, [Text])
162+
getNodeNameAndTypes hieKind hieAst =
159163
if nodeHasAnnotation ("HsVar", "HsExpr") hieAst
160-
then
161-
case mapMaybe extractName $ M.keys $ M.filter isUse $ getSourceNodeIds hieAst of
162-
[name] -> Just name -- TODO(@linj) will there be more than one name?
163-
_ -> Nothing
164+
then case hieAst & getSourceNodeIds & M.filter isUse & M.assocs of
165+
[(identifier, identifierDetails)] ->
166+
case extractName identifier of
167+
Nothing -> Nothing
168+
Just name ->
169+
let mTypeOfName = identType identifierDetails
170+
typesOfNode = case sourceNodeInfo hieAst of
171+
Nothing -> []
172+
Just nodeInfo -> nodeType nodeInfo
173+
allTypes = case mTypeOfName of
174+
Nothing -> typesOfNode
175+
Just typeOfName -> typeOfName : filter (isDifferentType typeOfName) typesOfNode
176+
in Just (name, prettyType <$> allTypes)
177+
[] -> Nothing
178+
_ -> Nothing -- seems impossible
164179
else Nothing -- TODO(@linj) must function node be HsVar?
165180
where
166181
extractName = rightToMaybe
167182

168-
-- TODO(@linj) share code with getNodeName
169-
getNodeType :: HieKind a -> RealSrcSpan -> HieAST a -> Maybe Text
170-
getNodeType (hieKind :: HieKind a) _span hieAst =
171-
if nodeHasAnnotation ("HsVar", "HsExpr") hieAst
172-
then
173-
case M.elems $ M.filter isUse $ getSourceNodeIds hieAst of
174-
[identifierDetails] -> identType identifierDetails >>= (prettyType >>> Just)
175-
_ -> Nothing -- TODO(@linj) will there be more than one identifierDetails?
176-
else Nothing
177-
where
183+
isDifferentType :: a -> a -> Bool
184+
isDifferentType type1 type2 = case hieKind of
185+
HieFresh -> deBruijnize type1 /= deBruijnize type2
186+
HieFromDisk _hieFile -> type1 /= type2
187+
178188
-- modified from Development.IDE.Spans.AtPoint.atPoint
179189
prettyType :: a -> Text
180190
prettyType = expandType >>> printOutputable

plugins/hls-signature-help-plugin/test/Main.hs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,8 @@ main =
143143
^ ^ ^
144144
|]
145145
[ Nothing,
146-
Just $ SignatureHelp [SignatureInformation "f :: forall a. Num a => a -> a -> a" Nothing (Just [ParameterInformation (InR (24,25)) Nothing, ParameterInformation (InR (29,30)) Nothing]) (Just (InL 0))] (Just 0) (Just (InL 0)),
147-
Just $ SignatureHelp [SignatureInformation "f :: forall a. Num a => a -> a -> a" Nothing (Just [ParameterInformation (InR (24,25)) Nothing, ParameterInformation (InR (29,30)) Nothing]) (Just (InL 1))] (Just 0) (Just (InL 1))
146+
Just $ SignatureHelp [SignatureInformation "f :: forall a. Num a => a -> a -> a" Nothing (Just [ParameterInformation (InR (24,25)) Nothing, ParameterInformation (InR (29,30)) Nothing]) (Just (InL 0)), SignatureInformation "f :: Integer -> Integer -> Integer" Nothing (Just [ParameterInformation (InR (5,12)) Nothing, ParameterInformation (InR (16,23)) Nothing]) (Just (InL 0))] (Just 0) (Just (InL 0)),
147+
Just $ SignatureHelp [SignatureInformation "f :: forall a. Num a => a -> a -> a" Nothing (Just [ParameterInformation (InR (24,25)) Nothing, ParameterInformation (InR (29,30)) Nothing]) (Just (InL 1)), SignatureInformation "f :: Integer -> Integer -> Integer" Nothing (Just [ParameterInformation (InR (5,12)) Nothing, ParameterInformation (InR (16,23)) Nothing]) (Just (InL 1))] (Just 0) (Just (InL 1))
148148
],
149149
mkTest
150150
"type constraint with kind signatures"
@@ -154,7 +154,7 @@ main =
154154
^ ^
155155
|]
156156
[ Nothing,
157-
Just $ SignatureHelp [SignatureInformation "pure :: forall (f :: Type -> Type) a. Applicative f => a -> f a" Nothing (Just [ParameterInformation (InR (55,56)) Nothing]) (Just (InL 0))] (Just 0) (Just (InL 0))
157+
Just $ SignatureHelp [SignatureInformation "pure :: forall (f :: Type -> Type) a. Applicative f => a -> f a" Nothing (Just [ParameterInformation (InR (55,56)) Nothing]) (Just (InL 0)), SignatureInformation "pure :: Bool -> IO Bool" Nothing (Just [ParameterInformation (InR (8,12)) Nothing]) (Just (InL 0)), SignatureInformation "pure :: forall a. a -> IO a" Nothing (Just [ParameterInformation (InR (18,19)) Nothing]) (Just (InL 0))] (Just 0) (Just (InL 0))
158158
],
159159
mkTest
160160
"dynamic function"

0 commit comments

Comments
 (0)