Skip to content

Show variant constructor's inline record types on hover #7519

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
May 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
- Add `RegExp.flags`. https://github.com/rescript-lang/rescript/pull/7461
- Add `Array.findLast`, `Array.findLastWithIndex`, `Array.findLastIndex`, `Array.findLastIndexWithIndex` and `Array.findLastIndexOpt`. https://github.com/rescript-lang/rescript/pull/7503
- Add `options` argument to `Console.dir`. https://github.com/rescript-lang/rescript/pull/7504
- Show variant constructor's inline record types on hover. https://github.com/rescript-lang/rescript/pull/7519

#### :bug: Bug fix

Expand Down
45 changes: 21 additions & 24 deletions analysis/src/Hover.ml
Original file line number Diff line number Diff line change
Expand Up @@ -137,13 +137,21 @@ let expandTypes ~file ~package ~supportsMarkdownLinks typ =
`Default )

(* Produces a hover with relevant types expanded in the main type being hovered. *)
let hoverWithExpandedTypes ~file ~package ~supportsMarkdownLinks typ =
let typeString = Markdown.codeBlock (typ |> Shared.typeToString) in
let hoverWithExpandedTypes ~file ~package ~supportsMarkdownLinks ?constructor
typ =
let expandedTypes, expansionType =
expandTypes ~file ~package ~supportsMarkdownLinks typ
in
match expansionType with
| `Default -> typeString :: expandedTypes |> String.concat "\n"
| `Default ->
let typeString = Shared.typeToString typ in
let typeString =
match constructor with
| Some constructor ->
typeString ^ "\n" ^ CompletionBackEnd.showConstructor constructor
| None -> typeString
in
Markdown.codeBlock typeString :: expandedTypes |> String.concat "\n"
| `InlineType -> expandedTypes |> String.concat "\n"

(* Leverages autocomplete functionality to produce a hover for a position. This
Expand Down Expand Up @@ -256,33 +264,22 @@ let newHover ~full:{file; package} ~supportsMarkdownLinks locItem =
| Const_int64 _ -> "int64"
| Const_bigint _ -> "bigint"))
| Typed (_, t, locKind) ->
let fromType ~docstring typ =
( hoverWithExpandedTypes ~file ~package ~supportsMarkdownLinks typ,
docstring )
let fromType ?constructor typ =
hoverWithExpandedTypes ~file ~package ~supportsMarkdownLinks ?constructor
typ
in
let parts =
match References.definedForLoc ~file ~package locKind with
| None ->
let typeString, docstring = t |> fromType ~docstring:[] in
typeString :: docstring
let typeString = t |> fromType in
[typeString]
| Some (docstring, res) -> (
match res with
| `Declared ->
let typeString, docstring = t |> fromType ~docstring in
| `Declared | `Field ->
let typeString = t |> fromType in
typeString :: docstring
| `Constructor {cname = {txt}; args; docstring} ->
let typeString, docstring = t |> fromType ~docstring in
let argsString =
match args with
| InlineRecord _ | Args [] -> ""
| Args args ->
args
|> List.map (fun (t, _) -> Shared.typeToString t)
|> String.concat ", " |> Printf.sprintf "(%s)"
in
typeString :: Markdown.codeBlock (txt ^ argsString) :: docstring
| `Field ->
let typeString, docstring = t |> fromType ~docstring in
typeString :: docstring)
| `Constructor constructor ->
let typeString = t |> fromType ~constructor in
typeString :: constructor.docstring)
in
Some (String.concat Markdown.divider parts)
8 changes: 8 additions & 0 deletions tests/analysis_tests/tests/src/Hover.res
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,14 @@ type variant = | /** Cool variant! */ CoolVariant | /** Other cool variant */ Ot
let coolVariant = CoolVariant
// ^hov

type payloadVariants = InlineRecord({field1: int, field2: bool}) | Args(int, bool)

let payloadVariant = InlineRecord({field1: 1, field2: true})
// ^hov

let payloadVariant2 = Args(1, true)
// ^hov

// Hover on unsaved
// let fff = "hello"; fff
// ^hov
Expand Down
24 changes: 15 additions & 9 deletions tests/analysis_tests/tests/src/expected/Hover.res.txt
Original file line number Diff line number Diff line change
Expand Up @@ -301,12 +301,18 @@ Hover src/Hover.res 248:19
{"contents": {"kind": "markdown", "value": "```rescript\nbool\n```\n---\n Mighty fine field here. "}}

Hover src/Hover.res 253:20
{"contents": {"kind": "markdown", "value": "```rescript\nvariant\n```\n\n---\n\n```\n \n```\n```rescript\ntype variant = CoolVariant | OtherCoolVariant\n```\nGo to: [Type definition](command:rescript-vscode.go_to_location?%5B%22Hover.res%22%2C251%2C0%5D)\n\n---\n```rescript\nCoolVariant\n```\n---\n Cool variant! "}}
{"contents": {"kind": "markdown", "value": "```rescript\nvariant\nCoolVariant\n```\n\n---\n\n```\n \n```\n```rescript\ntype variant = CoolVariant | OtherCoolVariant\n```\nGo to: [Type definition](command:rescript-vscode.go_to_location?%5B%22Hover.res%22%2C251%2C0%5D)\n\n---\n Cool variant! "}}

Hover src/Hover.res 257:23
Hover src/Hover.res 258:22
{"contents": {"kind": "markdown", "value": "```rescript\npayloadVariants\nInlineRecord({field1: int, field2: bool})\n```\n\n---\n\n```\n \n```\n```rescript\ntype payloadVariants =\n | InlineRecord({field1: int, field2: bool})\n | Args(int, bool)\n```\nGo to: [Type definition](command:rescript-vscode.go_to_location?%5B%22Hover.res%22%2C256%2C0%5D)\n"}}

Hover src/Hover.res 261:23
{"contents": {"kind": "markdown", "value": "```rescript\npayloadVariants\nArgs(int, bool)\n```\n\n---\n\n```\n \n```\n```rescript\ntype payloadVariants =\n | InlineRecord({field1: int, field2: bool})\n | Args(int, bool)\n```\nGo to: [Type definition](command:rescript-vscode.go_to_location?%5B%22Hover.res%22%2C256%2C0%5D)\n"}}

Hover src/Hover.res 265:23
Nothing at that position. Now trying to use completion.
posCursor:[257:23] posNoWhite:[257:22] Found expr:[257:22->257:25]
Pexp_ident fff:[257:22->257:25]
posCursor:[265:23] posNoWhite:[265:22] Found expr:[265:22->265:25]
Pexp_ident fff:[265:22->265:25]
Completable: Cpath Value[fff]
Package opens Stdlib.place holder Pervasives.JsxModules.place holder
Resolved opens 1 Stdlib
Expand All @@ -317,10 +323,10 @@ Resolved opens 1 Stdlib
ContextPath string
{"contents": {"kind": "markdown", "value": "```rescript\nstring\n```"}}

Hover src/Hover.res 260:33
Hover src/Hover.res 268:33
Nothing at that position. Now trying to use completion.
posCursor:[260:33] posNoWhite:[260:32] Found expr:[260:31->260:40]
Pexp_ident someField:[260:31->260:40]
posCursor:[268:33] posNoWhite:[268:32] Found expr:[268:31->268:40]
Pexp_ident someField:[268:31->268:40]
Completable: Cpath Value[someField]
Package opens Stdlib.place holder Pervasives.JsxModules.place holder
Resolved opens 1 Stdlib
Expand All @@ -333,9 +339,9 @@ ContextPath Value[x]
Path x
{"contents": {"kind": "markdown", "value": "```rescript\nbool\n```"}}

Hover src/Hover.res 263:8
Hover src/Hover.res 271:8
{"contents": {"kind": "markdown", "value": "\n [`Belt.Array`]()\n\n **mutable array**: Utilities functions\n\n```rescript\nmodule Array: {\n module Id\n module Array\n module SortArray\n module MutableQueue\n module MutableStack\n module List\n module Range\n module Set\n module Map\n module MutableSet\n module MutableMap\n module HashSet\n module HashMap\n module Option\n module Result\n module Int\n module Float\n}\n```"}}

Hover src/Hover.res 266:6
Hover src/Hover.res 274:6
{"contents": {"kind": "markdown", "value": "```rescript\ntype aliased = variant\n```\n\n---\n\n```\n \n```\n```rescript\ntype variant = CoolVariant | OtherCoolVariant\n```\nGo to: [Type definition](command:rescript-vscode.go_to_location?%5B%22Hover.res%22%2C251%2C0%5D)\n"}}