The Sumneko Lua language server has matured quite a bit and many Neovim developers use it while working on Neovim. Having a default configuration for Neovim development is a nice convenience (and dovetails well with the auto-generated compile_command.json for C development). The file is shipped under `contrib` and users can make use of it by symlinking to `.luarc.json` in the project root.
12 KiB
Contributing to Neovim
Getting started
If you want to help but don't know where to start, here are some low-risk/isolated tasks:
- Merge a Vim patch.
- Try a good first issue or complexity:low issue.
- Fix bugs found by Clang, PVS or Coverity.
- Improve documentation
Reporting problems
- Check the FAQ.
- Search existing issues (including closed!)
- Update Neovim to the latest version to see if your problem persists.
- Try to reproduce with
nvim --clean
("factory defaults"). - Bisect your config: disable plugins incrementally, to narrow down the cause of the issue.
- Bisect Neovim's source code to find the cause of a regression, if you can. This is extremely helpful.
- When reporting a crash, include a stacktrace.
- Use ASAN/UBSAN to get detailed errors for segfaults and undefined behavior.
- Check the logs.
:edit $NVIM_LOG_FILE
- Include
cmake --system-information
for build-related issues.
Developer guidelines
- Read
:help dev
if you are working on Nvim core. - Read
:help dev-ui
if you are developing a UI. - Read
:help dev-api-client
if you are developing an API client. - Install
ninja
for faster builds of Nvim.sudo apt-get install ninja-build make distclean make # Nvim build system uses ninja automatically, if available.
Pull requests (PRs)
- To avoid duplicate work, create a draft pull request.
- Your PR must include test coverage.
- Avoid cosmetic changes to unrelated files in the same commit.
- Use a feature branch instead of the master branch.
- Use a rebase workflow for small PRs.
- After addressing review comments, it's fine to rebase and force-push.
- Use a merge workflow for big, high-risk PRs.
- Merge
master
into your PR when there are conflicts or when master introduces breaking changes. - Use the
ri
git alias:
This avoids unnecessary rebases yet still allows you to combine related commits, separate monolithic commits, etc.[alias] ri = "!sh -c 't=\"${1:-master}\"; s=\"${2:-HEAD}\"; mb=\"$(git merge-base \"$t\" \"$s\")\"; if test \"x$mb\" = x ; then o=\"$t\"; else lm=\"$(git log -n1 --merges \"$t..$s\" --pretty=%H)\"; if test \"x$lm\" = x ; then o=\"$mb\"; else o=\"$lm\"; fi; fi; test $# -gt 0 && shift; test $# -gt 0 && shift; git rebase --interactive \"$o\" \"$@\"'"
- Do not edit commits that come before the merge commit.
- Merge
- During a squash/fixup, use
exec make -C build unittest
between each pick/edit/reword.
Stages: Draft and Ready for review
Pull requests have two stages: Draft and Ready for review.
- Create a Draft PR while you are not requesting feedback as
you are still working on the PR.
- You can skip this if your PR is ready for review.
- Change your PR to ready when the PR is ready for review.
- You can convert back to Draft at any time.
Do not add labels like [RFC]
or [WIP]
in the title to indicate the
state of your PR: this just adds noise. Non-Draft PRs are assumed to be open
for comments; if you want feedback from specific people, @
-mention them in
a comment.
Commit messages
Follow the conventional commits guidelines to make reviews easier and to make the VCS/git logs more valuable. The general structure of a commit message is:
<type>([optional scope]): <description>
[optional body]
[optional footer(s)]
- Prefix the commit subject with one of these types:
build
,ci
,docs
,feat
,fix
,perf
,refactor
,revert
,test
,vim-patch
,chore
- You can ignore this for "fixup" commits or any commits you expect to be squashed.
- Append optional scope to type such as
(lsp)
,(treesitter)
,(float)
, … - Description shouldn't start with a capital letter or end in a period.
- Use the imperative voice: "Fix bug" rather than "Fixed bug" or "Fixes bug."
- Try to keep the first line under 72 characters.
- A blank line must follow the subject.
- Breaking API changes must be indicated by
- "!" after the type/scope, and
- a "BREAKING CHANGE" footer describing the change.
Example:
refactor(provider)!: drop support for Python 2 BREAKING CHANGE: refactor to use Python 3 features since Python 2 is no longer supported.
Automated builds (CI)
Each pull request must pass the automated builds on sourcehut and GitHub Actions.
- CI builds are compiled with
-Werror
, so compiler warnings will fail the build. - If any tests fail, the build will fail. See test/README.md#running-tests to run tests locally. Passing locally doesn't guarantee passing the CI build, because of the different compilers and platforms tested against.
- CI runs ASan and other analyzers.
- To run valgrind locally:
VALGRIND=1 make test
- To run Clang ASan/UBSan locally:
CC=clang make CMAKE_FLAGS="-DCLANG_ASAN_UBSAN=ON"
- To run valgrind locally:
- The lint build checks modified lines and their immediate neighbors, to encourage incrementally updating the legacy style to meet our style. (See #3174 for background.)
- CI for freebsd and openbsd runs on sourcehut.
- To get a backtrace on freebsd (after connecting via ssh):
sudo pkg install tmux # If you want tmux. lldb build/bin/nvim -c nvim.core # To get a full backtrace: # 1. Rebuild with debug info. rm -rf nvim.core build gmake CMAKE_BUILD_TYPE=RelWithDebInfo CMAKE_EXTRA_FLAGS="-DCI_BUILD=ON -DMIN_LOG_LEVEL=3" nvim # 2. Run the failing test to generate a new core file. TEST_FILE=test/functional/foo.lua gmake functionaltest lldb build/bin/nvim -c nvim.core
- To get a backtrace on freebsd (after connecting via ssh):
Clang scan-build
View the Clang report to see potential bugs found by the Clang scan-build analyzer.
- Search the Neovim commit history to find examples:
git log --oneline --no-merges --grep clang
- To verify a fix locally, run
scan-build
like this:rm -rf build/ scan-build --use-analyzer=/usr/bin/clang make
PVS-Studio
View the PVS report to see potential bugs found by PVS Studio.
- Use this format for commit messages (where
{id}
is the PVS warning-id)):fix(PVS/V{id}): {description}
- Search the Neovim commit history to find examples:
git log --oneline --no-merges --grep PVS
- Try
./scripts/pvscheck.sh
to run PVS locally.
Coverity
Coverity runs against the master build. To view the defects, just request access; you will be approved.
- Use this format for commit messages (where
{id}
is the CID (Coverity ID); (example)):fix(coverity/{id}): {description}
- Search the Neovim commit history to find examples:
git log --oneline --no-merges --grep coverity
Clang sanitizers (ASAN and UBSAN)
ASAN/UBSAN can be used to detect memory errors and other common forms of undefined behavior at runtime in debug builds.
- To build Neovim with sanitizers enabled, use
rm -rf build && CMAKE_EXTRA_FLAGS="-DCMAKE_C_COMPILER=clang -DCLANG_ASAN_UBSAN=1" make
- When running Neovim, use
UBSAN_OPTIONS=print_stacktrace=1 ASAN_OPTIONS=log_path=/tmp/nvim_asan nvim args...
- If Neovim exits unexpectedly, check
/tmp/nvim_asan.{PID}
(or your preferredlog_path
) for log files with error messages.
Coding
Lint
You can run the linter locally by:
make lint
The lint step downloads the master error list and excludes them, so only lint errors related to the local changes are reported.
You can lint a single file (but this will not exclude legacy errors):
./src/clint.py src/nvim/ops.c
Style
- Style rules are (mostly) defined by
src/uncrustify.cfg
which tries to match the style-guide. To use the Nvimgq
command withuncrustify
:
The required version ofif !empty(findfile('src/uncrustify.cfg', ';')) setlocal formatprg=uncrustify\ -q\ -l\ C\ -c\ src/uncrustify.cfg\ --no-backup endif
uncrustify
is specified inuncrustify.cfg
. - There is also
.clang-format
which has drifted from the style-guide, but is available for reference. To use the Nvimgq
command withclang-format
:if !empty(findfile('.clang-format', ';')) setlocal formatprg=clang-format\ -style=file endif
Navigate
-
Set
blame.ignoreRevsFile
to ignore noise commits in git blame:git config blame.ignoreRevsFile .git-blame-ignore-revs
-
Use universal-ctags. ("Exuberant ctags", the typical
ctags
binary provided by your distro, is unmaintained and won't recognize many function signatures in Neovim source.) -
Explore the source code on the web.
-
If using lua-language-server, symlink
contrib/luarc.json
into the project root:$ ln -s contrib/luarc.json .luarc.json
Reviewing
To help review pull requests, start with this checklist.
Reviewing can be done on GitHub, but you may find it easier to do locally.
Using hub
, you can create a new branch with the contents of a pull
request, e.g. #1820:
hub checkout https://github.com/neovim/neovim/pull/1820
Use git log -p master..FETCH_HEAD
to list all
commits in the feature branch which aren't in the master
branch; -p
shows each commit's diff. To show the whole surrounding function of a change
as context, use the -W
argument as well.