aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorRiley Bruins <ribru17@hotmail.com>2024-07-27 08:34:30 -0700
committerGitHub <noreply@github.com>2024-07-27 17:34:30 +0200
commitf97e0de0053df1cb3b9f74b9b1239acced1b7d9a (patch)
tree99659d6656483a4b8704bb944a234cb62ef79115 /tests
parentfix(query): properly apply predicate injections (diff)
downloadnvim-treesitter-f97e0de0053df1cb3b9f74b9b1239acced1b7d9a.tar
nvim-treesitter-f97e0de0053df1cb3b9f74b9b1239acced1b7d9a.tar.gz
nvim-treesitter-f97e0de0053df1cb3b9f74b9b1239acced1b7d9a.tar.bz2
nvim-treesitter-f97e0de0053df1cb3b9f74b9b1239acced1b7d9a.tar.lz
nvim-treesitter-f97e0de0053df1cb3b9f74b9b1239acced1b7d9a.tar.xz
nvim-treesitter-f97e0de0053df1cb3b9f74b9b1239acced1b7d9a.tar.zst
nvim-treesitter-f97e0de0053df1cb3b9f74b9b1239acced1b7d9a.zip
feat: add rescript parser and queries (#6671)
Diffstat (limited to 'tests')
-rw-r--r--tests/indent/rescript/basic.res23
-rw-r--r--tests/indent/rescript/complex.res151
-rw-r--r--tests/indent/rescript/conditional.res104
-rw-r--r--tests/indent/rescript_spec.lua33
4 files changed, 311 insertions, 0 deletions
diff --git a/tests/indent/rescript/basic.res b/tests/indent/rescript/basic.res
new file mode 100644
index 000000000..c5138a7b3
--- /dev/null
+++ b/tests/indent/rescript/basic.res
@@ -0,0 +1,23 @@
+@genType
+type person = {
+ name: string,
+ age: int,
+}
+
+@genType
+type renderMe<'a> = React.component<{
+ "randomString": string,
+ "poly": 'a,
+}>
+
+@genType.import("./hookExample") @react.component
+external make: (
+ ~person: person,
+ ~children: React.element,
+ ~renderMe: renderMe<'a>,
+) => React.element = "makeRenamed"
+
+@genType.import("./hookExample")
+external foo: (~person: person) => string = "foo"
+
+let hi = 'a'
diff --git a/tests/indent/rescript/complex.res b/tests/indent/rescript/complex.res
new file mode 100644
index 000000000..1f21c3364
--- /dev/null
+++ b/tests/indent/rescript/complex.res
@@ -0,0 +1,151 @@
+let hit = ({hit, children}: DocSearch.hitComponent) => {
+ let toTitle = str =>
+ str->Js.String2.charAt(0)->Js.String2.toUpperCase ++ Js.String2.sliceToEnd(str, ~from=1)
+
+ let description = switch hit.url
+ ->Js.String2.split("/")
+ ->Js.Array2.sliceFrom(1)
+ ->Belt.List.fromArray {
+ | list{"blog" as r | "community" as r, ..._} => r->toTitle
+ | list{"docs", doc, version, ...rest} =>
+ let path = rest->Belt.List.toArray
+
+ let info =
+ path
+ ->Js.Array2.slice(~start=0, ~end_=Js.Array2.length(path) - 1)
+ ->Js.Array2.map(path =>
+ switch path {
+ | "api" => "API"
+ | other => toTitle(other)
+ }
+ )
+
+ [doc->toTitle, version->toTitle]->Js.Array2.concat(info)->Js.Array2.joinWith(" / ")
+ | _ => ""
+ }
+
+ <Next.Link href={hit.url} className="flex flex-col w-full">
+ <span className="text-gray-60 captions px-4 pt-3 pb-1 block">
+ {description->React.string}
+ </span>
+ children
+ </Next.Link>
+}
+
+let transformItems = (items: DocSearch.transformItems) => {
+ items->Belt.Array.keepMap(item => {
+ let url = try Webapi.URL.make(item.url)->Some catch {
+ | Js.Exn.Error(obj) =>
+ Js.Console.error2(`Failed to parse URL ${item.url}`, obj)
+ None
+ }
+ switch url {
+ | Some({pathname, hash}) => {...item, url: pathname ++ hash}->Some
+ | None => None
+ }
+ })
+}
+
+@react.component
+let make = () => {
+ let (state, setState) = React.useState(_ => Inactive)
+ let router = Next.Router.useRouter()
+
+ let version = switch Url.parse(router.route).version {
+ | Version(v) => v
+ | _ => "latest"
+ }
+
+ let handleCloseModal = () => {
+ let () = switch ReactDOM.querySelector(".DocSearch-Modal") {
+ | Some(modal) =>
+ switch ReactDOM.querySelector("body") {
+ | Some(body) =>
+ open Webapi
+ body->Element.classList->ClassList.remove("DocSearch--active")
+ modal->Element.addEventListener("transitionend", () => {
+ setState(_ => Inactive)
+ })
+ | None => setState(_ => Inactive)
+ }
+ | None => ()
+ }
+ }
+
+ React.useEffect(() => {
+ let isEditableTag = el =>
+ switch el->tagName {
+ | "TEXTAREA" | "SELECT" | "INPUT" => true
+ | _ => false
+ }
+
+ let focusSearch = e => {
+ switch activeElement {
+ | Some(el) if el->isEditableTag || el->isContentEditable => ()
+ | _ =>
+ setState(_ => Active)
+ e->keyboardEventPreventDefault
+ }
+ }
+
+ let handleGlobalKeyDown = e => {
+ switch e.key {
+ | "/" => focusSearch(e)
+ | "k" if e.ctrlKey || e.metaKey => focusSearch(e)
+ | "Escape" => handleCloseModal()
+ | _ => ()
+ }
+ }
+ addKeyboardEventListener("keydown", handleGlobalKeyDown)
+ Some(() => removeKeyboardEventListener("keydown", handleGlobalKeyDown))
+ }, [setState])
+
+ let onClick = _ => {
+ setState(_ => Active)
+ }
+
+ let onClose = React.useCallback(() => {
+ handleCloseModal()
+ }, [setState])
+
+ <>
+ <button onClick type_="button" className="text-gray-60 hover:text-fire-50 p-2">
+ <Icon.MagnifierGlass className="fill-current" />
+ </button>
+ {switch state {
+ | Active =>
+ switch ReactDOM.querySelector("body") {
+ | Some(element) =>
+ ReactDOM.createPortal(
+ <DocSearch
+ apiKey
+ appId
+ indexName
+ onClose
+ searchParameters={facetFilters: ["version:" ++ version]}
+ initialScrollY={window->scrollY}
+ transformItems={transformItems}
+ hitComponent=hit
+ />
+ element,
+ )
+ | None => React.null
+ }
+ | Inactive => React.null
+ }}
+ </>
+}
+
+let comparable = (type key, ~cmp) => {
+ module N = MakeComparable({
+ type t = key
+ let cmp = cmp
+ })
+ module(N: Comparable with type t = key)
+}
+
+<Next.Link href={hit.url} className="flex flex-col w-full">
+<span className="text-gray-60 captions px-4 pt-3 pb-1 block">
+ {description->React.string}
+ children
+</Next.Link>
diff --git a/tests/indent/rescript/conditional.res b/tests/indent/rescript/conditional.res
new file mode 100644
index 000000000..db8328f26
--- /dev/null
+++ b/tests/indent/rescript/conditional.res
@@ -0,0 +1,104 @@
+include UseClient
+include UseQuery
+include UseMutation
+include UseSubscription
+
+type hookResponse<'ret> = Types.Hooks.hookResponse<'ret> = {
+ operation: Types.operation,
+ fetching: bool,
+ data: option<'ret>,
+ error: option<CombinedError.t>,
+ response: Types.Hooks.response<'ret>,
+ extensions: option<Js.Json.t>,
+ stale: bool,
+}
+
+Js.Array2.slice(~start=0, ~end_=Js.Array2.length(moduleRoute) - 1)
+
+let pathModule = Path.join([dir, version, `${moduleName}.json`])
+
+let {Api.LocMsg.row: row, column, shortMsg} = locMsg
+
+let message = `${"error"->red}: failed to compile examples from ${kind} ${test.id->cyan}\n${errorMessage}`
+
+let version = (evt->ReactEvent.Form.target)["value"]
+
+let rehypePlugins =
+ [Rehype.WithOptions([Plugin(Rehype.slug), SlugOption({prefix: slugPrefix ++ "-"})])]->Some
+
+module Item = {
+ type t = {
+ name: string,
+ sellIn: int,
+ quality: int,
+ }
+
+ let make = (~name, ~sellIn, ~quality): t => {
+ name,
+ sellIn,
+ quality,
+ }
+}
+
+let updateQuality = (items: array<Item.t>) => {
+ items->Js.Array2.map(item => {
+ let newItem = ref(item)
+
+ call(
+ asdf,
+ asdf
+ )
+
+ if (
+ newItem.contents.name != "Aged Brie" && 5 > 2 &&
+ newItem.contents.name != "Backstage passes to a TAFKAL80ETC concert"
+ ) {
+ if newItem.contents.quality > 0 {
+ if newItem.contents.name != "Sulfuras, Hand of Ragnaros" {
+ newItem := {...newItem.contents, quality: newItem.contents.quality - 1}
+ }
+ }
+ } else if newItem.contents.quality < 50 {
+ newItem := {...newItem.contents, quality: newItem.contents.quality + 1}
+
+ if newItem.contents.name == "Backstage passes to a TAFKAL80ETC concert" {
+ if newItem.contents.sellIn < 11 {
+ if newItem.contents.quality < 50 {
+ newItem := {...newItem.contents, quality: newItem.contents.quality + 1}
+ }
+ }
+
+ if newItem.contents.sellIn < 6 {
+ if newItem.contents.quality < 50 {
+ newItem := {...newItem.contents, quality: newItem.contents.quality + 1}
+ }
+ }
+ }
+ }
+
+ if newItem.contents.name != "Sulfuras, Hand of Ragnaros" {
+ newItem := {...newItem.contents, sellIn: newItem.contents.sellIn - 1}
+ }
+
+ if newItem.contents.sellIn < 0 {
+ if newItem.contents.name != "Aged Brie" {
+ if newItem.contents.name != "Backstage passes to a TAFKAL80ETC concert" {
+ if newItem.contents.quality > 0 {
+ if newItem.contents.name != "Sulfuras, Hand of Ragnaros" {
+ newItem := {...newItem.contents, quality: newItem.contents.quality - 1}
+ }
+ }
+ } else {
+ newItem := {
+ ...newItem.contents,
+ quality: newItem.contents.quality - newItem.contents.quality,
+ }
+ }
+ } else if newItem.contents.quality < 50 {
+ newItem := {...newItem.contents, quality: newItem.contents.quality + 1}
+ }
+ }
+
+ newItem.contents
+ })
+}
diff --git a/tests/indent/rescript_spec.lua b/tests/indent/rescript_spec.lua
new file mode 100644
index 000000000..5b1f06abd
--- /dev/null
+++ b/tests/indent/rescript_spec.lua
@@ -0,0 +1,33 @@
+local Runner = require("tests.indent.common").Runner
+
+local run = Runner:new(it, "tests/indent/rescript", {
+ tabstop = 2,
+ shiftwidth = 2,
+ softtabstop = 0,
+ expandtab = true,
+})
+
+describe("indent ReScript:", function()
+ describe("whole file:", function()
+ run:whole_file(".", {})
+ end)
+
+ describe("new line:", function()
+ run:new_line("basic.res", { on_line = 5, text = "x", indent = 0 })
+ run:new_line("basic.res", { on_line = 9, text = '"another": here,', indent = 2 })
+ run:new_line("basic.res", { on_line = 10, text = "}", indent = 0 })
+ run:new_line("basic.res", { on_line = 14, text = "~test: test,", indent = 2 })
+ run:new_line("basic.res", { on_line = 18, text = "x", indent = 0 })
+
+ run:new_line("complex.res", { on_line = 3, text = "x", indent = 2 })
+ run:new_line("complex.res", { on_line = 5, text = "x", indent = 4 })
+ run:new_line("complex.res", { on_line = 17, text = "|", indent = 10 })
+ run:new_line("complex.res", { on_line = 25, text = "x", indent = 2 })
+ run:new_line("complex.res", { on_line = 60, text = "x", indent = 6 })
+ run:new_line("complex.res", { on_line = 120, text = "x", indent = 14 })
+ run:new_line("complex.res", { on_line = 136, text = "x", indent = 2 })
+
+ run:new_line("conditional.res", { on_line = 6, text = "test: bool,", indent = 2 })
+ run:new_line("conditional.res", { on_line = 95, text = "x", indent = 10 })
+ end)
+end)