diff --git a/.github/workflows/build_test.yml b/.github/workflows/build_test.yml new file mode 100644 index 0000000..e5750dc --- /dev/null +++ b/.github/workflows/build_test.yml @@ -0,0 +1,37 @@ +name: Rust Build and Nvim Integration + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +env: + CARGO_TERM_COLOR: always + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Build + run: cargo build --verbose + + - uses: rhysd/action-setup-vim@v1 + with: + neovim: true + + - name: Create symbolic link for Neovim configuration + run: | + cp ./target/debug/polyglot_ls /tmp/polyglot_ls + ln -s $(realpath editor_integrations/nvim/nvim-config) ${HOME}/.config/nvim-test + + + - name: Run integration tests + run: | + nvim --version + # install all plugins + NVIM_APPNAME=nvim-test nvim -c 'sleep 20' -c "q!" --headless + cd tests && ./run_all.sh diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml deleted file mode 100644 index 7f05c5f..0000000 --- a/.github/workflows/rust.yml +++ /dev/null @@ -1,20 +0,0 @@ -name: Rust - -on: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] - -env: - CARGO_TERM_COLOR: always - -jobs: - build: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - name: Build - run: cargo build --verbose diff --git a/editor_integrations/nvim/nvim-config/init.lua b/editor_integrations/nvim/nvim-config/init.lua new file mode 100644 index 0000000..b1a9864 --- /dev/null +++ b/editor_integrations/nvim/nvim-config/init.lua @@ -0,0 +1,26 @@ +require("patwie") +function test_lsp_code_action(action_title) + -- vim.api.nvim_win_set_cursor(0, { 2, 2 }) -- Line 3, Column 5 (0-indexed column) + + vim.defer_fn(function() + vim.lsp.buf.code_action({ + filter = function(action) + return action.title == action_title + end, + apply = true + }) + + -- -- After applying the code action, wait for a brief moment, then write the file and quit + -- vim.defer_fn(function() + -- -- Get the original filename + -- -- Construct the new filename + -- -- Write the buffer to the new file + -- -- vim.cmd("write! " .. new_filename) + -- -- vim.api.nvim_command("write! " .. new_filename) + -- -- Quit Neovim + -- -- vim.cmd("quit!") + -- -- vim.api.nvim_command("quit!") + -- end, 4000) -- Adjust delay as needed to ensure code action has completed + end, 1000) -- 1000 milliseconds = 1 second +end + diff --git a/editor_integrations/nvim/nvim-config/lazy-lock.json b/editor_integrations/nvim/nvim-config/lazy-lock.json new file mode 100644 index 0000000..b7652f2 --- /dev/null +++ b/editor_integrations/nvim/nvim-config/lazy-lock.json @@ -0,0 +1,3 @@ +{ + "nvim-lspconfig": { "branch": "master", "commit": "652386deae739e38fa1bcf2f06e3e7de9b3436ba" } +} diff --git a/editor_integrations/nvim/nvim-config/lua/patwie/init.lua b/editor_integrations/nvim/nvim-config/lua/patwie/init.lua new file mode 100644 index 0000000..c12bdca --- /dev/null +++ b/editor_integrations/nvim/nvim-config/lua/patwie/init.lua @@ -0,0 +1,2 @@ +require("patwie.lazy_init") + diff --git a/editor_integrations/nvim/nvim-config/lua/patwie/lazy/lsp.lua b/editor_integrations/nvim/nvim-config/lua/patwie/lazy/lsp.lua new file mode 100644 index 0000000..d6c8c04 --- /dev/null +++ b/editor_integrations/nvim/nvim-config/lua/patwie/lazy/lsp.lua @@ -0,0 +1,46 @@ +return { + + { + "neovim/nvim-lspconfig", + + config = function() + local util = require 'lspconfig.util' + local configs = require 'lspconfig.configs' + + if not configs.polyglot_ls then + configs.polyglot_ls = { + default_config = { + cmd = { "/tmp/polyglot_ls" }, + filetypes = { 'python', 'rust', 'text', 'go', 'gitcommit', 'markdown' }, + root_dir = util.root_pattern(unpack({ + 'pyproject.toml', + 'ruff.toml', + 'Cargo.toml', + })) or util.find_git_ancestor(), + single_file_support = true, + }, + } + end + + local servers = { + polyglot_ls = { + -- cmd = vim.lsp.rpc.connect('127.0.0.1', 9257), + cmd = { "/tmp/polyglot_ls", "--stdio" , "--use-mock" }, + filetypes = { 'python', 'rust', 'text', 'go', 'gitcommit', 'markdown' }, + }, + } + + local capabilities = vim.lsp.protocol.make_client_capabilities() + + for server_name, server_config in pairs(servers) do + server_config.capabilities = capabilities + server_config.flags = { + debounce_text_changes = 200, + allow_incremental_sync = true, + } + local lspconfig = require("lspconfig") + lspconfig[server_name].setup(server_config) + end + end, + }, +} diff --git a/editor_integrations/nvim/nvim-config/lua/patwie/lazy_init.lua b/editor_integrations/nvim/nvim-config/lua/patwie/lazy_init.lua new file mode 100644 index 0000000..9fdc55c --- /dev/null +++ b/editor_integrations/nvim/nvim-config/lua/patwie/lazy_init.lua @@ -0,0 +1,27 @@ +local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" +if not vim.loop.fs_stat(lazypath) then + vim.fn.system({ + "git", + "clone", + "--filter=blob:none", + "https://github.com/folke/lazy.nvim.git", + "--branch=stable", -- latest stable release + lazypath, + }) +end +vim.opt.rtp:prepend(lazypath) + +require("lazy").setup({ + spec = "patwie.lazy", + pkg = { + enabled = true, + cache = vim.fn.stdpath("state") .. "/lazy/pkg-cache.lua", + -- the first package source that is found for a plugin will be used. + sources = { + "lazy", + "rockspec", -- will only be used when rocks.enabled is true + "packspec", + }, + }, + change_detection = { notify = false } +}) diff --git a/tests/.gitignore b/tests/.gitignore new file mode 100644 index 0000000..f47cb20 --- /dev/null +++ b/tests/.gitignore @@ -0,0 +1 @@ +*.out diff --git a/tests/cases/Polyglot: Update Function Args Type Annotations/simple.2.2.py b/tests/cases/Polyglot: Update Function Args Type Annotations/simple.2.2.py new file mode 100644 index 0000000..942cd81 --- /dev/null +++ b/tests/cases/Polyglot: Update Function Args Type Annotations/simple.2.2.py @@ -0,0 +1,2 @@ +def add(a, b): + return a+b diff --git a/tests/cases/Polyglot: Update Function Args Type Annotations/simple.2.2.py.want b/tests/cases/Polyglot: Update Function Args Type Annotations/simple.2.2.py.want new file mode 100644 index 0000000..05e17e7 --- /dev/null +++ b/tests/cases/Polyglot: Update Function Args Type Annotations/simple.2.2.py.want @@ -0,0 +1,2 @@ +def add(MOCK): + return a+b diff --git a/tests/cases/Polyglot: Update Function Docstring/simple.2.2.py b/tests/cases/Polyglot: Update Function Docstring/simple.2.2.py new file mode 100644 index 0000000..942cd81 --- /dev/null +++ b/tests/cases/Polyglot: Update Function Docstring/simple.2.2.py @@ -0,0 +1,2 @@ +def add(a, b): + return a+b diff --git a/tests/cases/Polyglot: Update Function Docstring/simple.2.2.py.want b/tests/cases/Polyglot: Update Function Docstring/simple.2.2.py.want new file mode 100644 index 0000000..a4819f5 --- /dev/null +++ b/tests/cases/Polyglot: Update Function Docstring/simple.2.2.py.want @@ -0,0 +1,3 @@ +def add(a, b): + MOCK + return a+b diff --git a/tests/run_all.sh b/tests/run_all.sh new file mode 100755 index 0000000..c8a660e --- /dev/null +++ b/tests/run_all.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +TEST_DIR="cases" + +find "$TEST_DIR" -type f -name "*.py" ! -name "*.want.py" | while IFS= read -r file; do + echo "---" + echo $file + if [ -d "$file" ] || [[ "$file" == "." ]] || [[ "$file" == ".." ]]; then + continue + fi + base_filename=$(basename "$file" .py) + + IFS='.' read -r case_name cursor_line cursor_pos ext <<< "$base_filename" + want_file="${file}.want" + got_file="${file}.out" + action_name=$(basename "$(dirname "$file")") + + NVIM_APPNAME=nvim-test nvim -c "edit $file | call cursor($cursor_line, $cursor_pos)" -c "lua test_lsp_code_action(\"$action_name\")" -c 'sleep 4' -c "wq! $got_file" --headless + + if diff -u "$want_file" "$got_file"; then + echo "Test passed: $file" + else + echo "Test failed: $file" + exit 1 + fi +done +