From 1d536a9cc7fa7955a28b4bd188832f58c24f84fb Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Sun, 17 Dec 2023 21:13:35 +0100 Subject: [PATCH 1/5] add reprod --- analysis/tests/src/Reprod.res | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 analysis/tests/src/Reprod.res diff --git a/analysis/tests/src/Reprod.res b/analysis/tests/src/Reprod.res new file mode 100644 index 000000000..3eeba71ab --- /dev/null +++ b/analysis/tests/src/Reprod.res @@ -0,0 +1,4 @@ +let res = 1; + +// switch res { | res => res } +// ^xfm \ No newline at end of file From 605123dc84b6d8281a01a2c811f7931a760a18cc Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Sun, 17 Dec 2023 21:17:49 +0100 Subject: [PATCH 2/5] change to hover --- analysis/tests/src/Reprod.res | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/analysis/tests/src/Reprod.res b/analysis/tests/src/Reprod.res index 3eeba71ab..6a0d512a8 100644 --- a/analysis/tests/src/Reprod.res +++ b/analysis/tests/src/Reprod.res @@ -1,4 +1,4 @@ let res = 1; // switch res { | res => res } -// ^xfm \ No newline at end of file +// ^hov \ No newline at end of file From a80fc8b4723831f5c5d3eca2677881bb9504ce4a Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Mon, 18 Dec 2023 14:36:34 +0100 Subject: [PATCH 3/5] track scope properly when inferring values --- analysis/tests/src/Reprod.res | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 analysis/tests/src/Reprod.res diff --git a/analysis/tests/src/Reprod.res b/analysis/tests/src/Reprod.res deleted file mode 100644 index 6a0d512a8..000000000 --- a/analysis/tests/src/Reprod.res +++ /dev/null @@ -1,4 +0,0 @@ -let res = 1; - -// switch res { | res => res } -// ^hov \ No newline at end of file From 7266381535f906a698bcc6069301ef97a0e83375 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Mon, 18 Dec 2023 15:14:56 +0100 Subject: [PATCH 4/5] print exotic identifiers properly when completing polyvariants --- analysis/src/CompletionBackEnd.ml | 10 +++++----- analysis/src/SharedTypes.ml | 6 +++++- analysis/src/TypeUtils.ml | 3 ++- analysis/src/Utils.ml | 17 +++++++++++++++++ analysis/tests/src/CompletionExpressions.res | 9 +++++++++ analysis/tests/src/ExhaustiveSwitch.res | 2 +- .../expected/CompletionExpressions.res.txt | 19 +++++++++++++++++++ .../src/expected/ExhaustiveSwitch.res.txt | 2 +- 8 files changed, 59 insertions(+), 9 deletions(-) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index 9fdf52fd2..a31fa00d1 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -231,8 +231,8 @@ let kindToDetail name (kind : Completion.kind) = ^ "\n\n" ^ s else name ^ ": " ^ (typ |> Shared.typeToString) ^ "\n\n" ^ s | Constructor (c, s) -> showConstructor c ^ "\n\n" ^ s - | PolyvariantConstructor ({name; args}, s) -> - "#" ^ name + | PolyvariantConstructor ({displayName; args}, s) -> + "#" ^ displayName ^ (match args with | [] -> "" | typeExprs -> @@ -1223,13 +1223,13 @@ let rec completeTypedValue ~full ~prefix ~completionContext ~mode |> List.map (fun (constructor : polyVariantConstructor) -> Completion.createWithSnippet ~name: - ("#" ^ constructor.name + ("#" ^ constructor.displayName ^ printConstructorArgs (List.length constructor.args) ~asSnippet:false) ~insertText: ((if Utils.startsWith prefix "#" then "" else "#") - ^ constructor.name + ^ constructor.displayName ^ printConstructorArgs (List.length constructor.args) ~asSnippet:true) @@ -1771,7 +1771,7 @@ let rec processCompletable ~debug ~full ~scope ~env ~pos ~forHover completable = ~cases: (v.constructors |> List.map (fun (constructor : polyVariantConstructor) -> - "#" ^ constructor.name + "#" ^ constructor.displayName ^ match constructor.args with | [] -> "" diff --git a/analysis/src/SharedTypes.ml b/analysis/src/SharedTypes.ml index efd1fbd82..58bf298b8 100644 --- a/analysis/src/SharedTypes.ml +++ b/analysis/src/SharedTypes.ml @@ -311,7 +311,11 @@ end = struct {env with exported = structure.exported; pathRev; parent = Some env} end -type polyVariantConstructor = {name: string; args: Types.type_expr list} +type polyVariantConstructor = { + name: string; + displayName: string; + args: Types.type_expr list; +} type innerType = TypeExpr of Types.type_expr | ExtractedType of completionType and completionType = diff --git a/analysis/src/TypeUtils.ml b/analysis/src/TypeUtils.ml index 63940302e..03f3c74e2 100644 --- a/analysis/src/TypeUtils.ml +++ b/analysis/src/TypeUtils.ml @@ -157,6 +157,7 @@ let rec extractType ~env ~package (t : Types.type_expr) = |> List.map (fun (label, field) -> { name = label; + displayName = Utils.printMaybeExoticIdent ~allowUident:true label; args = (* Multiple arguments are represented as a Ttuple, while a single argument is just the type expression itself. *) (match field with @@ -691,7 +692,7 @@ module Codegen = struct (match c.args with | [] -> None | _ -> Some (any ())) - c.name)) + c.displayName)) | Toption (_, innerType) -> let extractedType = match innerType with diff --git a/analysis/src/Utils.ml b/analysis/src/Utils.ml index 7eddfa902..773389c2b 100644 --- a/analysis/src/Utils.ml +++ b/analysis/src/Utils.ml @@ -243,3 +243,20 @@ let rec flattenAnyNamespaceInPath path = (* Namespaces are in reverse order, so "URL-RescriptBun" where RescriptBun is the namespace. *) (parts |> List.rev) @ flattenAnyNamespaceInPath tail else head :: flattenAnyNamespaceInPath tail + +let printMaybeExoticIdent ?(allowUident = false) txt = + let len = String.length txt in + + let rec loop i = + if i == len then txt + else if i == 0 then + match String.unsafe_get txt i with + | 'A' .. 'Z' when allowUident -> loop (i + 1) + | 'a' .. 'z' | '_' -> loop (i + 1) + | _ -> "\"" ^ txt ^ "\"" + else + match String.unsafe_get txt i with + | 'A' .. 'Z' | 'a' .. 'z' | '0' .. '9' | '\'' | '_' -> loop (i + 1) + | _ -> "\"" ^ txt ^ "\"" + in + loop 0 diff --git a/analysis/tests/src/CompletionExpressions.res b/analysis/tests/src/CompletionExpressions.res index 0fa6882cb..260e666c4 100644 --- a/analysis/tests/src/CompletionExpressions.res +++ b/analysis/tests/src/CompletionExpressions.res @@ -262,3 +262,12 @@ let arr = ["hello"] // arr->Belt.Array.map() // ^com + +type exoticPolyvariant = [#"some exotic"] + +let takesExotic = (e: exoticPolyvariant) => { + ignore(e) +} + +// takesExotic() +// ^com diff --git a/analysis/tests/src/ExhaustiveSwitch.res b/analysis/tests/src/ExhaustiveSwitch.res index 4167f1201..5816aa635 100644 --- a/analysis/tests/src/ExhaustiveSwitch.res +++ b/analysis/tests/src/ExhaustiveSwitch.res @@ -1,5 +1,5 @@ type someVariant = One | Two | Three(option) -type somePolyVariant = [#one | #two | #three(option)] +type somePolyVariant = [#one | #two | #three(option) | #"exotic ident"] let withSomeVariant = One let withSomePoly: somePolyVariant = #one diff --git a/analysis/tests/src/expected/CompletionExpressions.res.txt b/analysis/tests/src/expected/CompletionExpressions.res.txt index 3c8f785fe..2536b4554 100644 --- a/analysis/tests/src/expected/CompletionExpressions.res.txt +++ b/analysis/tests/src/expected/CompletionExpressions.res.txt @@ -1113,3 +1113,22 @@ Path Belt.Array.map "insertTextFormat": 2 }] +Complete src/CompletionExpressions.res 271:15 +posCursor:[271:15] posNoWhite:[271:14] Found expr:[271:3->271:16] +Pexp_apply ...[271:3->271:14] (...[271:15->271:16]) +Completable: Cexpression CArgument Value[takesExotic]($0) +Package opens Pervasives.JsxModules.place holder +Resolved opens 1 pervasives +ContextPath CArgument Value[takesExotic]($0) +ContextPath Value[takesExotic] +Path takesExotic +[{ + "label": "#\"some exotic\"", + "kind": 4, + "tags": [], + "detail": "#\"some exotic\"\n\n[#\"some exotic\"]", + "documentation": null, + "insertText": "#\"some exotic\"", + "insertTextFormat": 2 + }] + diff --git a/analysis/tests/src/expected/ExhaustiveSwitch.res.txt b/analysis/tests/src/expected/ExhaustiveSwitch.res.txt index eaf737534..37a1c6973 100644 --- a/analysis/tests/src/expected/ExhaustiveSwitch.res.txt +++ b/analysis/tests/src/expected/ExhaustiveSwitch.res.txt @@ -42,7 +42,7 @@ Path withSomePol "detail": "insert exhaustive switch for value", "documentation": null, "filterText": "withSomePoly", - "insertText": "withSomePoly {\n | #one => ${1:failwith(\"todo\")}\n | #three(_) => ${2:failwith(\"todo\")}\n | #two => ${3:failwith(\"todo\")}\n }", + "insertText": "withSomePoly {\n | #one => ${1:failwith(\"todo\")}\n | #three(_) => ${2:failwith(\"todo\")}\n | #two => ${3:failwith(\"todo\")}\n | #\"exotic ident\" => ${4:failwith(\"todo\")}\n }", "insertTextFormat": 2 }] From b12a445cea24cc454c15afa23ae9ee4afac0a58e Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Mon, 18 Dec 2023 15:18:31 +0100 Subject: [PATCH 5/5] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e7ab801d8..ef1470c5d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ - Fix infinite loop when resolving inferred completions when several values in scope has the same name. https://github.com/rescript-lang/rescript-vscode/pull/869 - Fix crash when trying to print recursive polymorphic variants without a concrete definition. https://github.com/rescript-lang/rescript-vscode/pull/851 - Fix `rescript-language-server --version` command. https://github.com/rescript-lang/rescript-vscode/pull/873 +- Print exotic polyvariant constructor names with quotes when doing completion. https://github.com/rescript-lang/rescript-vscode/pull/870 #### :nail_care: Polish