Skip to content

inkpark/nvim-mybatis

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

88 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

nvim-mybatis

nvim-mybatis is a focused Neovim plugin for jumping between Java MyBatis mapper interfaces and XML statements, with automatic indexing, persisted project snapshots, save-time refreshes, and background manual reindexing. v0.3.2 keeps the release line intentionally narrow, focused on the standard mapper contract rather than broader framework heuristics.

中文文档 · Changelog

Quickstart

  1. Install the plugin.
  2. Open a Java mapper interface or MyBatis XML mapper.
  3. Run :MyBatisJump to jump to the paired location.
  4. The first full project index is written to <project-root>/.nvim_mybatis/index.mpack.
  5. After the project root has been indexed once, save edited *.java or *.xml files to keep that index fresh.
  6. Use :MyBatisReindex if you want to rebuild the project index manually.

Basic usage does not require a manual setup() call. The plugin auto-initializes from plugin/mybatis.lua when it is loaded by your plugin manager.

Requirements

  • Neovim 0.10 or newer
  • A MyBatis project that follows the standard mapper contract
  • Optional: jdtls for better Java method resolution
  • Optional: Neovim tree-sitter parsers for java and xml for more precise parser backends; the legacy parser remains the fallback

Installation

lazy.nvim

{
  "inkpark/nvim-mybatis",
}

Pin v0.3.2

{
  "inkpark/nvim-mybatis",
  tag = "v0.3.2",
}

No extra setup() call is needed for the default workflow. The plugin auto-initializes from plugin/mybatis.lua when it is loaded by your plugin manager.

Keymaps

The plugin exposes commands, but it does not install default keybindings. If you want faster access, bind the commands in your plugin manager config or your normal Neovim config.

lazy.nvim

{
  "inkpark/nvim-mybatis",
  keys = {
    { "<leader>mj", "<cmd>MyBatisJump<cr>", desc = "MyBatis Jump" },
    { "<leader>mr", "<cmd>MyBatisReindex<cr>", desc = "MyBatis Reindex" },
  },
}

vim.keymap.set

vim.keymap.set("n", "<leader>mj", "<cmd>MyBatisJump<cr>", { desc = "MyBatis Jump" })
vim.keymap.set("n", "<leader>mr", "<cmd>MyBatisReindex<cr>", { desc = "MyBatis Reindex" })

These bindings are only examples. Adjust them to match your own <leader> conventions.

Usage

MyBatisJump is the main entry point:

  • In a Java mapper buffer, it jumps from the current method to the matching XML statement.
  • On a Java mapper parameter type, it jumps to the matching XML parameterType when present.
  • On a Java mapper parameter name, it jumps to matching XML placeholders in the paired statement.
  • On a Java field such as Address.city, it jumps to XML placeholders and resultMap properties that resolve to that field.
  • In an XML mapper buffer, it jumps from the current statement to the matching Java method.
  • On XML type references such as parameterType, resultType, resultMap type, javaType, and ofType, it jumps to the referenced Java type definition.
  • On an XML placeholder such as #{query.user.address.city}, it jumps to the matching Java parameter or nested field.
  • On resultMap property paths such as address.city, it jumps to the matching nested Java field.
  • Inside <foreach> scopes, it resolves item aliases and nested aliases such as #{item.address.city} and #{tag.name}.

When only one target exists, the plugin jumps directly. When multiple targets exist, it opens a built-in floating selector with a live code preview so you can choose the destination explicitly.

When a project has no saved snapshot yet, the first MyBatisJump builds the index in a background headless Neovim worker, keeps the UI responsive, and automatically resumes the pending jump if you stay on the same cursor while indexing finishes.

MyBatisReindex rebuilds the cached index for the current project root in the background, keeps the editor responsive while it runs, and shows a command-line progress bar until completion.

Save behavior is incremental:

  • BufWritePost refreshes *.java buffers.
  • BufWritePost refreshes *.xml buffers.
  • This refresh path only applies after the project root has already been indexed once, for example by an earlier :MyBatisJump or :MyBatisReindex.
  • It keeps the cached index aligned with the current file without requiring a full reindex.

Disk cache behavior is project-local:

  • The first full index is persisted under <project-root>/.nvim_mybatis/index.mpack.
  • Later sessions load that snapshot first, then scan for only new, changed, or deleted *.java and *.xml files.
  • BufWritePost and :MyBatisReindex both update the on-disk snapshot, so future first jumps can reuse it.

v0.3.2 ships these release-level capabilities:

  • Mapper method <-> XML statement jumps for the standard MyBatis contract.
  • Type-aware XML reference jumps into Java classes and records.
  • Nested placeholder and resultMap property resolution into Java fields, plus reverse jumps from Java fields back to matching XML references.
  • Incremental save-time refreshes backed by a persisted project snapshot.
  • Background manual reindex with progress UI and last-known-good state protection on failure.
  • Optional jdtls assistance for better Java method detection in the current buffer.
  • Optional tree-sitter parser backends for Java and XML, with legacy parser fallback.

Supported Contract

nvim-mybatis assumes the standard Java-to-XML mapper relationship:

  • The XML namespace matches the Java interface fully qualified name.
  • The XML statement id matches the Java method name.
  • Supported XML statement types are select, insert, update, and delete.

Anything outside that contract is intentionally out of scope for the 0.3.x release line.

How It Works

The plugin discovers a project root by walking upward from the current buffer and looking for common markers:

  • .git
  • pom.xml
  • settings.gradle
  • build.gradle
  • gradlew
  • mvnw

This marker-based approach is layout-tolerant, so it works across common monorepo and nested-module layouts as long as the mapper files live under a recognized root. The runtime flow is project-index driven: on the first full index, the plugin scans Java and XML files under that root, parses mapper declarations, builds a lightweight index, and persists it under .nvim_mybatis. Later sessions load that snapshot, incrementally reconcile changed files, and then resolve jump targets from the refreshed index. It does not continuously watch the full project for changes.

Optional Tree-sitter Parser Backend

nvim-mybatis can use Neovim tree-sitter parsers for Java and XML when they are installed. Tree-sitter is optional: if Neovim cannot load a required parser, or if a tree-sitter parse path fails, the plugin silently falls back to the built-in legacy parser.

The default behavior enables tree-sitter opportunistically. You can disable it globally or per parser domain:

require("mybatis").setup({
  parser = {
    treesitter = {
      enabled = true,
      java = true,
      java_type = true,
      xml = true,
    },
  },
})

Set enabled = false to force the legacy parser for all Java/XML parsing, or set an individual domain such as xml = false to keep only that parser on the legacy path.

Optional jdtls Integration

jdtls is optional. When it is available, nvim-mybatis uses it to improve Java method resolution in the current buffer. When it is not available, the plugin falls back to its own lightweight Java parsing and cursor-based heuristics.

jdtls does not change the core contract or the supported file types. It only improves how the current Java symbol is identified before the jump happens.

Known Limitations / Non-goals

  • No support for arbitrary annotation-based mapper styles outside the XML contract.
  • No support for custom statement name mapping or namespace aliasing.
  • No support for unsupported XML statement types such as selectKey or other non-standard tags.
  • No automatic project-wide refactoring or code generation.
  • No attempt to model every MyBatis or Java parsing edge case in the 0.3.x release line.

The goal is dependable mapper navigation, not full MyBatis framework coverage.

Roadmap

The 0.3.x roadmap stays deliberately small:

  • Keep direct mapper navigation stable and predictable.
  • Improve diagnostics and ergonomics where they reduce user friction.
  • Expand parser coverage only when it clearly supports the core mapper workflow.
  • Keep jdtls optional rather than making it a hard dependency.

Future work will remain centered on the mapper jump and reindex workflow, not on turning the plugin into a general MyBatis tooling suite.

Tests / Development

Run the headless test suite with Neovim:

nvim --headless -u tests/minimal_init.lua -l tests/smoke/commands_spec.lua
nvim --headless -u tests/minimal_init.lua -l tests/smoke/minimal_init_spec.lua
nvim --headless -u tests/minimal_init.lua -l tests/unit/helpers_spec.lua
nvim --headless -u tests/minimal_init.lua -l tests/unit/parser_java_spec.lua
nvim --headless -u tests/minimal_init.lua -l tests/unit/parser_java_type_spec.lua
nvim --headless -u tests/minimal_init.lua -l tests/unit/parser_xml_spec.lua
nvim --headless -u tests/minimal_init.lua -l tests/unit/parser_backend_spec.lua
nvim --headless -u tests/minimal_init.lua -l tests/unit/scanner_spec.lua
nvim --headless -u tests/minimal_init.lua -l tests/unit/cache_spec.lua
nvim --headless -u tests/minimal_init.lua -l tests/unit/index_spec.lua
nvim --headless -u tests/minimal_init.lua -l tests/unit/reindex_spec.lua
nvim --headless -u tests/minimal_init.lua -l tests/unit/resolver_spec.lua
nvim --headless -u tests/minimal_init.lua -l tests/integration/jump_spec.lua
nvim --headless -u tests/minimal_init.lua -l tests/integration/java_field_jump_spec.lua
nvim --headless -u tests/minimal_init.lua -l tests/integration/refresh_spec.lua
nvim --headless -u tests/minimal_init.lua -l tests/integration/result_map_property_jump_spec.lua

About

mybatis plugin for neovim

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages