@@ -84,10 +84,33 @@ descriptor _recorder pluginId =
84
84
{ Ide.Types. pluginHandlers = mkPluginHandler SMethod_TextDocumentSignatureHelp signatureHelpProvider
85
85
}
86
86
87
+ {- Note [Stale Results in Signature Help]
88
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
89
+ Stale results work well when users are reading code.
90
+
91
+ When we add support for writing code, such as automatically triggering signature
92
+ help when a space char is inserted, we probably have to use up-to-date results.
93
+ -}
94
+
95
+ {-
96
+ Here is a brief description of the algorithm of finding relevant bits from HIE AST
97
+ 1. let 'hsAppNode' = the smallest 'HsApp' AST node which contains the cursor postion
98
+ See 'extractInfoFromSmallestContainingFunctionApplicationAst'
99
+ 2. let 'functionNode' = the left-most node of 'hsAppNode'
100
+ See 'getLeftMostNode'
101
+ 3. try to get 'functionName' and 'functionTypes' from 'functionNode'
102
+ We get 'Nothing' when we cannot get that info
103
+ See 'getNodeNameAndTypes'
104
+ 4. count 'parameterIndex' by traversing the 'hsAppNode' subtree from its root to the cursor position
105
+ We get 'Nothing' when either the cursor position is at 'functionNode'
106
+ or we encounter some AST node we do not yet know how to continue our traversal
107
+ See 'getParameterIndex'
108
+ -}
87
109
signatureHelpProvider :: PluginMethodHandler IdeState Method_TextDocumentSignatureHelp
88
110
signatureHelpProvider ideState _pluginId (SignatureHelpParams (TextDocumentIdentifier uri) position _mProgreeToken mSignatureHelpContext) = do
89
111
nfp <- getNormalizedFilePathE uri
90
112
results <- runIdeActionE " signatureHelp.ast" (shakeExtras ideState) $ do
113
+ -- see Note [Stale Results in Signature Help]
91
114
(HAR {hieAst, hieKind}, positionMapping) <- useWithStaleFastE GetHieAst nfp
92
115
case fromCurrentPosition positionMapping position of
93
116
Nothing -> pure []
@@ -103,6 +126,7 @@ signatureHelpProvider ideState _pluginId (SignatureHelpParams (TextDocumentIdent
103
126
Just (functionName, functionTypes, parameterIndex)
104
127
)
105
128
(docMap, argDocMap) <- runIdeActionE " signatureHelp.docMap" (shakeExtras ideState) $ do
129
+ -- see Note [Stale Results in Signature Help]
106
130
mResult <- ExceptT $ Right <$> useWithStaleFast GetDocMap nfp
107
131
case mResult of
108
132
Just (DKMap docMap _tyThingMap argDocMap, _positionMapping) -> pure (docMap, argDocMap)
@@ -142,7 +166,12 @@ mkSignatureInformation docMap argDocMap parameterIndex functionName functionType
142
166
Nothing -> mempty
143
167
Just thisArgDocMap' -> thisArgDocMap'
144
168
in SignatureInformation
145
- { _label = functionNameLabelPrefix <> printOutputableOneLine functionType,
169
+ { -- Server-side line wrapping may be better since more context is available.
170
+ -- However, server-side line wrapping may make it harder to calculate
171
+ -- parameter ranges. In addition, some clients, such as vscode, ignore
172
+ -- server-side line wrapping and instead does client-side line wrapping.
173
+ -- So we choose not to do server-side line wrapping.
174
+ _label = functionNameLabelPrefix <> printOutputableOneLine functionType,
146
175
_documentation = mFunctionDoc,
147
176
_parameters = Just $ mkParameterInformations thisArgDocMap (fromIntegral $ T. length functionNameLabelPrefix) functionType,
148
177
_activeParameter = Just $ InL parameterIndex
@@ -271,6 +300,10 @@ getNodeNameAndTypes hieKind hieAst =
271
300
Just nodeInfo -> nodeType nodeInfo
272
301
allTypes = case mTypeOfName of
273
302
Nothing -> typesOfNode
303
+ -- (the last?) one type of 'typesOfNode' may (always?) be the same as 'typeOfName'
304
+ -- To avoid generating two identical signature helps, we do a filtering here
305
+ -- This is similar to 'dropEnd1' in Development.IDE.Spans.AtPoint.atPoint
306
+ -- TODO perhaps extract a common function
274
307
Just typeOfName -> typeOfName : filter (isDifferentType typeOfName) typesOfNode
275
308
in Just (name, filterCoreTypes allTypes)
276
309
[] -> Nothing
0 commit comments