Skip to content
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

Suggest field name in completion of options in record fields #766

Merged
merged 2 commits into from
Apr 28, 2023
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 @@ -15,6 +15,7 @@
#### :rocket: New Feature

- Docstring template Code Action. https://github.com/rescript-lang/rescript-vscode/pull/764
- Add `Some(fieldName)` case when completing in a pattern with an option on a record field. https://github.com/rescript-lang/rescript-vscode/pull/766

## 1.16.0

Expand Down
29 changes: 21 additions & 8 deletions analysis/src/CompletionBackEnd.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1235,13 +1235,26 @@ let rec completeTypedValue ~full ~prefix ~completionContext ~mode
| Some insertText -> Some ("Some(" ^ insertText ^ ")"));
})
in
[
Completion.create "None" ~kind:(kindFromInnerType t) ~env;
let noneCase = Completion.create "None" ~kind:(kindFromInnerType t) ~env in
let someAnyCase =
Completion.createWithSnippet ~name:"Some(_)" ~kind:(kindFromInnerType t)
~env ~insertText:"Some(${1:_})" ();
]
@ expandedCompletions
|> filterItems ~prefix
~env ~insertText:"Some(${1:_})" ()
in
let completions =
match completionContext with
| Some (Completable.CameFromRecordField fieldName) ->
[
Completion.createWithSnippet
~name:("Some(" ^ fieldName ^ ")")
~kind:(kindFromInnerType t) ~env
~insertText:("Some(${1:" ^ fieldName ^ "})")
();
someAnyCase;
noneCase;
]
| _ -> [noneCase; someAnyCase]
in
completions @ expandedCompletions |> filterItems ~prefix
| Tuple (env, exprs, typ) ->
let numExprs = List.length exprs in
[
Expand Down Expand Up @@ -1279,7 +1292,7 @@ let rec completeTypedValue ~full ~prefix ~completionContext ~mode
(Field (field, TypeUtils.extractedTypeToString extractedType))
~env)
|> filterItems ~prefix
| None ->
| _ ->
if prefix = "" then
[
Completion.createWithSnippet ~name:"{}"
Expand All @@ -1304,7 +1317,7 @@ let rec completeTypedValue ~full ~prefix ~completionContext ~mode
Completion.create field.fname.txt ~kind:(Label "Inline record")
?deprecated:field.deprecated ~env)
|> filterItems ~prefix
| None ->
| _ ->
if prefix = "" then
[
Completion.createWithSnippet ~name:"{}"
Expand Down
7 changes: 6 additions & 1 deletion analysis/src/SharedTypes.ml
Original file line number Diff line number Diff line change
Expand Up @@ -529,7 +529,12 @@ module Completable = struct
| Optional of string

(** Additional context for nested completion where needed. *)
type nestedContext = RecordField of {seenFields: string list}
type nestedContext =
| RecordField of {seenFields: string list}
(** Completing for a record field, and we already saw the following fields... *)
| CameFromRecordField of string
(** We just came from this field (we leverage use this for better
completion names etc) *)

type nestedPath =
| NTupleItem of {itemNum: int}
Expand Down
16 changes: 13 additions & 3 deletions analysis/src/TypeUtils.ml
Original file line number Diff line number Diff line change
Expand Up @@ -257,10 +257,20 @@ let extractTypeFromResolvedType (typ : Type.t) ~env ~full =
| None -> None
| Some t -> t |> extractType ~env ~package:full.package)

(** The context we just came from as we resolve the nested structure. *)
type ctx = Rfield of string (** A record field of name *)

(** This moves through a nested path via a set of instructions, trying to resolve the type at the end of the path. *)
let rec resolveNested (typ : completionType) ~env ~full ~nested =
let rec resolveNested ~env ~full ~nested ?ctx (typ : completionType) =
match nested with
| [] -> Some (typ, env, None)
| [] ->
Some
( typ,
env,
match ctx with
| None -> None
| Some (Rfield fieldName) ->
Some (Completable.CameFromRecordField fieldName) )
| patternPath :: nested -> (
match (patternPath, typ) with
| Completable.NTupleItem {itemNum}, Tuple (env, tupleItems, _) -> (
Expand All @@ -283,7 +293,7 @@ let rec resolveNested (typ : completionType) ~env ~full ~nested =
typ
|> extractType ~env ~package:full.package
|> Utils.Option.flatMap (fun typ ->
typ |> resolveNested ~env ~full ~nested))
typ |> resolveNested ~ctx:(Rfield fieldName) ~env ~full ~nested))
| NRecordBody {seenFields}, Trecord {env; definition = `TypeExpr typeExpr}
->
typeExpr
Expand Down
37 changes: 20 additions & 17 deletions analysis/tests/src/expected/CompletionExpressions.res.txt
Original file line number Diff line number Diff line change
Expand Up @@ -191,11 +191,13 @@ ContextPath CArgument Value[fnTakingRecord]($0)
ContextPath Value[fnTakingRecord]
Path fnTakingRecord
[{
"label": "None",
"label": "Some(nested)",
"kind": 12,
"tags": [],
"detail": "otherRecord",
"documentation": null
"documentation": null,
"insertText": "Some(${1:nested})",
"insertTextFormat": 2
}, {
"label": "Some(_)",
"kind": 12,
Expand All @@ -204,6 +206,12 @@ Path fnTakingRecord
"documentation": null,
"insertText": "Some(${1:_})",
"insertTextFormat": 2
}, {
"label": "None",
"kind": 12,
"tags": [],
"detail": "otherRecord",
"documentation": null
}, {
"label": "Some({})",
"kind": 12,
Expand Down Expand Up @@ -298,21 +306,8 @@ Path fnTakingRecord
"tags": [],
"detail": "One\n\ntype someVariant = One | Two | Three(int, string)",
"documentation": null,
"sortText": "A One",
"insertText": "One",
"insertTextFormat": 2
}, {
"label": "Obj",
"kind": 9,
"tags": [],
"detail": "file module",
"documentation": null
}, {
"label": "Objects",
"kind": 9,
"tags": [],
"detail": "file module",
"documentation": null
}]

Complete src/CompletionExpressions.res 56:57
Expand Down Expand Up @@ -616,11 +611,13 @@ ContextPath CArgument Value[fnTakingRecordWithOptVariant]($0)
ContextPath Value[fnTakingRecordWithOptVariant]
Path fnTakingRecordWithOptVariant
[{
"label": "None",
"label": "Some(someVariant)",
"kind": 12,
"tags": [],
"detail": "someVariant",
"documentation": null
"documentation": null,
"insertText": "Some(${1:someVariant})",
"insertTextFormat": 2
}, {
"label": "Some(_)",
"kind": 12,
Expand All @@ -629,6 +626,12 @@ Path fnTakingRecordWithOptVariant
"documentation": null,
"insertText": "Some(${1:_})",
"insertTextFormat": 2
}, {
"label": "None",
"kind": 12,
"tags": [],
"detail": "someVariant",
"documentation": null
}, {
"label": "Some(One)",
"kind": 4,
Expand Down