@@ -84,10 +84,33 @@ descriptor _recorder pluginId =
8484 { Ide.Types. pluginHandlers = mkPluginHandler SMethod_TextDocumentSignatureHelp signatureHelpProvider
8585 }
8686
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+ -}
87109signatureHelpProvider :: PluginMethodHandler IdeState Method_TextDocumentSignatureHelp
88110signatureHelpProvider ideState _pluginId (SignatureHelpParams (TextDocumentIdentifier uri) position _mProgreeToken mSignatureHelpContext) = do
89111 nfp <- getNormalizedFilePathE uri
90112 results <- runIdeActionE " signatureHelp.ast" (shakeExtras ideState) $ do
113+ -- see Note [Stale Results in Signature Help]
91114 (HAR {hieAst, hieKind}, positionMapping) <- useWithStaleFastE GetHieAst nfp
92115 case fromCurrentPosition positionMapping position of
93116 Nothing -> pure []
@@ -103,6 +126,7 @@ signatureHelpProvider ideState _pluginId (SignatureHelpParams (TextDocumentIdent
103126 Just (functionName, functionTypes, parameterIndex)
104127 )
105128 (docMap, argDocMap) <- runIdeActionE " signatureHelp.docMap" (shakeExtras ideState) $ do
129+ -- see Note [Stale Results in Signature Help]
106130 mResult <- ExceptT $ Right <$> useWithStaleFast GetDocMap nfp
107131 case mResult of
108132 Just (DKMap docMap _tyThingMap argDocMap, _positionMapping) -> pure (docMap, argDocMap)
@@ -142,7 +166,12 @@ mkSignatureInformation docMap argDocMap parameterIndex functionName functionType
142166 Nothing -> mempty
143167 Just thisArgDocMap' -> thisArgDocMap'
144168 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,
146175 _documentation = mFunctionDoc,
147176 _parameters = Just $ mkParameterInformations thisArgDocMap (fromIntegral $ T. length functionNameLabelPrefix) functionType,
148177 _activeParameter = Just $ InL parameterIndex
@@ -271,6 +300,10 @@ getNodeNameAndTypes hieKind hieAst =
271300 Just nodeInfo -> nodeType nodeInfo
272301 allTypes = case mTypeOfName of
273302 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
274307 Just typeOfName -> typeOfName : filter (isDifferentType typeOfName) typesOfNode
275308 in Just (name, filterCoreTypes allTypes)
276309 [] -> Nothing
0 commit comments