Library / SDK
ThePrimeagen/refactoring.nvim avatar
ThePrimeagen/refactoring.nvim

refactoring.nvim: LSP and Tree-sitter Refactoring Operations for Neovim

The Refactoring library based off the Refactoring book by Martin Fowler

3,649 stars106 forksLuaMIT

At a glance

What is it?
refactoring.nvim is a Neovim plugin that implements Martin Fowler's refactoring catalog using LSP servers for reference and definition lookups and tree-sitter parsers for structural code analysis. It provides extract, inline, and debug-print operations that work with textobjects and dot-repeat across 13 supported languages.
Who is it for?
refactoring.nvim suits Neovim developers who run LSP servers and tree-sitter parsers and want automated refactoring operations that work on multi-file scopes. It requires Neovim 0.12.5 or later and a properly configured LSP server for inline operations.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 8 days ago.
What is it written in?
Mainly Lua, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What refactoring.nvim Solves and Who It Is For

Neovim is a programmer's editor that has gained LSP integration and tree-sitter parsing, two capabilities that enable structural code manipulation. refactoring.nvim builds on both to provide refactoring operations that work across file scopes, not just within a single buffer. The target user is a developer who uses Neovim as their primary editor, has LSP servers configured for their languages, and wants automated extract-function or inline-variable operations that a traditional IDE would provide. The README quotes Martin Fowler: 'If I use an environment that has good automated refactorings, I can trust those refactorings.' The plugin's goal is to bring that trust to Neovim by leveraging LSP for reference resolution and tree-sitter for syntax boundary detection, rather than relying on regex-based text manipulation.

How LSP and Tree-sitter Power Each Operation

refactoring.nvim uses two sources of information depending on the operation. Inline variable uses LSP textDocument/references to find every reference to the variable and textDocument/definition to locate its definition, then replaces all references with the definition's expression. Inline function similarly uses LSP to find all call sites and the function body. Tree-sitter provides the structural boundary information: refactor_scope identifies the scope containing a selection, refactor_reference finds variable references within a scope, refactor_variable marks variable definitions, refactor_function and refactor_function_call identify function boundaries and calls. Extract function uses tree-sitter to determine what variables enter and exit the selected region, which drives the generated function signature. The README notes the plugin keeps Lua logic as generic and language-agnostic as possible; all language-specific information comes from LSP servers and tree-sitter queries. The quality of tree-sitter queries determines how accurate the refactoring is for a given language.

Installing refactoring.nvim

The plugin requires Neovim 0.12.5 or later. The README shows two installation paths. Using vim.pack.add (Neovim's built-in package manager):

lua
vim.pack.add {
  "https://github.com/lewis6991/async.nvim",
  "https://github.com/theprimeagen/refactoring.nvim"
}

The README notes that async.nvim is only required for Neovim 0.12; Neovim 0.13 users do not need it. Using lazy.nvim:

lua
{
  "ThePrimeagen/refactoring.nvim",
  dependencies = {
    "lewis6991/async.nvim",
  },
  lazy = false,
},

Calling require('refactoring').setup() is not required for the plugin to work, but it is available for overriding defaults. Tree-sitter parsers and an LSP server for the target language must be installed separately before the operations that depend on them will function. The Makefile shows that the test suite uses make deps to clone async.nvim, mason.nvim, and nvim-treesitter and installs parsers for Lua, Java, PHP, Go, PowerShell, C, C#, C++, JavaScript, Python, Ruby, TSX, Vimscript, and Markdown. Tests run with mini.nvim's test runner in headless Neovim, so the test suite requires a working Neovim installation with Mason and tree-sitter available.

The Code Refactoring Operations

refactoring.nvim provides four structural code operations. Extract function takes a selected text region and moves it into a new function, replacing the selection with a call to that function. The generated function signature includes the variables that enter the selection as parameters and the variables that leave as return values, determined by tree-sitter query analysis. Extract variable takes an expression and all its identical usages in the buffer and replaces them with a named variable. Inline variable does the reverse: it replaces a variable and all its references with the variable's definition expression, then removes the variable declaration. Inline function inlines the function body at every call site; the README notes it only supports functions with a single return statement, which is a hard limit for functions returning multiple values or using early returns. Each operation works on the buffer's current content without the need to save first. The plugin integrates with Neovim's operator protocol, which means operations support dot-repeat and work with any textobject or motion. The :Refactor command offers completions for available refactors, previews the change before applying it, and accepts additional arguments for refactors that need extra input.

Debug Print Operations

The plugin includes three debug print operations alongside the structural refactorings. Print location inserts a debug statement with the cursor's location expressed as a path (for example, some_function#if#for). Print variable inserts a debug statement showing all variables and their locations in the selected range. Print expression inserts a debug statement with the selected expression and its location. A fourth operation, debug print cleanup, removes all print statements inserted by the plugin within the selected range. These operations require only tree-sitter (refactor_comment and refactor_output_statement queries), without an LSP dependency, making them available on any language with a tree-sitter parser. Print location and print variable generate language-appropriate print statements: a Python file gets a print() call; a Go file gets fmt.Println; a Lua file gets print().

Configuration and Keymap Setup

No keymaps are created by default. The README provides two keymap patterns. The dedicated keymap pattern assigns each operation to a separate key:

lua
local keymap = vim.keymap
keymap.set({ "n", "x" }, "<leader>re", function()
  return require("refactoring").extract_func()
end, { desc = "Extract Function", expr = true })

The single-key select pattern opens a picker to choose the operation:

lua
keymap.set({ "n", "x" }, "<leader>rs", function()
  require("refactoring").select_refactor()
end, { desc = "Select refactor" })

Configuration can be set globally with require('refactoring').setup({...}), per-call with require('refactoring').inline_var({...}), or per-buffer with vim.b.refactor_config = {...}. The default configuration is at lua/refactoring/config.lua in the repository.

Supported Languages and How to Add a New One

The README lists 13 supported languages: C, C#, C++, Go, Java, JavaScript, TypeScript, JSX, TSX, Lua, PHP, PowerShell, Python, Ruby, and Vimscript. Tree-sitter queries for all supported languages are bundled with the plugin in the queries/ directory. Adding or improving support for a new language requires creating tree-sitter query files in the Neovim config directory at ~/.config/nvim/queries/lang/query_name.scm. Each file must start with ;; extends to extend the bundled queries rather than replace them entirely, which is how tree-sitter modeline extensions work in Neovim. The contributor workflow the README describes is to create queries locally and daily-drive them (use them in real work) before opening a pull request, because language-specific edge cases often surface only in real-world code. Each feature's required query names are listed in the Features section of the README: for example, extract function requires refactor_reference, refactor_scope, refactor_output_function, and refactor_input_function. Alongside the queries, contributors must also add code generation functions to the global config. The README notes the goal is to keep Lua logic generic and language-agnostic, so contributors add only tree-sitter queries and code generation functions, not changes to the core refactoring algorithms. This architecture means that better tree-sitter queries directly produce better refactoring accuracy for a given language.

Editorial conclusion

refactoring.nvim suits Neovim developers who run LSP servers and tree-sitter parsers and want automated refactoring operations that work on multi-file scopes. It requires Neovim 0.12.5 or later and a properly configured LSP server for inline operations. Developers on Neovim versions below 0.12.5 or on languages without tree-sitter parser support will find most operations unavailable. The last push was on 2026-09-23.

Frequently asked questions

What is the purpose of refactoring?

Refactoring improves the internal structure of code without changing its external behavior, making it easier to understand and modify. refactoring.nvim implements specific operations from Martin Fowler's refactoring catalog: extracting functions, inlining variables, and inlining functions, using LSP and tree-sitter to make those transformations structurally correct.

When should code be refactored?

The README does not prescribe when to refactor. The plugin provides operations for extract function, extract variable, inline function, and inline variable that can be invoked at any time through keymaps or the :Refactor command, which supports previewing changes before applying them.

What is the difference between refactoring and restructuring code?

The README does not define a distinction. refactoring.nvim implements automated operations from Fowler's refactoring catalog that preserve external behavior while changing internal structure. The plugin works at the function and variable scope level, driven by LSP reference lookups and tree-sitter structural queries.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. ThePrimeagen/refactoring.nvim on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/theprimeagen-refactoring-nvim.svg)](https://hysenlabs.com/projects/theprimeagen-refactoring-nvim)