From 45cd8711fe6efd7d6d3ff33cfd636c64ee3d4665 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Wed, 16 Aug 2023 18:11:52 +0200 Subject: [PATCH 1/5] add TypeAtPos completion type and let it drive completion when something might've compiled already and has a type, but no explicit type annotation --- analysis/src/CompletionBackEnd.ml | 8 ++++ analysis/src/CompletionFrontEnd.ml | 21 +++++++++ analysis/src/SharedTypes.ml | 3 ++ analysis/tests/src/RecordCompletion.res | 21 +++++++++ analysis/tests/src/expected/Fragment.res.txt | 4 ++ .../src/expected/RecordCompletion.res.txt | 47 ++++++++++++++++++- 6 files changed, 102 insertions(+), 2 deletions(-) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index a510fb15a..3ca0b904c 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -1113,6 +1113,14 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact [Completion.create "dummy" ~env ~kind:(kindFromInnerType typ)] | None -> []) | None -> []) + | CTypeAtPos loc -> ( + match + References.getLocItem ~full ~pos:(Pos.ofLexing loc.loc_start) ~debug + with + | None -> [] + | Some {locType = Typed (_, typExpr, _)} -> + [Completion.create "dummy" ~env ~kind:(Value typExpr)] + | _ -> []) let getOpens ~debug ~rawOpens ~package ~env = if debug && rawOpens <> [] then diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index 470becc5e..797f28248 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -591,6 +591,27 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = (Completable.Cexpression {contextPath = ctxPath; prefix; nested = List.rev nested}) | _ -> ()) + | {pvb_pat = {ppat_desc = Ppat_var {loc}}; pvb_expr} + when locHasCursor pvb_expr.pexp_loc -> ( + (* Expression without a type annotation. We can complete this if this + has compiled previously and there's a type available for the identifier itself. + This is nice because the type is assigned even if the assignment isn't complete. + + E.g: let x = {name: "name", }, when `x` has compiled. *) + match + pvb_expr + |> CompletionExpressions.traverseExpr ~exprPath:[] ~pos:posBeforeCursor + ~firstCharBeforeCursorNoWhite + with + | Some (prefix, nested) -> + (* This completion should be low prio, so let any deeper completion + hit first, and only set this TypeAtPos completion if nothing else + here hit. *) + Ast_iterator.default_iterator.value_binding iterator value_binding; + setResult + (Completable.Cexpression + {contextPath = CTypeAtPos loc; prefix; nested = List.rev nested}) + | _ -> ()) | { pvb_pat = {ppat_desc = Ppat_constraint (_pat, coreType); ppat_loc}; pvb_expr; diff --git a/analysis/src/SharedTypes.ml b/analysis/src/SharedTypes.ml index e12223cdb..5af4b2b74 100644 --- a/analysis/src/SharedTypes.ml +++ b/analysis/src/SharedTypes.ml @@ -592,6 +592,8 @@ module Completable = struct } | CJsxPropValue of {pathToComponent: string list; propName: string} | CPatternPath of {rootCtxPath: contextPath; nested: nestedPath list} + | CTypeAtPos of Location.t + (** A position holding something that might have a *compiled* type. *) type patternMode = Default | Destructuring @@ -671,6 +673,7 @@ module Completable = struct ^ (nested |> List.map (fun nestedPath -> nestedPathToString nestedPath) |> String.concat "->") + | CTypeAtPos _loc -> "CTypeAtPos()" let toString = function | Cpath cp -> "Cpath " ^ contextPathToString cp diff --git a/analysis/tests/src/RecordCompletion.res b/analysis/tests/src/RecordCompletion.res index 0ec0c6982..742fcf487 100644 --- a/analysis/tests/src/RecordCompletion.res +++ b/analysis/tests/src/RecordCompletion.res @@ -22,3 +22,24 @@ let n = {R.name: ""} // n.R. xx // ^com + +type optRecord = { + name: string, + age?: int, + online?: bool, +} + +let optRecord = { + name: "Hello", + // ^com +} + +type someVariant = One(int, optRecord) + +let x = One( + 1, + { + name: "What", + // ^com + }, +) diff --git a/analysis/tests/src/expected/Fragment.res.txt b/analysis/tests/src/expected/Fragment.res.txt index d80d1c56a..adb67f8d8 100644 --- a/analysis/tests/src/expected/Fragment.res.txt +++ b/analysis/tests/src/expected/Fragment.res.txt @@ -12,5 +12,9 @@ posCursor:[9:56] posNoWhite:[9:55] Found expr:[9:13->9:66] JSX 9:26] > _children:9:26 posCursor:[9:56] posNoWhite:[9:55] Found expr:__ghost__[9:10->9:67] Pexp_construct []:__ghost__[9:10->9:67] None +Completable: Cexpression CTypeAtPos()=[]->variantPayload::::($1) +Package opens Pervasives.JsxModules.place holder +Resolved opens 1 pervasives +ContextPath CTypeAtPos() null diff --git a/analysis/tests/src/expected/RecordCompletion.res.txt b/analysis/tests/src/expected/RecordCompletion.res.txt index f8ae52243..6badf1eee 100644 --- a/analysis/tests/src/expected/RecordCompletion.res.txt +++ b/analysis/tests/src/expected/RecordCompletion.res.txt @@ -50,8 +50,8 @@ Path Js.Array2.m }] Complete src/RecordCompletion.res 19:7 -posCursor:[19:7] posNoWhite:[19:6] Found expr:[19:3->19:7] -Pexp_field [19:3->19:4] R.:[19:5->19:7] +posCursor:[19:7] posNoWhite:[19:6] Found expr:[19:3->25:4] +Pexp_field [19:3->19:4] R.:[19:5->25:4] Completable: Cpath Module[R]."" Package opens Pervasives.JsxModules.place holder Resolved opens 1 pervasives @@ -81,3 +81,46 @@ Path R. "documentation": null }] +Complete src/RecordCompletion.res 32:17 +posCursor:[32:17] posNoWhite:[32:15] Found expr:[31:16->34:1] +Completable: Cexpression CTypeAtPos()->recordBody +Package opens Pervasives.JsxModules.place holder +Resolved opens 1 pervasives +ContextPath CTypeAtPos() +[{ + "label": "age", + "kind": 5, + "tags": [], + "detail": "age?: int\n\noptRecord", + "documentation": null + }, { + "label": "online", + "kind": 5, + "tags": [], + "detail": "online?: bool\n\noptRecord", + "documentation": null + }] + +Complete src/RecordCompletion.res 41:18 +posCursor:[41:18] posNoWhite:[41:16] Found expr:[38:8->44:1] +Pexp_construct One:[38:8->38:11] [38:11->44:1] +posCursor:[41:18] posNoWhite:[41:16] Found expr:[38:11->44:1] +posCursor:[41:18] posNoWhite:[41:16] Found expr:[40:2->43:3] +Completable: Cexpression CTypeAtPos()->variantPayload::One($1), recordBody +Package opens Pervasives.JsxModules.place holder +Resolved opens 1 pervasives +ContextPath CTypeAtPos() +[{ + "label": "age", + "kind": 5, + "tags": [], + "detail": "age?: int\n\noptRecord", + "documentation": null + }, { + "label": "online", + "kind": 5, + "tags": [], + "detail": "online?: bool\n\noptRecord", + "documentation": null + }] + From ee049ec22bc5453f4c410aaf1834ceb5154977b9 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Wed, 16 Aug 2023 18:12:45 +0200 Subject: [PATCH 2/5] move TypeAtPos tests to own file --- analysis/tests/src/RecordCompletion.res | 21 --------- analysis/tests/src/TypeAtPosCompletion.res | 20 ++++++++ .../tests/src/expected/Completion.res.txt | 6 +++ .../src/expected/CompletionJsxProps.res.txt | 6 +++ .../src/expected/RecordCompletion.res.txt | 47 +------------------ .../src/expected/TypeAtPosCompletion.res.txt | 43 +++++++++++++++++ 6 files changed, 77 insertions(+), 66 deletions(-) create mode 100644 analysis/tests/src/TypeAtPosCompletion.res create mode 100644 analysis/tests/src/expected/TypeAtPosCompletion.res.txt diff --git a/analysis/tests/src/RecordCompletion.res b/analysis/tests/src/RecordCompletion.res index 742fcf487..0ec0c6982 100644 --- a/analysis/tests/src/RecordCompletion.res +++ b/analysis/tests/src/RecordCompletion.res @@ -22,24 +22,3 @@ let n = {R.name: ""} // n.R. xx // ^com - -type optRecord = { - name: string, - age?: int, - online?: bool, -} - -let optRecord = { - name: "Hello", - // ^com -} - -type someVariant = One(int, optRecord) - -let x = One( - 1, - { - name: "What", - // ^com - }, -) diff --git a/analysis/tests/src/TypeAtPosCompletion.res b/analysis/tests/src/TypeAtPosCompletion.res new file mode 100644 index 000000000..9df4185ac --- /dev/null +++ b/analysis/tests/src/TypeAtPosCompletion.res @@ -0,0 +1,20 @@ +type optRecord = { + name: string, + age?: int, + online?: bool, +} + +let optRecord = { + name: "Hello", + // ^com +} + +type someVariant = One(int, optRecord) + +let x = One( + 1, + { + name: "What", + // ^com + }, +) diff --git a/analysis/tests/src/expected/Completion.res.txt b/analysis/tests/src/expected/Completion.res.txt index 560385753..aef3b28be 100644 --- a/analysis/tests/src/expected/Completion.res.txt +++ b/analysis/tests/src/expected/Completion.res.txt @@ -1764,6 +1764,12 @@ Path T "tags": [], "detail": "file module", "documentation": null + }, { + "label": "TypeAtPosCompletion", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null }, { "label": "TypeDefinition", "kind": 9, diff --git a/analysis/tests/src/expected/CompletionJsxProps.res.txt b/analysis/tests/src/expected/CompletionJsxProps.res.txt index 475fbb2cf..43a91f799 100644 --- a/analysis/tests/src/expected/CompletionJsxProps.res.txt +++ b/analysis/tests/src/expected/CompletionJsxProps.res.txt @@ -68,6 +68,12 @@ Path CompletionSupport.TestComponent.make "tags": [], "detail": "file module", "documentation": null + }, { + "label": "TypeAtPosCompletion", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null }, { "label": "TypeDefinition", "kind": 9, diff --git a/analysis/tests/src/expected/RecordCompletion.res.txt b/analysis/tests/src/expected/RecordCompletion.res.txt index 6badf1eee..f8ae52243 100644 --- a/analysis/tests/src/expected/RecordCompletion.res.txt +++ b/analysis/tests/src/expected/RecordCompletion.res.txt @@ -50,8 +50,8 @@ Path Js.Array2.m }] Complete src/RecordCompletion.res 19:7 -posCursor:[19:7] posNoWhite:[19:6] Found expr:[19:3->25:4] -Pexp_field [19:3->19:4] R.:[19:5->25:4] +posCursor:[19:7] posNoWhite:[19:6] Found expr:[19:3->19:7] +Pexp_field [19:3->19:4] R.:[19:5->19:7] Completable: Cpath Module[R]."" Package opens Pervasives.JsxModules.place holder Resolved opens 1 pervasives @@ -81,46 +81,3 @@ Path R. "documentation": null }] -Complete src/RecordCompletion.res 32:17 -posCursor:[32:17] posNoWhite:[32:15] Found expr:[31:16->34:1] -Completable: Cexpression CTypeAtPos()->recordBody -Package opens Pervasives.JsxModules.place holder -Resolved opens 1 pervasives -ContextPath CTypeAtPos() -[{ - "label": "age", - "kind": 5, - "tags": [], - "detail": "age?: int\n\noptRecord", - "documentation": null - }, { - "label": "online", - "kind": 5, - "tags": [], - "detail": "online?: bool\n\noptRecord", - "documentation": null - }] - -Complete src/RecordCompletion.res 41:18 -posCursor:[41:18] posNoWhite:[41:16] Found expr:[38:8->44:1] -Pexp_construct One:[38:8->38:11] [38:11->44:1] -posCursor:[41:18] posNoWhite:[41:16] Found expr:[38:11->44:1] -posCursor:[41:18] posNoWhite:[41:16] Found expr:[40:2->43:3] -Completable: Cexpression CTypeAtPos()->variantPayload::One($1), recordBody -Package opens Pervasives.JsxModules.place holder -Resolved opens 1 pervasives -ContextPath CTypeAtPos() -[{ - "label": "age", - "kind": 5, - "tags": [], - "detail": "age?: int\n\noptRecord", - "documentation": null - }, { - "label": "online", - "kind": 5, - "tags": [], - "detail": "online?: bool\n\noptRecord", - "documentation": null - }] - diff --git a/analysis/tests/src/expected/TypeAtPosCompletion.res.txt b/analysis/tests/src/expected/TypeAtPosCompletion.res.txt new file mode 100644 index 000000000..69d519b86 --- /dev/null +++ b/analysis/tests/src/expected/TypeAtPosCompletion.res.txt @@ -0,0 +1,43 @@ +Complete src/TypeAtPosCompletion.res 7:17 +posCursor:[7:17] posNoWhite:[7:15] Found expr:[6:16->9:1] +Completable: Cexpression CTypeAtPos()->recordBody +Package opens Pervasives.JsxModules.place holder +Resolved opens 1 pervasives +ContextPath CTypeAtPos() +[{ + "label": "age", + "kind": 5, + "tags": [], + "detail": "age?: int\n\noptRecord", + "documentation": null + }, { + "label": "online", + "kind": 5, + "tags": [], + "detail": "online?: bool\n\noptRecord", + "documentation": null + }] + +Complete src/TypeAtPosCompletion.res 16:18 +posCursor:[16:18] posNoWhite:[16:16] Found expr:[13:8->19:1] +Pexp_construct One:[13:8->13:11] [13:11->19:1] +posCursor:[16:18] posNoWhite:[16:16] Found expr:[13:11->19:1] +posCursor:[16:18] posNoWhite:[16:16] Found expr:[15:2->18:3] +Completable: Cexpression CTypeAtPos()->variantPayload::One($1), recordBody +Package opens Pervasives.JsxModules.place holder +Resolved opens 1 pervasives +ContextPath CTypeAtPos() +[{ + "label": "age", + "kind": 5, + "tags": [], + "detail": "age?: int\n\noptRecord", + "documentation": null + }, { + "label": "online", + "kind": 5, + "tags": [], + "detail": "online?: bool\n\noptRecord", + "documentation": null + }] + From 2334855ff06c2e5626031b714b67e5e5562fab68 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Wed, 16 Aug 2023 18:22:48 +0200 Subject: [PATCH 3/5] add array test --- analysis/tests/src/TypeAtPosCompletion.res | 5 ++ .../src/expected/TypeAtPosCompletion.res.txt | 78 +++++++++++++++++++ 2 files changed, 83 insertions(+) diff --git a/analysis/tests/src/TypeAtPosCompletion.res b/analysis/tests/src/TypeAtPosCompletion.res index 9df4185ac..41d558bed 100644 --- a/analysis/tests/src/TypeAtPosCompletion.res +++ b/analysis/tests/src/TypeAtPosCompletion.res @@ -18,3 +18,8 @@ let x = One( // ^com }, ) + +let arr = [ + optRecord, + // ^com +] diff --git a/analysis/tests/src/expected/TypeAtPosCompletion.res.txt b/analysis/tests/src/expected/TypeAtPosCompletion.res.txt index 69d519b86..7c8f6c7c1 100644 --- a/analysis/tests/src/expected/TypeAtPosCompletion.res.txt +++ b/analysis/tests/src/expected/TypeAtPosCompletion.res.txt @@ -41,3 +41,81 @@ ContextPath CTypeAtPos() "documentation": null }] +Complete src/TypeAtPosCompletion.res 22:12 +posCursor:[22:12] posNoWhite:[22:11] Found expr:[21:10->24:1] +Completable: Cexpression CTypeAtPos()->array +Package opens Pervasives.JsxModules.place holder +Resolved opens 1 pervasives +ContextPath CTypeAtPos() +[{ + "label": "{}", + "kind": 12, + "tags": [], + "detail": "optRecord", + "documentation": null, + "sortText": "A", + "insertText": "{$0}", + "insertTextFormat": 2 + }] + +Complete src/TypeAtPosCompletion.res 38:5 +posCursor:[38:5] posNoWhite:[38:4] Found expr:[37:12->0:-1] +Completable: Cpath Value[Belt, Option, getExn](Nolabel)-> +Package opens Pervasives.JsxModules.place holder +Resolved opens 1 pervasives +ContextPath Value[Belt, Option, getExn](Nolabel)-> +ContextPath Value[Belt, Option, getExn](Nolabel) +ContextPath Value[Belt, Option, getExn] +Path Belt.Option.getExn +CPPipe env:TypeAtPosCompletion envFromCompletionItem:Belt_Option +Path Belt.Int. +[{ + "label": "Belt.Int.fromString", + "kind": 12, + "tags": [], + "detail": "string => option", + "documentation": {"kind": "markdown", "value": "\n Converts a given `string` to an `int`. Returns `Some(int)` when the input is a number, `None` otherwise.\n\n ```res example\n Js.log(Belt.Int.fromString(\"1\") === Some(1)) /* true */\n ```\n"} + }, { + "label": "Belt.Int.*", + "kind": 12, + "tags": [], + "detail": "(int, int) => int", + "documentation": {"kind": "markdown", "value": "\n Multiplication of two `int` values. Same as the multiplication from `Pervasives`.\n\n ```res example\n open Belt.Int\n Js.log(2 * 2 === 4) /* true */\n ```\n"} + }, { + "label": "Belt.Int./", + "kind": 12, + "tags": [], + "detail": "(int, int) => int", + "documentation": {"kind": "markdown", "value": "\n Division of two `int` values. Same as the division from `Pervasives`.\n\n ```res example\n open Belt.Int\n Js.log(4 / 2 === 2); /* true */\n ```\n"} + }, { + "label": "Belt.Int.toString", + "kind": 12, + "tags": [], + "detail": "int => string", + "documentation": {"kind": "markdown", "value": "\n Converts a given `int` to a `string`. Uses the JavaScript `String` constructor under the hood.\n\n ```res example\n Js.log(Belt.Int.toString(1) === \"1\") /* true */\n ```\n"} + }, { + "label": "Belt.Int.toFloat", + "kind": 12, + "tags": [], + "detail": "int => float", + "documentation": {"kind": "markdown", "value": "\n Converts a given `int` to a `float`.\n\n ```res example\n Js.log(Belt.Int.toFloat(1) === 1.0) /* true */\n ```\n"} + }, { + "label": "Belt.Int.fromFloat", + "kind": 12, + "tags": [], + "detail": "float => int", + "documentation": {"kind": "markdown", "value": "\n Converts a given `float` to an `int`.\n\n ```res example\n Js.log(Belt.Int.fromFloat(1.0) === 1) /* true */\n ```\n"} + }, { + "label": "Belt.Int.-", + "kind": 12, + "tags": [], + "detail": "(int, int) => int", + "documentation": {"kind": "markdown", "value": "\n Subtraction of two `int` values. Same as the subtraction from `Pervasives`.\n\n ```res example\n open Belt.Int\n Js.log(2 - 1 === 1) /* true */\n ```\n"} + }, { + "label": "Belt.Int.+", + "kind": 12, + "tags": [], + "detail": "(int, int) => int", + "documentation": {"kind": "markdown", "value": "\n Addition of two `int` values. Same as the addition from `Pervasives`.\n\n ```res example\n open Belt.Int\n Js.log(2 + 2 === 4) /* true */\n ```\n"} + }] + From ddb07bc8d44f5d2a21f089f2c7167cf96ae085de Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Wed, 16 Aug 2023 18:31:34 +0200 Subject: [PATCH 4/5] update test output --- .../src/expected/TypeAtPosCompletion.res.txt | 61 ------------------- 1 file changed, 61 deletions(-) diff --git a/analysis/tests/src/expected/TypeAtPosCompletion.res.txt b/analysis/tests/src/expected/TypeAtPosCompletion.res.txt index 7c8f6c7c1..8a334e9c6 100644 --- a/analysis/tests/src/expected/TypeAtPosCompletion.res.txt +++ b/analysis/tests/src/expected/TypeAtPosCompletion.res.txt @@ -58,64 +58,3 @@ ContextPath CTypeAtPos() "insertTextFormat": 2 }] -Complete src/TypeAtPosCompletion.res 38:5 -posCursor:[38:5] posNoWhite:[38:4] Found expr:[37:12->0:-1] -Completable: Cpath Value[Belt, Option, getExn](Nolabel)-> -Package opens Pervasives.JsxModules.place holder -Resolved opens 1 pervasives -ContextPath Value[Belt, Option, getExn](Nolabel)-> -ContextPath Value[Belt, Option, getExn](Nolabel) -ContextPath Value[Belt, Option, getExn] -Path Belt.Option.getExn -CPPipe env:TypeAtPosCompletion envFromCompletionItem:Belt_Option -Path Belt.Int. -[{ - "label": "Belt.Int.fromString", - "kind": 12, - "tags": [], - "detail": "string => option", - "documentation": {"kind": "markdown", "value": "\n Converts a given `string` to an `int`. Returns `Some(int)` when the input is a number, `None` otherwise.\n\n ```res example\n Js.log(Belt.Int.fromString(\"1\") === Some(1)) /* true */\n ```\n"} - }, { - "label": "Belt.Int.*", - "kind": 12, - "tags": [], - "detail": "(int, int) => int", - "documentation": {"kind": "markdown", "value": "\n Multiplication of two `int` values. Same as the multiplication from `Pervasives`.\n\n ```res example\n open Belt.Int\n Js.log(2 * 2 === 4) /* true */\n ```\n"} - }, { - "label": "Belt.Int./", - "kind": 12, - "tags": [], - "detail": "(int, int) => int", - "documentation": {"kind": "markdown", "value": "\n Division of two `int` values. Same as the division from `Pervasives`.\n\n ```res example\n open Belt.Int\n Js.log(4 / 2 === 2); /* true */\n ```\n"} - }, { - "label": "Belt.Int.toString", - "kind": 12, - "tags": [], - "detail": "int => string", - "documentation": {"kind": "markdown", "value": "\n Converts a given `int` to a `string`. Uses the JavaScript `String` constructor under the hood.\n\n ```res example\n Js.log(Belt.Int.toString(1) === \"1\") /* true */\n ```\n"} - }, { - "label": "Belt.Int.toFloat", - "kind": 12, - "tags": [], - "detail": "int => float", - "documentation": {"kind": "markdown", "value": "\n Converts a given `int` to a `float`.\n\n ```res example\n Js.log(Belt.Int.toFloat(1) === 1.0) /* true */\n ```\n"} - }, { - "label": "Belt.Int.fromFloat", - "kind": 12, - "tags": [], - "detail": "float => int", - "documentation": {"kind": "markdown", "value": "\n Converts a given `float` to an `int`.\n\n ```res example\n Js.log(Belt.Int.fromFloat(1.0) === 1) /* true */\n ```\n"} - }, { - "label": "Belt.Int.-", - "kind": 12, - "tags": [], - "detail": "(int, int) => int", - "documentation": {"kind": "markdown", "value": "\n Subtraction of two `int` values. Same as the subtraction from `Pervasives`.\n\n ```res example\n open Belt.Int\n Js.log(2 - 1 === 1) /* true */\n ```\n"} - }, { - "label": "Belt.Int.+", - "kind": 12, - "tags": [], - "detail": "(int, int) => int", - "documentation": {"kind": "markdown", "value": "\n Addition of two `int` values. Same as the addition from `Pervasives`.\n\n ```res example\n open Belt.Int\n Js.log(2 + 2 === 4) /* true */\n ```\n"} - }] - From 433ea56cb1b7c8a86d0c6d277e03102a4aef1a6c Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Wed, 16 Aug 2023 18:32:23 +0200 Subject: [PATCH 5/5] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b5aa429d..9e2a0b4bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ - Add support for syntax highlighting in `%raw` and `%ffi` extension points. https://github.com/rescript-lang/rescript-vscode/pull/774 - Add completion to top level decorators. https://github.com/rescript-lang/rescript-vscode/pull/799 - Add code action for wrapping patterns where option is expected with `Some`. https://github.com/rescript-lang/rescript-vscode/pull/806 +- Better completion from identifiers with inferred types. https://github.com/rescript-lang/rescript-vscode/pull/808 #### :nail_care: Polish