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

Complete polyvariants #669

Merged
merged 4 commits into from
Dec 30, 2022
Merged
Show file tree
Hide file tree
Changes from 2 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
49 changes: 49 additions & 0 deletions analysis/src/CompletionBackEnd.ml
Original file line number Diff line number Diff line change
Expand Up @@ -711,6 +711,18 @@ 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; args}, s) ->
"#" ^ name
^ (match args with
| [] -> ""
| [typeExpr] -> typeExpr |> Shared.typeToString
zth marked this conversation as resolved.
Show resolved Hide resolved
| typeExprs ->
"("
^ (typeExprs
|> List.map (fun typeExpr -> typeExpr |> Shared.typeToString)
|> String.concat ", ")
^ ")")
^ "\n\n" ^ s

let findAllCompletions ~(env : QueryEnv.t) ~prefix ~exact ~namesUsed
~(completionContext : Completable.completionContext) =
Expand Down Expand Up @@ -1519,6 +1531,23 @@ 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;
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 =
Expand Down Expand Up @@ -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"
Expand Down
3 changes: 2 additions & 1 deletion analysis/src/CompletionFrontEnd.ml
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down
10 changes: 9 additions & 1 deletion analysis/src/SharedTypes.ml
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,8 @@ end = struct
{env with exported = structure.exported; pathRev; parent = Some env}
end

type polyVariantConstructor = {name: string; args: Types.type_expr list}

module Completion = struct
type kind =
| Module of Module.t
Expand All @@ -287,6 +289,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

Expand Down Expand Up @@ -331,7 +334,7 @@ module Completion = struct
match kind with
| Module _ -> 9
| FileModule _ -> 9
| Constructor (_, _) -> 4
| Constructor (_, _) | PolyvariantConstructor (_, _) -> 4
| ObjLabel _ -> 4
| Label _ -> 4
| Field (_, _) -> 5
Expand Down Expand Up @@ -578,6 +581,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
Expand Down
6 changes: 6 additions & 0 deletions analysis/tests/src/CompletionJsxProps.res
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,9 @@
// let _ = <CompletionSupport.TestComponent test=T
// ^com

// let _ = <CompletionSupport.TestComponent polyArg=
// ^com

// let _ = <CompletionSupport.TestComponent polyArg=#t
// ^com

7 changes: 6 additions & 1 deletion analysis/tests/src/CompletionSupport.res
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,14 @@ type testVariant = One | Two | Three(int)

module TestComponent = {
@react.component
let make = (~on: bool, ~test: testVariant) => {
let make = (
~on: bool,
~test: testVariant,
~polyArg: option<[#one | #two | #two2 | #three(int, bool)]>=?,
) => {
ignore(on)
ignore(test)
ignore(polyArg)
React.null
}
}
68 changes: 68 additions & 0 deletions analysis/tests/src/expected/CompletionJsxProps.res.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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 <CompletionSupport.TestComponent:[9:12->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 <CompletionSupport.TestComponent:[12:12->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
}]