@@ -5,8 +5,8 @@ module Ide.Plugin.SignatureHelp (descriptor) where
5
5
6
6
import Control.Arrow ((>>>) )
7
7
import Data.Bifunctor (bimap )
8
+ import Data.Function ((&) )
8
9
import qualified Data.Map.Strict as M
9
- import Data.Maybe (mapMaybe )
10
10
import qualified Data.Set as S
11
11
import Data.Text (Text )
12
12
import qualified Data.Text as T
@@ -34,10 +34,12 @@ import Development.IDE.GHC.Compat (ContextInfo (Use),
34
34
mkRealSrcLoc ,
35
35
mkRealSrcSpan ,
36
36
nodeChildren , nodeSpan ,
37
- ppr , recoverFullType ,
37
+ nodeType , ppr ,
38
+ recoverFullType ,
38
39
smallestContainingSatisfying ,
39
40
sourceNodeInfo )
40
41
import Development.IDE.GHC.Compat.Util (LexicalFastString (LexicalFastString ))
42
+ import GHC.Core.Map.Type (deBruijnize )
41
43
import GHC.Data.Maybe (rightToMaybe )
42
44
import GHC.Types.SrcLoc (isRealSubspanOf )
43
45
import Ide.Plugin.Error (getNormalizedFilePathE )
@@ -86,28 +88,30 @@ signatureHelpProvider ideState _pluginId (SignatureHelpParams (TextDocumentIdent
86
88
hieAst
87
89
( \ span hieAst -> do
88
90
let functionNode = getLeftMostNode hieAst
89
- functionName <- getNodeName span functionNode
90
- functionType <- getNodeType hieKind span functionNode
91
+ (functionName, functionTypes) <- getNodeNameAndTypes hieKind functionNode
91
92
argumentNumber <- getArgumentNumber span hieAst
92
- Just (functionName, functionType , argumentNumber)
93
+ Just (functionName, functionTypes , argumentNumber)
93
94
)
94
95
case results of
95
96
-- 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
98
99
_ -> pure $ InR Null
99
100
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 =
102
110
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)
111
115
(Just $ InL argumentNumber)
112
116
113
117
-- TODO(@linj) can type string be a multi-line string?
@@ -154,27 +158,33 @@ getLeftMostNode thisNode =
154
158
[] -> thisNode
155
159
leftChild: _ -> getLeftMostNode leftChild
156
160
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 =
159
163
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
164
179
else Nothing -- TODO(@linj) must function node be HsVar?
165
180
where
166
181
extractName = rightToMaybe
167
182
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
+
178
188
-- modified from Development.IDE.Spans.AtPoint.atPoint
179
189
prettyType :: a -> Text
180
190
prettyType = expandType >>> printOutputable
0 commit comments