From 105ed492252520993e17116a9aa0c39224ccb22b Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Thu, 29 Dec 2022 22:31:49 +0100 Subject: [PATCH 1/4] complete polyvariants --- analysis/src/CompletionBackEnd.ml | 49 +++++++++++++ analysis/src/CompletionFrontEnd.ml | 3 +- analysis/src/SharedTypes.ml | 14 +++- analysis/tests/src/CompletionJsxProps.res | 6 ++ analysis/tests/src/CompletionSupport.res | 7 +- .../src/expected/CompletionJsxProps.res.txt | 68 +++++++++++++++++++ 6 files changed, 144 insertions(+), 3 deletions(-) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index daaa056f6..2253303b1 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -711,6 +711,14 @@ let detail name (kind : Completion.kind) = | FileModule _ -> "file module" | Field ({typ}, s) -> name ^ ": " ^ (typ |> Shared.typeToString) ^ "\n\n" ^ s | Constructor (c, s) -> showConstructor c ^ "\n\n" ^ s + | PolyvariantConstructor ({name; payload}, s) -> + "#" ^ name + ^ (match payload with + | None -> "" + | Some ({desc = Types.Ttuple _} as typeExpr) -> + typeExpr |> Shared.typeToString + | Some typeExpr -> "(" ^ (typeExpr |> Shared.typeToString) ^ ")") + ^ "\n\n" ^ s let findAllCompletions ~(env : QueryEnv.t) ~prefix ~exact ~namesUsed ~(completionContext : Completable.completionContext) = @@ -1519,6 +1527,27 @@ let rec extractType ~env ~package (t : Types.type_expr) = {env; constructors; variantName = name.txt; variantDecl = decl}) | _ -> None) | Ttuple expressions -> Some (Tuple (env, expressions, t)) + | Tvariant {row_fields} -> + let constructors = + row_fields + |> List.map (fun (label, field) -> + { + name = label; + payload = + (match field with + | Types.Rpresent maybeTypeExpr -> maybeTypeExpr + | _ -> None); + args = + (* Multiple arguments are represented as a Ttuple, while a single argument is just the type expression itself. *) + (match field with + | Types.Rpresent (Some typeExpr) -> ( + match typeExpr.desc with + | Ttuple args -> args + | _ -> [typeExpr]) + | _ -> []); + }) + in + Some (Tpolyvariant {env; constructors; typeExpr = t}) | _ -> None let filterItems items ~prefix = @@ -1575,6 +1604,26 @@ let completeTypedValue ~env ~envWhereCompletionStarted ~full ~prefix variantDecl |> Shared.declToString variantName )) ~env ()) |> filterItems ~prefix + | Some (Tpolyvariant {env; constructors; typeExpr}) -> + constructors + |> List.map (fun (constructor : polyVariantConstructor) -> + Completion.createWithSnippet + ~name: + ("#" ^ constructor.name + ^ printConstructorArgs + (List.length constructor.args) + ~asSnippet:false) + ~insertText: + ((if Utils.startsWith prefix "#" then "" else "#") + ^ constructor.name + ^ printConstructorArgs + (List.length constructor.args) + ~asSnippet:true) + ~kind: + (PolyvariantConstructor + (constructor, typeExpr |> Shared.typeToString)) + ~env ()) + |> filterItems ~prefix | Some (Toption (env, t)) -> [ Completion.create ~name:"None" diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index 5203c1572..aaeee4dd1 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -11,7 +11,8 @@ let extractCompletableArgValueInfo exp = match exp.Parsetree.pexp_desc with | Pexp_ident {txt = Lident txt} -> Some txt | Pexp_construct ({txt = Lident "()"}, _) -> Some "" - | Pexp_construct ({txt = Lident txt}, _) -> Some txt + | Pexp_construct ({txt = Lident txt}, None) -> Some txt + | Pexp_variant (label, None) -> Some ("#" ^ label) | _ -> None let isExprHole exp = diff --git a/analysis/src/SharedTypes.ml b/analysis/src/SharedTypes.ml index b68eb57ee..5d35e3518 100644 --- a/analysis/src/SharedTypes.ml +++ b/analysis/src/SharedTypes.ml @@ -279,6 +279,12 @@ end = struct {env with exported = structure.exported; pathRev; parent = Some env} end +type polyVariantConstructor = { + name: string; + payload: Types.type_expr option; + args: Types.type_expr list; +} + module Completion = struct type kind = | Module of Module.t @@ -287,6 +293,7 @@ module Completion = struct | Label of string | Type of Type.t | Constructor of Constructor.t * string + | PolyvariantConstructor of polyVariantConstructor * string | Field of field * string | FileModule of string @@ -331,7 +338,7 @@ module Completion = struct match kind with | Module _ -> 9 | FileModule _ -> 9 - | Constructor (_, _) -> 4 + | Constructor (_, _) | PolyvariantConstructor (_, _) -> 4 | ObjLabel _ -> 4 | Label _ -> 4 | Field (_, _) -> 5 @@ -578,6 +585,11 @@ module Completable = struct variantDecl: Types.type_declaration; variantName: string; } + | Tpolyvariant of { + env: QueryEnv.t; + constructors: polyVariantConstructor list; + typeExpr: Types.type_expr; + } let toString = let completionContextToString = function diff --git a/analysis/tests/src/CompletionJsxProps.res b/analysis/tests/src/CompletionJsxProps.res index 65f5fa7e1..41dcfe57f 100644 --- a/analysis/tests/src/CompletionJsxProps.res +++ b/analysis/tests/src/CompletionJsxProps.res @@ -7,3 +7,9 @@ // let _ = { + let make = ( + ~on: bool, + ~test: testVariant, + ~polyArg: option<[#one | #two | #two2 | #three(int, bool)]>=?, + ) => { ignore(on) ignore(test) + ignore(polyArg) React.null } } diff --git a/analysis/tests/src/expected/CompletionJsxProps.res.txt b/analysis/tests/src/expected/CompletionJsxProps.res.txt index 7a6dec0df..7656ead99 100644 --- a/analysis/tests/src/expected/CompletionJsxProps.res.txt +++ b/analysis/tests/src/expected/CompletionJsxProps.res.txt @@ -50,3 +50,71 @@ Completable: CjsxPropValue [CompletionSupport, TestComponent] test=T "insertTextFormat": 2 }] +Complete src/CompletionJsxProps.res 9:52 +posCursor:[9:52] posNoWhite:[9:51] Found expr:[9:12->9:52] +JSX 9:43] polyArg[9:44->9:51]=...__ghost__[0:-1->0:-1]> _children:None +Completable: CjsxPropValue [CompletionSupport, TestComponent] polyArg= +[{ + "label": "#one", + "kind": 4, + "tags": [], + "detail": "#one\n\n[#one | #three(int, bool) | #two | #two2]", + "documentation": null, + "insertText": "#one", + "insertTextFormat": 2 + }, { + "label": "#three(_, _)", + "kind": 4, + "tags": [], + "detail": "#three(int, bool)\n\n[#one | #three(int, bool) | #two | #two2]", + "documentation": null, + "insertText": "#three(${1:_}, ${2:_})", + "insertTextFormat": 2 + }, { + "label": "#two", + "kind": 4, + "tags": [], + "detail": "#two\n\n[#one | #three(int, bool) | #two | #two2]", + "documentation": null, + "insertText": "#two", + "insertTextFormat": 2 + }, { + "label": "#two2", + "kind": 4, + "tags": [], + "detail": "#two2\n\n[#one | #three(int, bool) | #two | #two2]", + "documentation": null, + "insertText": "#two2", + "insertTextFormat": 2 + }] + +Complete src/CompletionJsxProps.res 12:54 +posCursor:[12:54] posNoWhite:[12:53] Found expr:[12:12->12:54] +JSX 12:43] polyArg[12:44->12:51]=...[12:52->12:54]> _children:None +Completable: CjsxPropValue [CompletionSupport, TestComponent] polyArg=#t +[{ + "label": "#three(_, _)", + "kind": 4, + "tags": [], + "detail": "#three(int, bool)\n\n[#one | #three(int, bool) | #two | #two2]", + "documentation": null, + "insertText": "three(${1:_}, ${2:_})", + "insertTextFormat": 2 + }, { + "label": "#two", + "kind": 4, + "tags": [], + "detail": "#two\n\n[#one | #three(int, bool) | #two | #two2]", + "documentation": null, + "insertText": "two", + "insertTextFormat": 2 + }, { + "label": "#two2", + "kind": 4, + "tags": [], + "detail": "#two2\n\n[#one | #three(int, bool) | #two | #two2]", + "documentation": null, + "insertText": "two2", + "insertTextFormat": 2 + }] + From 752aa7adf70eab9cce9acad788f1448e4f357c25 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Thu, 29 Dec 2022 22:36:01 +0100 Subject: [PATCH 2/4] remove redundant field from polyVariantConstructor type --- analysis/src/CompletionBackEnd.ml | 20 ++++++++++---------- analysis/src/SharedTypes.ml | 6 +----- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index 2253303b1..5f8974c23 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -711,13 +711,17 @@ let detail name (kind : Completion.kind) = | FileModule _ -> "file module" | Field ({typ}, s) -> name ^ ": " ^ (typ |> Shared.typeToString) ^ "\n\n" ^ s | Constructor (c, s) -> showConstructor c ^ "\n\n" ^ s - | PolyvariantConstructor ({name; payload}, s) -> + | PolyvariantConstructor ({name; args}, s) -> "#" ^ name - ^ (match payload with - | None -> "" - | Some ({desc = Types.Ttuple _} as typeExpr) -> - typeExpr |> Shared.typeToString - | Some typeExpr -> "(" ^ (typeExpr |> Shared.typeToString) ^ ")") + ^ (match args with + | [] -> "" + | [typeExpr] -> typeExpr |> Shared.typeToString + | typeExprs -> + "(" + ^ (typeExprs + |> List.map (fun typeExpr -> typeExpr |> Shared.typeToString) + |> String.concat ", ") + ^ ")") ^ "\n\n" ^ s let findAllCompletions ~(env : QueryEnv.t) ~prefix ~exact ~namesUsed @@ -1533,10 +1537,6 @@ let rec extractType ~env ~package (t : Types.type_expr) = |> List.map (fun (label, field) -> { name = label; - payload = - (match field with - | Types.Rpresent maybeTypeExpr -> maybeTypeExpr - | _ -> None); args = (* Multiple arguments are represented as a Ttuple, while a single argument is just the type expression itself. *) (match field with diff --git a/analysis/src/SharedTypes.ml b/analysis/src/SharedTypes.ml index 5d35e3518..ef2808427 100644 --- a/analysis/src/SharedTypes.ml +++ b/analysis/src/SharedTypes.ml @@ -279,11 +279,7 @@ end = struct {env with exported = structure.exported; pathRev; parent = Some env} end -type polyVariantConstructor = { - name: string; - payload: Types.type_expr option; - args: Types.type_expr list; -} +type polyVariantConstructor = {name: string; args: Types.type_expr list} module Completion = struct type kind = From 3e7534f30cbc527b6396b478b2cd15633ef55501 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Fri, 30 Dec 2022 18:18:24 +0100 Subject: [PATCH 3/4] fix mistake in printing polyvariant constructor payloads --- analysis/src/CompletionBackEnd.ml | 1 - 1 file changed, 1 deletion(-) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index 5f8974c23..3568d3581 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -715,7 +715,6 @@ let detail name (kind : Completion.kind) = "#" ^ name ^ (match args with | [] -> "" - | [typeExpr] -> typeExpr |> Shared.typeToString | typeExprs -> "(" ^ (typeExprs From 7fb96364e5c7bd026bda2f1da17f5f1be18a4dc2 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Fri, 30 Dec 2022 18:19:03 +0100 Subject: [PATCH 4/4] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2528a1e55..2840e47b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ - Add autocomplete for function argument values (booleans, variants and options. More values coming), both labelled and unlabelled. https://github.com/rescript-lang/rescript-vscode/pull/665 - Add autocomplete for JSX prop values. https://github.com/rescript-lang/rescript-vscode/pull/667 - Add snippet support in completion items. https://github.com/rescript-lang/rescript-vscode/pull/668 +- Add support from completing polyvariants as values. https://github.com/rescript-lang/rescript-vscode/pull/669 #### :nail_care: Polish