From bd87ecd256dd5bb64626e9a69f34fb861a78815c Mon Sep 17 00:00:00 2001 From: nojaf Date: Thu, 19 Dec 2024 14:30:43 +0100 Subject: [PATCH 1/7] Add Rxjs completion test --- analysis/tests/src/Rxjs.res | 49 +++++++++++++++++++ analysis/tests/src/RxjsCompletion.res | 29 +++++++++++ analysis/tests/src/expected/Rxjs.res.txt | 0 .../tests/src/expected/RxjsCompletion.res.txt | 20 ++++++++ 4 files changed, 98 insertions(+) create mode 100644 analysis/tests/src/Rxjs.res create mode 100644 analysis/tests/src/RxjsCompletion.res create mode 100644 analysis/tests/src/expected/Rxjs.res.txt create mode 100644 analysis/tests/src/expected/RxjsCompletion.res.txt diff --git a/analysis/tests/src/Rxjs.res b/analysis/tests/src/Rxjs.res new file mode 100644 index 000000000..8353d4e5d --- /dev/null +++ b/analysis/tests/src/Rxjs.res @@ -0,0 +1,49 @@ +// These are bindings used in RxjsCompletion.res +// We are using a separate file to test complication for modules of external files. +type target + +module Subscriber = { + type t<'t> = {next: 't => unit} +} + +module Observable = { + type t<'t> + + type dispose = unit => unit + + @new @module("rxjs") + external make: (Subscriber.t<'t> => dispose) => t<'t> = "Observable" + + type subscription + + @send + external subscribe: (t<'t>, 't => unit) => subscription = "subscribe" +} + +@module("rxjs") +external fromEvent: (target, string) => Observable.t<'t> = "fromEvent" + +type operation<'t, 'u> + +@send +external pipe: (Observable.t<'t>, operation<'t, 'u>) => Observable.t<'u> = "pipe" + +@send +external pipe2: (Observable.t<'t>, operation<'t, 'u>, operation<'u, 'i>) => Observable.t<'i> = + "pipe" + +@module("rxjs") +external map: ('t => 'u) => operation<'t, 'u> = "map" + +@module("rxjs") +external distinctUntilChanged: unit => operation<'t, 't> = "distinctUntilChanged" + +@module("rxjs") +external merge: (Observable.t<'t>, Observable.t<'t>) => Observable.t<'t> = "merge" + +@module("rxjs") +external scan: (('acc, 't) => 'acc, 'acc) => operation<'t, 'acc> = "scan" + +@module("rxjs") +external combineLatest: (Observable.t<'a>, Observable.t<'b>) => Observable.t<('a, 'b)> = + "combineLatest" diff --git a/analysis/tests/src/RxjsCompletion.res b/analysis/tests/src/RxjsCompletion.res new file mode 100644 index 000000000..13c84638a --- /dev/null +++ b/analysis/tests/src/RxjsCompletion.res @@ -0,0 +1,29 @@ +type keyPress = + | Up(string) + | Down(string) + +@val +external window: {..} = "window" + +let main = async () => { + let keyMapObservable = { + open Rxjs + + let keydown = + fromEvent(Obj.magic(window), "keydown")->pipe2( + map(event => Down(event["key"])), + distinctUntilChanged(), + ) + + let keyup = + fromEvent(Obj.magic(window), "keyup")->pipe2( + map(event => Up(event["key"])), + distinctUntilChanged(), + ) + + // merge(keydown, keyup). + // ^com + } + + ignore(keyMapObservable) +} diff --git a/analysis/tests/src/expected/Rxjs.res.txt b/analysis/tests/src/expected/Rxjs.res.txt new file mode 100644 index 000000000..e69de29bb diff --git a/analysis/tests/src/expected/RxjsCompletion.res.txt b/analysis/tests/src/expected/RxjsCompletion.res.txt new file mode 100644 index 000000000..ded4f2835 --- /dev/null +++ b/analysis/tests/src/expected/RxjsCompletion.res.txt @@ -0,0 +1,20 @@ +Complete src/RxjsCompletion.res 23:29 +posCursor:[23:29] posNoWhite:[23:28] Found expr:[7:17->28:1] +posCursor:[23:29] posNoWhite:[23:28] Found expr:[8:2->27:26] +posCursor:[23:29] posNoWhite:[23:28] Found expr:[9:4->23:29] +posCursor:[23:29] posNoWhite:[23:28] Found expr:[11:4->23:29] +posCursor:[23:29] posNoWhite:[23:28] Found expr:[17:4->23:29] +posCursor:[23:29] posNoWhite:[23:28] Found expr:[23:7->23:29] +Pexp_field [23:7->23:28] _:[25:2->23:29] +Completable: Cpath Value[merge](Nolabel, Nolabel)."" +Raw opens: 1 Rxjs.place holder +Package opens Pervasives.JsxModules.place holder +Resolved opens 2 pervasives Rxjs.res +ContextPath Value[merge](Nolabel, Nolabel)."" +ContextPath Value[merge](Nolabel, Nolabel) +ContextPath Value[merge] +Path merge +CPPipe pathFromEnv:Observable found:true +Path Rxjs.Observable. +[] + From ef4e6a06208d04659f329b05b343cbbbd417fd5b Mon Sep 17 00:00:00 2001 From: nojaf Date: Thu, 19 Dec 2024 14:53:43 +0100 Subject: [PATCH 2/7] Add Rxjs binding example --- analysis/tests/src/RxjsCompletion.res | 2 ++ .../tests/src/expected/RxjsCompletion.res.txt | 19 +++++++++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/analysis/tests/src/RxjsCompletion.res b/analysis/tests/src/RxjsCompletion.res index 13c84638a..2db3d62f4 100644 --- a/analysis/tests/src/RxjsCompletion.res +++ b/analysis/tests/src/RxjsCompletion.res @@ -23,6 +23,8 @@ let main = async () => { // merge(keydown, keyup). // ^com + + // Rxjs.Observable.subscribe, Rxjs.pipe and Rxjs.pipe2 should be completed } ignore(keyMapObservable) diff --git a/analysis/tests/src/expected/RxjsCompletion.res.txt b/analysis/tests/src/expected/RxjsCompletion.res.txt index ded4f2835..8ae7ac3c0 100644 --- a/analysis/tests/src/expected/RxjsCompletion.res.txt +++ b/analysis/tests/src/expected/RxjsCompletion.res.txt @@ -1,11 +1,11 @@ Complete src/RxjsCompletion.res 23:29 -posCursor:[23:29] posNoWhite:[23:28] Found expr:[7:17->28:1] -posCursor:[23:29] posNoWhite:[23:28] Found expr:[8:2->27:26] +posCursor:[23:29] posNoWhite:[23:28] Found expr:[7:17->30:1] +posCursor:[23:29] posNoWhite:[23:28] Found expr:[8:2->29:26] posCursor:[23:29] posNoWhite:[23:28] Found expr:[9:4->23:29] posCursor:[23:29] posNoWhite:[23:28] Found expr:[11:4->23:29] posCursor:[23:29] posNoWhite:[23:28] Found expr:[17:4->23:29] posCursor:[23:29] posNoWhite:[23:28] Found expr:[23:7->23:29] -Pexp_field [23:7->23:28] _:[25:2->23:29] +Pexp_field [23:7->23:28] _:[27:2->23:29] Completable: Cpath Value[merge](Nolabel, Nolabel)."" Raw opens: 1 Rxjs.place holder Package opens Pervasives.JsxModules.place holder @@ -16,5 +16,16 @@ ContextPath Value[merge] Path merge CPPipe pathFromEnv:Observable found:true Path Rxjs.Observable. -[] +[{ + "label": "->Observable.subscribe", + "kind": 12, + "tags": [], + "detail": "(t<'t>, 't => unit) => subscription", + "documentation": null, + "sortText": "subscribe", + "textEdit": { + "range": {"start": {"line": 23, "character": 28}, "end": {"line": 23, "character": 28}}, + "newText": "->Observable.subscribe" + } + }] From 34b2430e2e5efe0ff97bbddf699b2c8b3f80bdf8 Mon Sep 17 00:00:00 2001 From: nojaf Date: Thu, 19 Dec 2024 16:34:04 +0100 Subject: [PATCH 3/7] Extend Rxjs test with fully qualified access --- analysis/tests/src/RxjsCompletion.res | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/analysis/tests/src/RxjsCompletion.res b/analysis/tests/src/RxjsCompletion.res index 2db3d62f4..eaf2b40d4 100644 --- a/analysis/tests/src/RxjsCompletion.res +++ b/analysis/tests/src/RxjsCompletion.res @@ -1,3 +1,6 @@ +@@warning("-26") +@@warning("-110") + type keyPress = | Up(string) | Down(string) @@ -24,8 +27,13 @@ let main = async () => { // merge(keydown, keyup). // ^com - // Rxjs.Observable.subscribe, Rxjs.pipe and Rxjs.pipe2 should be completed + // Rxjs.Observable.subscribe, Rxjs.pipe and Rxjs.pipe2 should be completed } - ignore(keyMapObservable) + let (a,b) : ( Rxjs.Observable.t , Rxjs.Observable.t) = %todo + + // Rxjs.combineLatest(a, b). + // ^com + + // Rxjs.Observable.subscribe, Rxjs.pipe and Rxjs.pipe2 should be completed } From cd771f02f48f16243be4ca40e8326713d3882a2f Mon Sep 17 00:00:00 2001 From: nojaf Date: Thu, 19 Dec 2024 16:45:26 +0100 Subject: [PATCH 4/7] Add@editor.completeFrom and incomplete test output --- analysis/tests/src/Rxjs.res | 2 + .../tests/src/expected/RxjsCompletion.res.txt | 49 +++++++++++++++---- 2 files changed, 42 insertions(+), 9 deletions(-) diff --git a/analysis/tests/src/Rxjs.res b/analysis/tests/src/Rxjs.res index 8353d4e5d..8d3cecbc1 100644 --- a/analysis/tests/src/Rxjs.res +++ b/analysis/tests/src/Rxjs.res @@ -7,6 +7,8 @@ module Subscriber = { } module Observable = { + // Complete items defined inside the parent module. + @editor.completeFrom(Rxjs) type t<'t> type dispose = unit => unit diff --git a/analysis/tests/src/expected/RxjsCompletion.res.txt b/analysis/tests/src/expected/RxjsCompletion.res.txt index 8ae7ac3c0..f07e1dd72 100644 --- a/analysis/tests/src/expected/RxjsCompletion.res.txt +++ b/analysis/tests/src/expected/RxjsCompletion.res.txt @@ -1,11 +1,11 @@ -Complete src/RxjsCompletion.res 23:29 -posCursor:[23:29] posNoWhite:[23:28] Found expr:[7:17->30:1] -posCursor:[23:29] posNoWhite:[23:28] Found expr:[8:2->29:26] -posCursor:[23:29] posNoWhite:[23:28] Found expr:[9:4->23:29] -posCursor:[23:29] posNoWhite:[23:28] Found expr:[11:4->23:29] -posCursor:[23:29] posNoWhite:[23:28] Found expr:[17:4->23:29] -posCursor:[23:29] posNoWhite:[23:28] Found expr:[23:7->23:29] -Pexp_field [23:7->23:28] _:[27:2->23:29] +Complete src/RxjsCompletion.res 26:29 +posCursor:[26:29] posNoWhite:[26:28] Found expr:[10:17->38:1] +posCursor:[26:29] posNoWhite:[26:28] Found expr:[11:2->32:78] +posCursor:[26:29] posNoWhite:[26:28] Found expr:[12:4->26:29] +posCursor:[26:29] posNoWhite:[26:28] Found expr:[14:4->26:29] +posCursor:[26:29] posNoWhite:[26:28] Found expr:[20:4->26:29] +posCursor:[26:29] posNoWhite:[26:28] Found expr:[26:7->26:29] +Pexp_field [26:7->26:28] _:[30:2->26:29] Completable: Cpath Value[merge](Nolabel, Nolabel)."" Raw opens: 1 Rxjs.place holder Package opens Pervasives.JsxModules.place holder @@ -16,6 +16,7 @@ ContextPath Value[merge] Path merge CPPipe pathFromEnv:Observable found:true Path Rxjs.Observable. +Path Rxjs. [{ "label": "->Observable.subscribe", "kind": 12, @@ -24,8 +25,38 @@ Path Rxjs.Observable. "documentation": null, "sortText": "subscribe", "textEdit": { - "range": {"start": {"line": 23, "character": 28}, "end": {"line": 23, "character": 28}}, + "range": {"start": {"line": 26, "character": 28}, "end": {"line": 26, "character": 28}}, "newText": "->Observable.subscribe" } }] +Complete src/RxjsCompletion.res 34:30 +posCursor:[34:30] posNoWhite:[34:29] Found expr:[10:17->38:1] +posCursor:[34:30] posNoWhite:[34:29] Found expr:[10:11->38:1] +posCursor:[34:30] posNoWhite:[34:29] Found expr:[11:2->34:30] +posCursor:[34:30] posNoWhite:[34:29] Found expr:[32:2->34:30] +posCursor:[34:30] posNoWhite:[34:29] Found expr:[34:5->34:30] +Pexp_field [34:5->34:29] _:[38:0->34:30] +Completable: Cpath Value[Rxjs, combineLatest](Nolabel, Nolabel)."" +Package opens Pervasives.JsxModules.place holder +Resolved opens 1 pervasives +ContextPath Value[Rxjs, combineLatest](Nolabel, Nolabel)."" +ContextPath Value[Rxjs, combineLatest](Nolabel, Nolabel) +ContextPath Value[Rxjs, combineLatest] +Path Rxjs.combineLatest +CPPipe pathFromEnv:Observable found:true +Path Rxjs.Observable. +Path Rxjs. +[{ + "label": "->Rxjs.Observable.subscribe", + "kind": 12, + "tags": [], + "detail": "(t<'t>, 't => unit) => subscription", + "documentation": null, + "sortText": "subscribe", + "textEdit": { + "range": {"start": {"line": 34, "character": 29}, "end": {"line": 34, "character": 29}}, + "newText": "->Rxjs.Observable.subscribe" + } + }] + From 9765485c2812e6b2c61caad012c9a217eade577e Mon Sep 17 00:00:00 2001 From: nojaf Date: Thu, 19 Dec 2024 16:53:20 +0100 Subject: [PATCH 5/7] Add passing test for property completion --- analysis/tests/src/CompletionPipeProperty.res | 23 +++++++++ .../expected/CompletionPipeProperty.res.txt | 50 +++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 analysis/tests/src/CompletionPipeProperty.res create mode 100644 analysis/tests/src/expected/CompletionPipeProperty.res.txt diff --git a/analysis/tests/src/CompletionPipeProperty.res b/analysis/tests/src/CompletionPipeProperty.res new file mode 100644 index 000000000..f4ef0c364 --- /dev/null +++ b/analysis/tests/src/CompletionPipeProperty.res @@ -0,0 +1,23 @@ +module ObservablePoint = { + type t = { + mutable x: int, + mutable y: int, + } + + @send + external setBoth: (t, float) => unit = "set" + + @send + external set: (t, float, float) => unit = "set" +} + +module Sprite = { + type t = { + anchor: ObservablePoint.t, + } +} + +let sprite : Sprite.t = %todo + +// sprite.anchor. +// ^com \ No newline at end of file diff --git a/analysis/tests/src/expected/CompletionPipeProperty.res.txt b/analysis/tests/src/expected/CompletionPipeProperty.res.txt new file mode 100644 index 000000000..ffd87d26d --- /dev/null +++ b/analysis/tests/src/expected/CompletionPipeProperty.res.txt @@ -0,0 +1,50 @@ +Complete src/CompletionPipeProperty.res 21:17 +posCursor:[21:17] posNoWhite:[21:16] Found expr:[21:3->21:17] +Pexp_field [21:3->21:16] _:[23:0->21:17] +Completable: Cpath Value[sprite].anchor."" +Package opens Pervasives.JsxModules.place holder +Resolved opens 1 pervasives +ContextPath Value[sprite].anchor."" +ContextPath Value[sprite].anchor +ContextPath Value[sprite] +Path sprite +CPPipe pathFromEnv:Sprite found:true +Path Sprite.anchor +CPPipe pathFromEnv:ObservablePoint found:true +Path ObservablePoint. +[{ + "label": "->ObservablePoint.setBoth", + "kind": 12, + "tags": [], + "detail": "(t, float) => unit", + "documentation": null, + "sortText": "setBoth", + "textEdit": { + "range": {"start": {"line": 21, "character": 16}, "end": {"line": 21, "character": 16}}, + "newText": "->ObservablePoint.setBoth" + } + }, { + "label": "->ObservablePoint.set", + "kind": 12, + "tags": [], + "detail": "(t, float, float) => unit", + "documentation": null, + "sortText": "set", + "textEdit": { + "range": {"start": {"line": 21, "character": 16}, "end": {"line": 21, "character": 16}}, + "newText": "->ObservablePoint.set" + } + }, { + "label": "x", + "kind": 5, + "tags": [], + "detail": "int", + "documentation": {"kind": "markdown", "value": "```rescript\nx: int\n```\n\n```rescript\ntype t = {mutable x: int, mutable y: int}\n```"} + }, { + "label": "y", + "kind": 5, + "tags": [], + "detail": "int", + "documentation": {"kind": "markdown", "value": "```rescript\ny: int\n```\n\n```rescript\ntype t = {mutable x: int, mutable y: int}\n```"} + }] + From a874b216778bcc92b93b73a3ba5aa916ae02b409 Mon Sep 17 00:00:00 2001 From: nojaf Date: Thu, 19 Dec 2024 16:56:26 +0100 Subject: [PATCH 6/7] Test still works when types are not named t. --- analysis/tests/src/CompletionPipeProperty.res | 12 ++++++------ .../src/expected/CompletionPipeProperty.res.txt | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/analysis/tests/src/CompletionPipeProperty.res b/analysis/tests/src/CompletionPipeProperty.res index f4ef0c364..3ef739ed9 100644 --- a/analysis/tests/src/CompletionPipeProperty.res +++ b/analysis/tests/src/CompletionPipeProperty.res @@ -1,23 +1,23 @@ module ObservablePoint = { - type t = { + type op = { mutable x: int, mutable y: int, } @send - external setBoth: (t, float) => unit = "set" + external setBoth: (op, float) => unit = "set" @send - external set: (t, float, float) => unit = "set" + external set: (op, float, float) => unit = "set" } module Sprite = { - type t = { - anchor: ObservablePoint.t, + type s = { + anchor: ObservablePoint.op, } } -let sprite : Sprite.t = %todo +let sprite : Sprite.s = %todo // sprite.anchor. // ^com \ No newline at end of file diff --git a/analysis/tests/src/expected/CompletionPipeProperty.res.txt b/analysis/tests/src/expected/CompletionPipeProperty.res.txt index ffd87d26d..7cfbd37c9 100644 --- a/analysis/tests/src/expected/CompletionPipeProperty.res.txt +++ b/analysis/tests/src/expected/CompletionPipeProperty.res.txt @@ -16,7 +16,7 @@ Path ObservablePoint. "label": "->ObservablePoint.setBoth", "kind": 12, "tags": [], - "detail": "(t, float) => unit", + "detail": "(op, float) => unit", "documentation": null, "sortText": "setBoth", "textEdit": { @@ -27,7 +27,7 @@ Path ObservablePoint. "label": "->ObservablePoint.set", "kind": 12, "tags": [], - "detail": "(t, float, float) => unit", + "detail": "(op, float, float) => unit", "documentation": null, "sortText": "set", "textEdit": { @@ -39,12 +39,12 @@ Path ObservablePoint. "kind": 5, "tags": [], "detail": "int", - "documentation": {"kind": "markdown", "value": "```rescript\nx: int\n```\n\n```rescript\ntype t = {mutable x: int, mutable y: int}\n```"} + "documentation": {"kind": "markdown", "value": "```rescript\nx: int\n```\n\n```rescript\ntype op = {mutable x: int, mutable y: int}\n```"} }, { "label": "y", "kind": 5, "tags": [], "detail": "int", - "documentation": {"kind": "markdown", "value": "```rescript\ny: int\n```\n\n```rescript\ntype t = {mutable x: int, mutable y: int}\n```"} + "documentation": {"kind": "markdown", "value": "```rescript\ny: int\n```\n\n```rescript\ntype op = {mutable x: int, mutable y: int}\n```"} }] From 9a8b960044e78908bb12bdd05992f9e9d1614f7c Mon Sep 17 00:00:00 2001 From: nojaf Date: Thu, 19 Dec 2024 17:02:38 +0100 Subject: [PATCH 7/7] Add test for @editor.completeFrom --- .../CompletionMultipleEditorCompleteFrom.res | 22 +++++++++++++++++++ ...mpletionMultipleEditorCompleteFrom.res.txt | 14 ++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 analysis/tests/src/CompletionMultipleEditorCompleteFrom.res create mode 100644 analysis/tests/src/expected/CompletionMultipleEditorCompleteFrom.res.txt diff --git a/analysis/tests/src/CompletionMultipleEditorCompleteFrom.res b/analysis/tests/src/CompletionMultipleEditorCompleteFrom.res new file mode 100644 index 000000000..35950e161 --- /dev/null +++ b/analysis/tests/src/CompletionMultipleEditorCompleteFrom.res @@ -0,0 +1,22 @@ +@@warning("-26") +@@warning("-27") +@@warning("-110") + +module A = { + @editor.completeFrom(B) @editor.completeFrom(C) + type a +} + +module B = { + let b = (a: A.a) => 1 +} + +module C = { + open A + let c = (a: a) => {'c'} +} + +let a : A.a = %todo +// a. +// ^com +// B.b and C.c should be completed \ No newline at end of file diff --git a/analysis/tests/src/expected/CompletionMultipleEditorCompleteFrom.res.txt b/analysis/tests/src/expected/CompletionMultipleEditorCompleteFrom.res.txt new file mode 100644 index 000000000..8476ebfc1 --- /dev/null +++ b/analysis/tests/src/expected/CompletionMultipleEditorCompleteFrom.res.txt @@ -0,0 +1,14 @@ +Complete src/CompletionMultipleEditorCompleteFrom.res 19:5 +posCursor:[19:5] posNoWhite:[19:4] Found expr:[19:3->19:5] +Pexp_field [19:3->19:4] _:[22:0->19:5] +Completable: Cpath Value[a]."" +Package opens Pervasives.JsxModules.place holder +Resolved opens 1 pervasives +ContextPath Value[a]."" +ContextPath Value[a] +Path a +CPPipe pathFromEnv:A found:true +Path A. +Path B. +[] +