From a00161e46561f5f63a3e5a258e233d9bc6bbf215 Mon Sep 17 00:00:00 2001 From: Sam McCall Date: Tue, 20 Apr 2021 22:00:34 +0200 Subject: [PATCH 1/9] Add textDocument/inlayHints (First draft, several points left open) --- _data/specification-3-17-toc.yml | 2 + _specifications/specification-3-17.md | 177 ++++++++++++++++++++++++++ 2 files changed, 179 insertions(+) diff --git a/_data/specification-3-17-toc.yml b/_data/specification-3-17-toc.yml index 4e6d4763f..bd0b1c5a3 100644 --- a/_data/specification-3-17-toc.yml +++ b/_data/specification-3-17-toc.yml @@ -229,6 +229,8 @@ anchor: textDocument_linkedEditingRange - title: moniker anchor: textDocument_moniker + - title: inlay hints + anchor: textDocument_inlayHints - title: Change Log anchor: changeLog children: diff --git a/_specifications/specification-3-17.md b/_specifications/specification-3-17.md index 759b61aa6..684794dc1 100644 --- a/_specifications/specification-3-17.md +++ b/_specifications/specification-3-17.md @@ -8217,6 +8217,182 @@ export interface Moniker { Server implementations of this method should ensure that the moniker calculation matches to those used in the corresponding LSIF implementation to ensure symbols can be associated correctly across IDE sessions and LSIF indexes. +#### Inlay hints (:leftwards_arrow_with_hook:) + +> *Since version 3.17.0* + +Inlay hints are short textual annotations that are attached to ranges in the source code. + +**TODO**: Is "inlay hints" too presentational a name? The protocol allows other UI (e.g. pop-up when cursor is in the target range). + +These typically spell out some inferred information, such as the parameter name when passing a value to a function. + +```typescript +/** + * Well-known kinds of information conveyed by InlayHints. + * This is not an exhaustive list, servers may use other categories as needed. + */ +export enum InlayHintCategory { + /** + * The range is an expression passed as an argument to a function. + * The label is the name of the parameter. + */ + 'parameter', + /** + * The range is an entity whose type is unknown. + * The label is its inferred type. + */ + 'type' +} +``` + +Hints may be grouped into server-defined _classes_. +Hints in the same class are displayed in similar ways, and the class avoids duplicating this information in each hint. + +**TODO**: classes might be useful "subcategories" for users to enable/disable hints. If so, they'd need a description. + +**TODO**: are classes actually useful? should we just inline this info into the hints? + +```typescript +export interface InlayHintClass { + /** + * The kind of information this hint conveys. + * May be an InlayHintCategory or any other value. + */ + category?: string; + + /** + * The placement of the label, when displayed inline. + * "start" and "end" mean insertion at the endpoints of the target range. + * Default is "start". + */ + position?: "start" | "end"; + + /** + * Text to be displayed before the label when displayed inline. + * Typically this is punctuation allowing it to read naturally as code. + */ + prefix?: string; + /** + * Text to be displayed after the label when displayed inline. + */ + suffix?: string; +} +``` + +The `textDocument/inlayHints` request is sent from the client to the server to retrieve inlay hints for a document. + +_Client Capabilities_: + +* property name (optional): `textDocument.inlayHints` +* property type: `InlayHintsClientCapabilities` defined as follows: + +```typescript +interface InlayHintsClientCapabilities { + /** + * Whether implementation supports dynamic registration. If this is set to + * `true` the client supports the new `(TextDocumentRegistrationOptions & + * StaticRegistrationOptions)` return value for the corresponding server + * capability as well. + */ + dynamicRegistration?: boolean; +} +``` + +_Server Capability_: + +* property name (optional): `inlayHintsProvider` +* property type: `boolean | InlayHintsOptions | InlayHintsRegistrationOptions` is defined as follows: + +```typescript +export interface InlayHintsOptions extends WorkDoneProgressOptions { + /** + * Defines the classes of hints the server will provide. + * Individual hints may reference one of these by index. + */ + hintClasses?: InlayHintClass[], + + /** + * Whether the server supports retrieving inlay hints for a limited range + * within a document. + */ + range?: boolean; +} +``` + +_Registration Options_: `InlayHintsRegistrationOptions` defined as follows: + +```typescript +export interface InlayHintsRegistrationOptions extends + TextDocumentRegistrationOptions, InlayHintsOptions { +} +``` + +_Request_: + +* method: `textDocument/inlayHints` +* params: `InlayHintsParams` defined as follows: + +```typescript +export interface InlayHintsParams extends WorkDoneProgressParams, PartialResultParams { + /** + * The text document. + */ + textDocument: TextDocumentIdentifier; + + /** + * The range the inlay hints are requested for. + * If unset, returns all hints for the document. + * Servers that do not set InlayHintsOptions.range may ignore this. + * + * TODO: it's more common in LSP to have a separate request - do we need to? + */ + range?: Range; + + // TODO: is 'only' useful in practice? +} +``` + +_Response_: + +* result: `InlayHint[]` +* partial result: `InlayHint[]` +* error: code and message set in case an exception happens during the 'textDocument/inlayHint' request + +`InlayHint` is defined as follows: + +```typescript +/** + * An inlay hint is a short textual annotation for a range of source code. + */ +export interface InlayHint { + /** + * The value to be shown. + */ + label: string; + + /** + * The range of text this hint is attached to. + * May affect when the hint is displayed, and the effect of selecting it. + */ + target: Range; + + /** + * References an InlayHintClass that provides additional properties. + * This is an index into InlayHintsOptions.hintClasses. + */ + hintClass?: uinteger + + /** + * The placement of the label, when displayed inline. + * This overrides the default value set by the class. + */ + position?: Position; +} +``` + +**TODO**: Do we need a `/refresh` server->client call, like with SemanticTokens and Code Lens? + ### Implementation Considerations Language servers usually run in a separate process and client communicate with them in an asynchronous fashion. Additionally clients usually allow users to interact with the source code even if request results are pending. We recommend the following implementation pattern to avoid that clients apply outdated response results: @@ -8240,6 +8416,7 @@ Servers usually support different communication channels (e.g. stdio, pipes, ... #### 3.17.0 (xx/xx/xxxx) * Add support for a completion item label details. +* Add support for inlay hints. #### 3.16.0 (12/14/2020) From 99d150d66c0be49d5c3c8fe8ea9fdcbcfd772c03 Mon Sep 17 00:00:00 2001 From: Sam McCall Date: Wed, 21 Apr 2021 17:16:58 +0200 Subject: [PATCH 2/9] Clarify open-ness and purpose of category enum. Add only for filtering. --- _specifications/specification-3-17.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/_specifications/specification-3-17.md b/_specifications/specification-3-17.md index 684794dc1..7adf6d6ea 100644 --- a/_specifications/specification-3-17.md +++ b/_specifications/specification-3-17.md @@ -8230,7 +8230,7 @@ These typically spell out some inferred information, such as the parameter name ```typescript /** * Well-known kinds of information conveyed by InlayHints. - * This is not an exhaustive list, servers may use other categories as needed. + * Clients may choose to display hints from some categories but not others. */ export enum InlayHintCategory { /** @@ -8257,7 +8257,8 @@ Hints in the same class are displayed in similar ways, and the class avoids dupl export interface InlayHintClass { /** * The kind of information this hint conveys. - * May be an InlayHintCategory or any other value. + * May be an InlayHintCategory or any other value, clients should treat + * unrecognized values as if missing. */ category?: string; @@ -8349,7 +8350,12 @@ export interface InlayHintsParams extends WorkDoneProgressParams, PartialResultP */ range?: Range; - // TODO: is 'only' useful in practice? + /** + * The categories of inlay hints that are interesting to the client. + * The client should filter out hints of other categories, so the server may + * skip computing them. + */ + only?: string[]; } ``` From f414076dc2d5cdba1790d14660e068e8e32a125b Mon Sep 17 00:00:00 2001 From: Sam McCall Date: Wed, 21 Apr 2021 17:18:01 +0200 Subject: [PATCH 3/9] Resolve question on presentational naming. Hover is a good precedent --- _specifications/specification-3-17.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/_specifications/specification-3-17.md b/_specifications/specification-3-17.md index 7adf6d6ea..d9eb9aa53 100644 --- a/_specifications/specification-3-17.md +++ b/_specifications/specification-3-17.md @@ -8222,9 +8222,6 @@ Server implementations of this method should ensure that the moniker calculation > *Since version 3.17.0* Inlay hints are short textual annotations that are attached to ranges in the source code. - -**TODO**: Is "inlay hints" too presentational a name? The protocol allows other UI (e.g. pop-up when cursor is in the target range). - These typically spell out some inferred information, such as the parameter name when passing a value to a function. ```typescript From 6e6379b30b3f657f965de51593dd02a932229bc7 Mon Sep 17 00:00:00 2001 From: Sam McCall Date: Wed, 21 Apr 2021 17:22:35 +0200 Subject: [PATCH 4/9] Add TODO - should we hint at future plans? --- _specifications/specification-3-17.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/_specifications/specification-3-17.md b/_specifications/specification-3-17.md index d9eb9aa53..ca3fda29c 100644 --- a/_specifications/specification-3-17.md +++ b/_specifications/specification-3-17.md @@ -8396,6 +8396,8 @@ export interface InlayHint { **TODO**: Do we need a `/refresh` server->client call, like with SemanticTokens and Code Lens? +**TODO**: Likely future evolution: add a `/resolve` call enabling interactions with hints. Should we foreshadow this? + ### Implementation Considerations Language servers usually run in a separate process and client communicate with them in an asynchronous fashion. Additionally clients usually allow users to interact with the source code even if request results are pending. We recommend the following implementation pattern to avoid that clients apply outdated response results: From 08804d43f2c9145965c32f8ac59cc6a4838bb973 Mon Sep 17 00:00:00 2001 From: Sam McCall Date: Wed, 21 Apr 2021 17:22:51 +0200 Subject: [PATCH 5/9] Tweak wording --- _specifications/specification-3-17.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_specifications/specification-3-17.md b/_specifications/specification-3-17.md index ca3fda29c..619d5ff92 100644 --- a/_specifications/specification-3-17.md +++ b/_specifications/specification-3-17.md @@ -8227,7 +8227,7 @@ These typically spell out some inferred information, such as the parameter name ```typescript /** * Well-known kinds of information conveyed by InlayHints. - * Clients may choose to display hints from some categories but not others. + * Clients may choose which categories to display according to user preferences. */ export enum InlayHintCategory { /** From 84d0fe3333fa33a509a3185968ca30e758b28bf5 Mon Sep 17 00:00:00 2001 From: Sam McCall Date: Thu, 27 May 2021 16:21:42 +0200 Subject: [PATCH 6/9] Remove classes (and position=before/after, prefix/suffix) --- _specifications/specification-3-17.md | 56 +++------------------------ 1 file changed, 5 insertions(+), 51 deletions(-) diff --git a/_specifications/specification-3-17.md b/_specifications/specification-3-17.md index 619d5ff92..66fcd61f1 100644 --- a/_specifications/specification-3-17.md +++ b/_specifications/specification-3-17.md @@ -8243,41 +8243,6 @@ export enum InlayHintCategory { } ``` -Hints may be grouped into server-defined _classes_. -Hints in the same class are displayed in similar ways, and the class avoids duplicating this information in each hint. - -**TODO**: classes might be useful "subcategories" for users to enable/disable hints. If so, they'd need a description. - -**TODO**: are classes actually useful? should we just inline this info into the hints? - -```typescript -export interface InlayHintClass { - /** - * The kind of information this hint conveys. - * May be an InlayHintCategory or any other value, clients should treat - * unrecognized values as if missing. - */ - category?: string; - - /** - * The placement of the label, when displayed inline. - * "start" and "end" mean insertion at the endpoints of the target range. - * Default is "start". - */ - position?: "start" | "end"; - - /** - * Text to be displayed before the label when displayed inline. - * Typically this is punctuation allowing it to read naturally as code. - */ - prefix?: string; - /** - * Text to be displayed after the label when displayed inline. - */ - suffix?: string; -} -``` - The `textDocument/inlayHints` request is sent from the client to the server to retrieve inlay hints for a document. _Client Capabilities_: @@ -8304,12 +8269,6 @@ _Server Capability_: ```typescript export interface InlayHintsOptions extends WorkDoneProgressOptions { - /** - * Defines the classes of hints the server will provide. - * Individual hints may reference one of these by index. - */ - hintClasses?: InlayHintClass[], - /** * Whether the server supports retrieving inlay hints for a limited range * within a document. @@ -8370,7 +8329,7 @@ _Response_: */ export interface InlayHint { /** - * The value to be shown. + * The text to be shown. */ label: string; @@ -8381,16 +8340,11 @@ export interface InlayHint { target: Range; /** - * References an InlayHintClass that provides additional properties. - * This is an index into InlayHintsOptions.hintClasses. + * The kind of information this hint conveys. + * May be an InlayHintCategory or any other value, clients should treat + * unrecognized values as if missing. */ - hintClass?: uinteger - - /** - * The placement of the label, when displayed inline. - * This overrides the default value set by the class. - */ - position?: Position; + category?: string; } ``` From c62fb012f473b37ea81a9b193905bb0d4523a8a8 Mon Sep 17 00:00:00 2001 From: Sam McCall Date: Thu, 27 May 2021 16:22:31 +0200 Subject: [PATCH 7/9] Make range support mandatory for servers --- _specifications/specification-3-17.md | 8 -------- 1 file changed, 8 deletions(-) diff --git a/_specifications/specification-3-17.md b/_specifications/specification-3-17.md index 66fcd61f1..67a7a4575 100644 --- a/_specifications/specification-3-17.md +++ b/_specifications/specification-3-17.md @@ -8269,11 +8269,6 @@ _Server Capability_: ```typescript export interface InlayHintsOptions extends WorkDoneProgressOptions { - /** - * Whether the server supports retrieving inlay hints for a limited range - * within a document. - */ - range?: boolean; } ``` @@ -8300,9 +8295,6 @@ export interface InlayHintsParams extends WorkDoneProgressParams, PartialResultP /** * The range the inlay hints are requested for. * If unset, returns all hints for the document. - * Servers that do not set InlayHintsOptions.range may ignore this. - * - * TODO: it's more common in LSP to have a separate request - do we need to? */ range?: Range; From f82e51b0cebb048c1f522e93d01119d72d0e90ed Mon Sep 17 00:00:00 2001 From: Sam McCall Date: Thu, 27 May 2021 16:24:55 +0200 Subject: [PATCH 8/9] Attach to positions rather than ranges in code --- _specifications/specification-3-17.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/_specifications/specification-3-17.md b/_specifications/specification-3-17.md index 67a7a4575..406884c11 100644 --- a/_specifications/specification-3-17.md +++ b/_specifications/specification-3-17.md @@ -8221,7 +8221,7 @@ Server implementations of this method should ensure that the moniker calculation > *Since version 3.17.0* -Inlay hints are short textual annotations that are attached to ranges in the source code. +Inlay hints are short textual annotations that are attached to points in the source code. These typically spell out some inferred information, such as the parameter name when passing a value to a function. ```typescript @@ -8326,10 +8326,9 @@ export interface InlayHint { label: string; /** - * The range of text this hint is attached to. - * May affect when the hint is displayed, and the effect of selecting it. + * The position within the code this hint is attached to. */ - target: Range; + position: Position; /** * The kind of information this hint conveys. From d55733dda4317da4ea9386e35d8ebc5be1d944e2 Mon Sep 17 00:00:00 2001 From: Sam McCall Date: Sat, 29 May 2021 13:49:45 +0200 Subject: [PATCH 9/9] Fix type of InlayHintCategory values --- _specifications/specification-3-17.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_specifications/specification-3-17.md b/_specifications/specification-3-17.md index 406884c11..763ceff1d 100644 --- a/_specifications/specification-3-17.md +++ b/_specifications/specification-3-17.md @@ -8234,12 +8234,12 @@ export enum InlayHintCategory { * The range is an expression passed as an argument to a function. * The label is the name of the parameter. */ - 'parameter', + Parameter = 'parameter', /** * The range is an entity whose type is unknown. * The label is its inferred type. */ - 'type' + Type = 'type' } ```