diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index ee49f51..5ff9548 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -6,11 +6,9 @@ jobs: name: Test runs-on: ubuntu-latest steps: - - name: Install packages - run: | - sudo add-apt-repository ppa:neovim-ppa/stable - sudo apt update - sudo apt install neovim + - uses: rhysd/action-setup-vim@v1 + with: + neovim: true - uses: actions/checkout@v1 - uses: actions/setup-node@v1 with: @@ -22,3 +20,5 @@ jobs: nvim --version vim --version make test + - name: Test syntax + run: make test-syntax diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8797070..1c36955 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,6 +5,7 @@ - Clone the repo - `npm install` dependencies - `make test` to run the tests +- `make test-syntax`, require Neovim >= 0.9.0 **Working within VIM** @@ -21,6 +22,20 @@ Plug ~/Projects/vim-rescript **Integration Specs:** For all the informal specs about editor integration & the ReScript platform, check out the [CONTRIBUTING](https://github.com/rescript-lang/rescript-vscode/blob/master/CONTRIBUTING.md) file of the rescript-vscode reference implementation. +### Syntax Tests + +Syntax tests require Neovim >= 0.9.0 + +#### Adding new tests + +- Create or edit a file at `test/syntax/` directory. +- Write some code and add a comment in the following format: `//^` below the code. The `^` indicates the capture location. Example: + ```rescript + let a = true + //^ + ``` +- Run `make test-syntax` + ### Use custom rescript-editor-support.exe > Note: Don't do this as a ReScript user. This is only intended for extension development purposes only. diff --git a/Makefile b/Makefile index 34452e2..43a01e0 100644 --- a/Makefile +++ b/Makefile @@ -7,3 +7,7 @@ export INMAKE test: @$(MYVIM) -u ./test/test_all.vim + +test-syntax: + nvim -l test/test-syntax.lua + git diff --name-only --exit-code -- 'test/syntax/expected/*.res.txt' diff --git a/test/syntax/expected/highlight.res.txt b/test/syntax/expected/highlight.res.txt new file mode 100644 index 0000000..3446a6e --- /dev/null +++ b/test/syntax/expected/highlight.res.txt @@ -0,0 +1,271 @@ +{ { + col = 1, + row = 0, + syntax = { { + hl_group = "resArrowPipe", + hl_group_link = "Statement" + } } + }, { + col = 1, + row = 3, + syntax = {} + }, { + col = 1, + row = 6, + syntax = { { + hl_group = "resAttribute", + hl_group_link = "PreProc" + } } + }, { + col = 9, + row = 8, + syntax = {} + }, { + col = 1, + row = 11, + syntax = { { + hl_group = "resKeyword", + hl_group_link = "Statement" + } } + }, { + col = 7, + row = 14, + syntax = {} + }, { + col = 9, + row = 17, + syntax = { { + hl_group = "resBoolean", + hl_group_link = "Constant" + } } + }, { + col = 9, + row = 19, + syntax = { { + hl_group = "resBoolean", + hl_group_link = "Constant" + } } + }, { + col = 11, + row = 22, + syntax = { { + hl_group = "resString", + hl_group_link = "Constant" + } } + }, { + col = 19, + row = 24, + syntax = { { + hl_group = "resString", + hl_group_link = "Constant" + } } + }, { + col = 8, + row = 26, + syntax = { { + hl_group = "resChar", + hl_group_link = "Constant" + } } + }, { + col = 11, + row = 29, + syntax = { { + hl_group = "resString", + hl_group_link = "Constant" + } } + }, { + col = 8, + row = 32, + syntax = {} + }, { + col = 12, + row = 34, + syntax = {} + }, { + col = 12, + row = 37, + syntax = {} + }, { + col = 7, + row = 40, + syntax = {} + }, { + col = 9, + row = 43, + syntax = {} + }, { + col = 9, + row = 46, + syntax = {} + }, { + col = 1, + row = 49, + syntax = { { + hl_group = "resKeyword", + hl_group_link = "Statement" + } } + }, { + col = 4, + row = 52, + syntax = {} + }, { + col = 7, + row = 56, + syntax = { { + hl_group = "resType", + hl_group_link = "Type" + } } + }, { + col = 7, + row = 61, + syntax = {} + }, { + col = 9, + row = 65, + syntax = { { + hl_group = "resType", + hl_group_link = "Type" + } } + }, { + col = 11, + row = 68, + syntax = {} + }, { + col = 9, + row = 71, + syntax = { { + hl_group = "resModuleOrVariant", + hl_group_link = "Identifier" + } } + }, { + col = 9, + row = 74, + syntax = { { + hl_group = "resPolyVariant", + hl_group_link = "Identifier" + } } + }, { + col = 7, + row = 77, + syntax = {} + }, { + col = 3, + row = 80, + syntax = { { + hl_group = "resKeyword", + hl_group_link = "Statement" + } } + }, { + col = 1, + row = 85, + syntax = { { + hl_group = "resKeyword", + hl_group_link = "Statement" + } } + }, { + col = 2, + row = 87, + syntax = { { + hl_group = "resModuleChain", + hl_group_link = "PreProc" + } } + }, { + col = 1, + row = 91, + syntax = { { + hl_group = "resKeyword", + hl_group_link = "Statement" + } } + }, { + col = 1, + row = 96, + syntax = { { + hl_group = "resKeyword", + hl_group_link = "Statement" + } } + }, { + col = 1, + row = 100, + syntax = { { + hl_group = "resKeyword", + hl_group_link = "Statement" + } } + }, { + col = 3, + row = 103, + syntax = { { + hl_group = "resKeyword", + hl_group_link = "Statement" + } } + }, { + col = 17, + row = 105, + syntax = { { + hl_group = "resKeyword", + hl_group_link = "Statement" + } } + }, { + col = 1, + row = 109, + syntax = { { + hl_group = "resKeyword", + hl_group_link = "Statement" + } } + }, { + col = 1, + row = 112, + syntax = { { + hl_group = "resKeyword", + hl_group_link = "Statement" + } } + }, { + col = 1, + row = 116, + syntax = { { + hl_group = "resKeyword", + hl_group_link = "Statement" + } } + }, { + col = 1, + row = 118, + syntax = {} + }, { + col = 5, + row = 120, + syntax = {} + }, { + col = 5, + row = 124, + syntax = { { + hl_group = "resType", + hl_group_link = "Type" + } } + }, { + col = 5, + row = 126, + syntax = { { + hl_group = "resType", + hl_group_link = "Type" + } } + }, { + col = 5, + row = 128, + syntax = { { + hl_group = "resKeyword", + hl_group_link = "Statement" + } } + }, { + col = 4, + row = 130, + syntax = { { + hl_group = "resType", + hl_group_link = "Type" + } } + }, { + col = 5, + row = 132, + syntax = { { + hl_group = "resType", + hl_group_link = "Type" + } } + } } \ No newline at end of file diff --git a/test/syntax/highlight.res b/test/syntax/highlight.res new file mode 100644 index 0000000..6bd1e5a --- /dev/null +++ b/test/syntax/highlight.res @@ -0,0 +1,134 @@ +@@warning("-27") +//^ + +%%raw(`console.log("Hello")`) +//^ + +@deprecated +//^ +let _ = %raw(`1`) + //^ + +let a = 1 +//^ + +let _ = 1 + //^ + +let _ = true + //^ +let _ = false + //^ + +let _ = "hello!" + //^ +let _ = `Hello World 👋 ${name}` + //^ +let _ = 'a' + //^ + +let _ = j`Today` + //^ + +let _ = %re("/b/g") + //^ +let _ = true && true + //^ + +let _ = true || false + //^ + +let _ = !true + //^ + +let _ = 2 <= 3 + //^ + +let _ = 2 <= 3 + //^ + +type t +//^ + +type r + //^ + +type t = { + age: int + //^ +} + +type t = { + a: promise + //^ +} + +let _ = list{1, 2} + //^ + +let _ = {...me, age: me.age + 1} + //^ + +let _ = Some("My Name") + //^ + +let _ = #red + //^ + +let _ = if true { + //^ + "Good morning!" +} else { + //^ + "Hello!" +} + +for i in 1 to 10 { +//^ + Js.log(i) + //^ +} + +while true { +//^ + Js.log(true) +} + +exception InputClosed(string) +//^ + + +try { +//^ + someJSFunctionThatThrows() +} catch { + //^ +| Not_found => assert false + //^ +} + +open Js.Array2 +//^ + +include Js +//^ + + +switch [1, 2, 3] { +//^ + | [] => true +//^ + | _ => false + //^ +} + +let list = 2 + //^ +let array = [1] + //^ +let catch = 1 + //^ +let ref = ref(false) + //^ +let option = None + //^ diff --git a/test/test-syntax.lua b/test/test-syntax.lua new file mode 100644 index 0000000..269a6c0 --- /dev/null +++ b/test/test-syntax.lua @@ -0,0 +1,49 @@ +local cwd = vim.fn.getcwd() +local dir = '/test/syntax/' +local expected_dir = '/test/syntax/expected' + +local FILES = { 'highlight.res' } + +local function main(file) + -- Load syntax file + local path = cwd .. dir .. file + + vim.cmd.edit(path) + vim.cmd.source(cwd .. '/syntax/rescript.vim') + + local bufnr = vim.api.nvim_get_current_buf() + local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, true) + + local pattern = '//^' + local locations = {} + + for number, line in ipairs(lines) do + local is_start_pattern = vim.startswith(vim.trim(line), pattern) + local is_valid = number - 1 > 0 + and not vim.startswith(vim.trim(lines[number - 1]), pattern) + + if is_start_pattern and is_valid then + local start_match, _ = string.find(line, pattern) + + local col = start_match - 1 + string.len(pattern) + + local item = + vim.inspect_pos(bufnr, number - 2, col - 2, { syntax = true }) + + table.insert( + locations, + { row = item.row, col = item.col, syntax = item.syntax } + ) + end + end + + local output_file = cwd .. expected_dir .. '/' .. file .. '.txt' + + local fd = vim.loop.fs_open(output_file, 'w', 438) + vim.loop.fs_write(fd, vim.inspect(locations), 0) + vim.loop.fs_close(fd) +end + +for _, file in ipairs(FILES) do + main(file) +end