Skip to content

Commit 9b952c8

Browse files
authored
Implement signature help (#4626)
1 parent 60a6c48 commit 9b952c8

29 files changed

+1036
-25
lines changed

.github/workflows/test.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,10 @@ jobs:
261261
name: Compile the plugin-tutorial
262262
run: cabal build plugin-tutorial
263263

264+
- if: matrix.test
265+
name: Test hls-signature-help-plugin test suite
266+
run: cabal test hls-signature-help-plugin-tests || cabal test hls-signature-help-plugin-tests
267+
264268
test_post_job:
265269
if: always()
266270
runs-on: ubuntu-latest

CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
/plugins/hls-rename-plugin
3838
/plugins/hls-retrie-plugin @wz1000
3939
/plugins/hls-semantic-tokens-plugin @soulomoon
40+
/plugins/hls-signature-help-plugin @jian-lin
4041
/plugins/hls-splice-plugin @konn
4142
/plugins/hls-stan-plugin @0rphee
4243
/plugins/hls-stylish-haskell-plugin @michaelpj

docs/configuration.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ Here is a list of the additional settings currently supported by `haskell-langua
5252
Plugins have a generic config to control their behaviour. The schema of such config is:
5353

5454
- `haskell.plugin.${pluginName}.globalOn`: usually with default true. Whether the plugin is enabled at runtime or it is not. That is the option you might use if you want to disable completely a plugin.
55-
- Actual plugin names are: `ghcide-code-actions-fill-holes`, `ghcide-completions`, `ghcide-hover-and-symbols`, `ghcide-type-lenses`, `ghcide-code-actions-type-signatures`, `ghcide-code-actions-bindings`, `ghcide-code-actions-imports-exports`, `eval`, `moduleName`, `pragmas`, `importLens`, `class`, `hlint`, `retrie`, `rename`, `splice`, `stan`.
55+
- Actual plugin names are: `ghcide-code-actions-fill-holes`, `ghcide-completions`, `ghcide-hover-and-symbols`, `ghcide-type-lenses`, `ghcide-code-actions-type-signatures`, `ghcide-code-actions-bindings`, `ghcide-code-actions-imports-exports`, `eval`, `moduleName`, `pragmas`, `importLens`, `class`, `hlint`, `retrie`, `rename`, `splice`, `stan`, `signatureHelp`.
5656
- So to disable the import lens with an explicit list of module definitions you could set `haskell.plugin.importLens.globalOn: false`
5757
- `haskell.plugin.${pluginName}.${lspCapability}On`: usually with default true. Whether a concrete plugin capability is enabled.
5858
- Capabilities are the different ways a lsp server can interact with the editor. The current available capabilities of the server are: `callHierarchy`, `codeActions`, `codeLens`, `diagnostics`, `hover`, `symbols`, `completion`, `rename`.

docs/features.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Many of these are standard LSP features, but a lot of special features are provi
77
| --------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
88
| [Diagnostics](#diagnostics) | `textDocument/publishDiagnostics` |
99
| [Hovers](#hovers) | `textDocument/hover` |
10+
| [Signature help](#signature-help) | `textDocument/signatureHelp` |
1011
| [Jump to definition](#jump-to-definition) | `textDocument/definition` |
1112
| [Jump to type definition](#jump-to-type-definition) | `textDocument/typeDefinition` |
1213
| [Find references](#find-references) | `textDocument/references` |
@@ -63,6 +64,12 @@ Provided by: `hls-explicit-fixity-plugin`
6364

6465
Provides fixity information.
6566

67+
## Signature help
68+
69+
Provided by: `hls-signature-help-plugin`
70+
71+
Shows and highlights the function signature, the function documentation and the arguments documentation when the cursor is at a function argument.
72+
6673
## Jump to definition
6774

6875
Provided by: `ghcide`
@@ -445,7 +452,6 @@ Contributions welcome!
445452

446453
| Feature | Status | [LSP method](./what-is-hls.md#lsp-terminology) |
447454
| ---------------------- | ----------------- | ---------------------------------------------- |
448-
| Signature help | Unimplemented | `textDocument/signatureHelp` |
449455
| Jump to declaration | Unclear if useful | `textDocument/declaration` |
450456
| Jump to implementation | Unclear if useful | `textDocument/implementation` |
451457
| Linked editing | Unimplemented | `textDocument/linkedEditingRange` |

docs/support/plugin-support.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ For example, a plugin to provide a formatter which has itself been abandoned has
5151
| `hls-class-plugin` | 2 | |
5252
| `hls-change-type-signature-plugin` | 2 | |
5353
| `hls-eval-plugin` | 2 | |
54+
| `hls-signature-help-plugin` | 2 | |
5455
| `hls-explicit-fixity-plugin` | 2 | |
5556
| `hls-explicit-record-fields-plugin` | 2 | |
5657
| `hls-fourmolu-plugin` | 2 | |

ghcide/src/Development/IDE/Core/Actions.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ getAtPoint file pos = runMaybeT $ do
6363

6464
(hf, mapping) <- useWithStaleFastMT GetHieAst file
6565
env <- hscEnv . fst <$> useWithStaleFastMT GhcSession file
66-
dkMap <- lift $ maybe (DKMap mempty mempty) fst <$> runMaybeT (useWithStaleFastMT GetDocMap file)
66+
dkMap <- lift $ maybe (DKMap mempty mempty mempty) fst <$> runMaybeT (useWithStaleFastMT GetDocMap file)
6767

6868
!pos' <- MaybeT (return $ fromCurrentPosition mapping pos)
6969
MaybeT $ liftIO $ fmap (first (toCurrentRange mapping =<<)) <$> AtPoint.atPoint opts hf dkMap env pos'

ghcide/src/Development/IDE/Core/RuleTypes.hs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -253,9 +253,15 @@ type instance RuleResult GetHieAst = HieAstResult
253253
-- | A IntervalMap telling us what is in scope at each point
254254
type instance RuleResult GetBindings = Bindings
255255

256-
data DocAndTyThingMap = DKMap {getDocMap :: !DocMap, getTyThingMap :: !TyThingMap}
256+
data DocAndTyThingMap = DKMap
257+
{ getDocMap :: !DocMap
258+
-- ^ Docs for declarations: functions, data types, instances, methods, etc
259+
, getTyThingMap :: !TyThingMap
260+
, getArgDocMap :: !ArgDocMap
261+
-- ^ Docs for arguments, e.g., function arguments and method arguments
262+
}
257263
instance NFData DocAndTyThingMap where
258-
rnf (DKMap a b) = rwhnf a `seq` rwhnf b
264+
rnf (DKMap a b c) = rwhnf a `seq` rwhnf b `seq` rwhnf c
259265

260266
instance Show DocAndTyThingMap where
261267
show = const "docmap"

ghcide/src/Development/IDE/Core/Rules.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -582,7 +582,7 @@ getDocMapRule recorder =
582582

583583
-- | Persistent rule to ensure that hover doesn't block on startup
584584
persistentDocMapRule :: Rules ()
585-
persistentDocMapRule = addPersistentRule GetDocMap $ \_ -> pure $ Just (DKMap mempty mempty, idDelta, Nothing)
585+
persistentDocMapRule = addPersistentRule GetDocMap $ \_ -> pure $ Just (DKMap mempty mempty mempty, idDelta, Nothing)
586586

587587
readHieFileForSrcFromDisk :: Recorder (WithPriority Log) -> NormalizedFilePath -> MaybeT IdeAction Compat.HieFile
588588
readHieFileForSrcFromDisk recorder file = do

ghcide/src/Development/IDE/GHC/Compat/Outputable.hs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ module Development.IDE.GHC.Compat.Outputable (
99
ppr, pprPanic, text, vcat, (<+>), ($$), empty, hang, nest, punctuate,
1010
printSDocQualifiedUnsafe,
1111
printWithoutUniques,
12+
printWithoutUniquesOneLine,
1213
mkPrintUnqualifiedDefault,
1314
PrintUnqualified,
1415
defaultUserStyle,
@@ -27,6 +28,7 @@ module Development.IDE.GHC.Compat.Outputable (
2728
pprMsgEnvelopeBagWithLoc,
2829
Error.getMessages,
2930
renderWithContext,
31+
showSDocOneLine,
3032
defaultSDocContext,
3133
errMsgDiagnostic,
3234
unDecorated,
@@ -76,8 +78,14 @@ type PrintUnqualified = NamePprCtx
7678
--
7779
-- It print with a user-friendly style like: `a_a4ME` as `a`.
7880
printWithoutUniques :: Outputable a => a -> String
79-
printWithoutUniques =
80-
renderWithContext (defaultSDocContext
81+
printWithoutUniques = printWithoutUniques' renderWithContext
82+
83+
printWithoutUniquesOneLine :: Outputable a => a -> String
84+
printWithoutUniquesOneLine = printWithoutUniques' showSDocOneLine
85+
86+
printWithoutUniques' :: Outputable a => (SDocContext -> SDoc -> String) -> a -> String
87+
printWithoutUniques' showSDoc =
88+
showSDoc (defaultSDocContext
8189
{
8290
sdocStyle = defaultUserStyle
8391
, sdocSuppressUniques = True

ghcide/src/Development/IDE/GHC/Util.hs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ module Development.IDE.GHC.Util(
2727
dontWriteHieFiles,
2828
disableWarningsAsErrors,
2929
printOutputable,
30+
printOutputableOneLine,
3031
getExtensions,
3132
stripOccNamePrefix,
3233
) where
@@ -264,11 +265,17 @@ ioe_dupHandlesNotCompatible h =
264265
-- 1. print with a user-friendly style: `a_a4ME` as `a`.
265266
-- 2. unescape escape sequences of printable unicode characters within a pair of double quotes
266267
printOutputable :: Outputable a => a -> T.Text
267-
printOutputable =
268+
printOutputable = printOutputable' printWithoutUniques
269+
270+
printOutputableOneLine :: Outputable a => a -> T.Text
271+
printOutputableOneLine = printOutputable' printWithoutUniquesOneLine
272+
273+
printOutputable' :: Outputable a => (a -> String) -> a -> T.Text
274+
printOutputable' print =
268275
-- IfaceTyLit from GHC.Iface.Type implements Outputable with 'show'.
269276
-- Showing a String escapes non-ascii printable characters. We unescape it here.
270277
-- More discussion at https://github.com/haskell/haskell-language-server/issues/3115.
271-
unescape . T.pack . printWithoutUniques
278+
unescape . T.pack . print
272279
{-# INLINE printOutputable #-}
273280

274281
getExtensions :: ParsedModule -> [Extension]

0 commit comments

Comments
 (0)