263 changed files with 33669 additions and 2 deletions
@ -1,4 +1,4 @@ |
|||||||
set keywordprg=man " Просмотр страниц руководства |
set keywordprg=man " Просмотр страниц руководства |
||||||
|
|
||||||
set makeprg=bash\ -n\ % " Проверка на ошибки и синтаксис |
set makeprg=shellcheck\ -s\ bash\ -f\ gcc\ % " Проверка на ошибки и синтаксис |
||||||
set errorformat=%f:\ line\ %l:\ %m " Формат строки с информацией |
set errorformat=\|\|\ %f:line\ %l:%c:\ %m " Формат строки с информацией |
||||||
|
@ -0,0 +1,125 @@ |
|||||||
|
version: 2 |
||||||
|
|
||||||
|
common: &common |
||||||
|
docker: |
||||||
|
- image: neomake/vims-for-tests:47@sha256:b540d84bb5ca445ee28625a5c2f72ce790908a23cd9e6f0b05150840ad15e8b3 |
||||||
|
working_directory: ~/repo |
||||||
|
steps: |
||||||
|
- checkout |
||||||
|
- run: |
||||||
|
name: Run tests |
||||||
|
command: | |
||||||
|
cc-test-reporter before-build |
||||||
|
make --keep-going testcoverage TEST_VIM=$TEST_VIM |
||||||
|
- run: |
||||||
|
name: Handle coverage |
||||||
|
command: | |
||||||
|
set -x |
||||||
|
mkdir test-results |
||||||
|
cp -a .coverage_covimerage test-results/.coverage_covimerage.$CIRCLE_BUILD_NUM |
||||||
|
|
||||||
|
# Upload to codecov, which handles this per job itself. |
||||||
|
coverage xml |
||||||
|
# -Z: exit with 1 in case of failures. |
||||||
|
codecov -Z -X search -X gcov -X pycov -f coverage.xml \ |
||||||
|
-n "$CIRCLE_JOB" -F "${CIRCLE_JOB%%-*}" -e CIRCLE_JOB |
||||||
|
set +x |
||||||
|
- persist_to_workspace: |
||||||
|
root: . |
||||||
|
paths: |
||||||
|
- test-results/ |
||||||
|
|
||||||
|
jobs: |
||||||
|
nvim-038: |
||||||
|
<<: *common |
||||||
|
environment: |
||||||
|
TEST_VIM=/vim-build/bin/neovim-v0.3.8 |
||||||
|
nvim-017: |
||||||
|
<<: *common |
||||||
|
environment: |
||||||
|
TEST_VIM=/vim-build/bin/neovim-v0.1.7 |
||||||
|
nvim-master: |
||||||
|
<<: *common |
||||||
|
environment: |
||||||
|
TEST_VIM=/vim-build/bin/neovim-master |
||||||
|
vim-master: |
||||||
|
<<: *common |
||||||
|
environment: |
||||||
|
TEST_VIM=/vim-build/bin/vim-master |
||||||
|
vim-81: |
||||||
|
<<: *common |
||||||
|
environment: |
||||||
|
TEST_VIM=/vim-build/bin/vim81 |
||||||
|
vim-80: |
||||||
|
<<: *common |
||||||
|
environment: |
||||||
|
TEST_VIM=/vim-build/bin/vim80 |
||||||
|
vim-74-xenial: |
||||||
|
<<: *common |
||||||
|
environment: |
||||||
|
TEST_VIM=/vim-build/bin/vim74-xenial |
||||||
|
vim-74-trusty: |
||||||
|
<<: *common |
||||||
|
environment: |
||||||
|
TEST_VIM=/vim-build/bin/vim74-trusty |
||||||
|
vim-73: |
||||||
|
<<: *common |
||||||
|
environment: |
||||||
|
TEST_VIM=/vim-build/bin/vim73 |
||||||
|
|
||||||
|
checkqa: |
||||||
|
<<: *common |
||||||
|
steps: |
||||||
|
- checkout |
||||||
|
- run: make checkqa |
||||||
|
|
||||||
|
coverage: |
||||||
|
<<: *common |
||||||
|
steps: |
||||||
|
# TODO: checkout only necessary for covimerage plugin?! |
||||||
|
# Writing/using .coveragerc only might be enough. |
||||||
|
- checkout |
||||||
|
- attach_workspace: |
||||||
|
at: /tmp/workspace |
||||||
|
- run: |
||||||
|
name: Upload global coverage results |
||||||
|
command: | |
||||||
|
set -x |
||||||
|
cp -a /tmp/workspace/test-results/.coverage_covimerage.* . |
||||||
|
|
||||||
|
coverage combine |
||||||
|
coverage xml |
||||||
|
|
||||||
|
# Coveralls. |
||||||
|
# Only TRAVIS_JOB_ID is used by python-coveralls. |
||||||
|
env -u COVERALLS_PARALLEL TRAVIS_JOB_ID=$CIRCLE_WORKFLOW_ID coveralls |
||||||
|
|
||||||
|
# Codeclimate. |
||||||
|
cc-test-reporter after-build |
||||||
|
set +x |
||||||
|
|
||||||
|
workflows: |
||||||
|
version: 2 |
||||||
|
test: |
||||||
|
jobs: |
||||||
|
- nvim-038 |
||||||
|
- nvim-017 |
||||||
|
- vim-81 |
||||||
|
- vim-80 |
||||||
|
- vim-74-xenial |
||||||
|
- vim-74-trusty |
||||||
|
- vim-73 |
||||||
|
- nvim-master |
||||||
|
- vim-master |
||||||
|
- checkqa |
||||||
|
- coverage: |
||||||
|
requires: |
||||||
|
- nvim-master |
||||||
|
- nvim-038 |
||||||
|
- nvim-017 |
||||||
|
- vim-master |
||||||
|
- vim-81 |
||||||
|
- vim-80 |
||||||
|
- vim-74-xenial |
||||||
|
- vim-74-trusty |
||||||
|
- vim-73 |
@ -0,0 +1,7 @@ |
|||||||
|
[run] |
||||||
|
plugins = covimerage |
||||||
|
data_file = .coverage_covimerage |
||||||
|
|
||||||
|
[report] |
||||||
|
include = autoload/*,plugin/*,syntax/*,tests/* |
||||||
|
omit = tests/fixtures/vim/* |
@ -0,0 +1,3 @@ |
|||||||
|
policies: |
||||||
|
ProhibitImplicitScopeVariable: |
||||||
|
enabled: false |
@ -0,0 +1,63 @@ |
|||||||
|
# From https://github.com/tweekmonster/vim-testbed. |
||||||
|
FROM testbed/vim:16@sha256:ce0e3c0407e9af4c41868636199906e3c2a6c6f02b97f6bb3e2767aeba6d5c85 |
||||||
|
|
||||||
|
# Currently tested versions: |
||||||
|
# - v7.3.429 (Ubuntu Precise, 12.04LTS) |
||||||
|
# - v7.4.052 (Ubuntu Trusty, 14.04LTS) |
||||||
|
# - v7.4.1689 (Ubuntu Xenial, 16.04LTS) |
||||||
|
# - v8.0.586 (Updated Vim 8, https://vim.sourceforge.io/download.php) |
||||||
|
# TODO: clean up names to make them usable as-is in CircleCI config. |
||||||
|
# Uses fixed-profiling patch with vim81 (https://github.com/vim/vim/pull/2499). |
||||||
|
RUN install_vim -tag v7.3.429 -name vim73 --with-features=huge -build \ |
||||||
|
-tag v7.4.052 -name vim74-trusty --with-features=huge -build \ |
||||||
|
-tag v7.4.1689 -name vim74-xenial --with-features=huge -build \ |
||||||
|
-tag v8.0.0586 -name vim80 -py2 -build \ |
||||||
|
-tag neovim:v0.1.7 -build \ |
||||||
|
&& rm -rf /vim-build/**/runtime/tutor |
||||||
|
RUN install_vim -tag v8.1.0622 -name vim81 -build \ |
||||||
|
-tag neovim:v0.3.8 -py3 -build \ |
||||||
|
&& rm -rf /vim-build/**/runtime/tutor |
||||||
|
|
||||||
|
ENV NEOMAKE_DOCKERFILE_UPDATE=2019-09-19 |
||||||
|
|
||||||
|
# Git master in a separate layer, since the above is meant to be stable. |
||||||
|
RUN install_vim -tag master -build \ |
||||||
|
-tag neovim:master -build \ |
||||||
|
&& rm -rf /vim-build/**/runtime/tutor |
||||||
|
|
||||||
|
# Install tools for running tests (busybox's grep does not have --line-number). |
||||||
|
# openssh for CircleCI to improve Git checkout. |
||||||
|
RUN apk --no-cache add bash curl grep make openssh-client |
||||||
|
|
||||||
|
# Codeclimate reporter. |
||||||
|
RUN curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > /usr/local/bin/cc-test-reporter \ |
||||||
|
&& chmod +x /usr/local/bin/cc-test-reporter |
||||||
|
|
||||||
|
# Install dep plugins (test runner and those used during tests). |
||||||
|
# Keeps git and installs ssh for CircleCI's checkout (and diffing for changed |
||||||
|
# files). grep for checks. |
||||||
|
ENV NEOMAKE_TESTS_DEP_PLUGINS_DIR=/neomake-deps |
||||||
|
ENV VIMHELPLINT_DIR=$NEOMAKE_TESTS_DEP_PLUGINS_DIR/vim-vimhelplint |
||||||
|
RUN mkdir $NEOMAKE_TESTS_DEP_PLUGINS_DIR |
||||||
|
RUN apk --no-cache add git \ |
||||||
|
&& git clone -q --depth=1 -b display-source-with-exceptions https://github.com/blueyed/vader.vim $NEOMAKE_TESTS_DEP_PLUGINS_DIR/vader \ |
||||||
|
&& git clone -q --depth=1 https://github.com/tpope/vim-fugitive $NEOMAKE_TESTS_DEP_PLUGINS_DIR/vim-fugitive \ |
||||||
|
&& git clone -q --depth=1 https://github.com/machakann/vim-vimhelplint $NEOMAKE_TESTS_DEP_PLUGINS_DIR/vim-vimhelplint \ |
||||||
|
&& git clone -q --depth=1 https://github.com/syngan/vim-vimlint /tools/vim-vimlint \ |
||||||
|
&& git clone -q --depth=1 https://github.com/ynkdir/vim-vimlparser /tools/vim-vimlparser |
||||||
|
RUN test -f /vim-build/bin/vim81 && ln -s /vim-build/bin/vim81 /usr/local/bin/vim |
||||||
|
RUN printf '#!/bin/sh -x\n/tools/vim-vimlint/bin/vimlint.sh -l /tools/vim-vimlint -p /tools/vim-vimlparser "$@"\n' > /usr/local/bin/vimlint |
||||||
|
RUN chmod +x /usr/local/bin/vimlint |
||||||
|
|
||||||
|
# Install covimerage and vint. |
||||||
|
RUN apk --no-cache add python3 \ |
||||||
|
&& pip3 install -U pip \ |
||||||
|
&& pip3 install --no-cache-dir python-coveralls covimerage==0.1.7 vim-vint==0.3.21 \ |
||||||
|
&& rm -rf /usr/include /usr/lib/python*/turtle* /usr/lib/python*/tkinter \ |
||||||
|
&& pip3 uninstall --yes pip \ |
||||||
|
&& curl https://codecov.io/bash -o /usr/bin/codecov \ |
||||||
|
&& chmod +x /usr/bin/codecov \ |
||||||
|
&& cd /usr/bin && ln -s python3 python |
||||||
|
|
||||||
|
RUN adduser -D -s /bin/bash neomake |
||||||
|
USER neomake |
@ -0,0 +1,21 @@ |
|||||||
|
The MIT License (MIT) |
||||||
|
|
||||||
|
Copyright (c) 2015 benekastah |
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy |
||||||
|
of this software and associated documentation files (the "Software"), to deal |
||||||
|
in the Software without restriction, including without limitation the rights |
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||||
|
copies of the Software, and to permit persons to whom the Software is |
||||||
|
furnished to do so, subject to the following conditions: |
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in |
||||||
|
all copies or substantial portions of the Software. |
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
||||||
|
THE SOFTWARE. |
@ -0,0 +1,413 @@ |
|||||||
|
# Do not let mess "cd" with user-defined paths.
|
||||||
|
CDPATH:=
|
||||||
|
|
||||||
|
TEST_SHELL:=$(shell command -v bash 2>/dev/null)
|
||||||
|
ifeq ($(TEST_SHELL),) |
||||||
|
$(error Could not determine TEST_SHELL (defaults to bash))
|
||||||
|
endif |
||||||
|
# This is expected in tests.
|
||||||
|
TEST_VIM_PREFIX:=SHELL=$(TEST_SHELL)
|
||||||
|
SHELL:=$(TEST_SHELL) -o pipefail
|
||||||
|
|
||||||
|
# Use nvim if it is installed, otherwise vim.
|
||||||
|
ifeq ($(TEST_VIM),) |
||||||
|
ifeq ($(shell command -v nvim 2>/dev/null),) |
||||||
|
TEST_VIM:=vim
|
||||||
|
else |
||||||
|
TEST_VIM:=nvim
|
||||||
|
endif |
||||||
|
endif |
||||||
|
|
||||||
|
IS_NEOVIM=$(findstring nvim,$(TEST_VIM))$(findstring neovim,$(TEST_VIM))
|
||||||
|
test: $(if $(IS_NEOVIM),testnvim,testvim) |
||||||
|
test_interactive: $(if $(TEST_VIM),$(if $(IS_NEOVIM),testnvim_interactive,testvim_interactive),testnvim_interactive testvim_interactive) |
||||||
|
|
||||||
|
VADER:=Vader!
|
||||||
|
VADER_OPTIONS:=-q
|
||||||
|
VADER_ARGS=tests/all.vader
|
||||||
|
VIM_ARGS='+$(VADER) $(VADER_OPTIONS) $(VADER_ARGS)'
|
||||||
|
|
||||||
|
NEOMAKE_TESTS_DEP_PLUGINS_DIR?=build/vim/plugins
|
||||||
|
TESTS_VADER_DIR:=$(NEOMAKE_TESTS_DEP_PLUGINS_DIR)/vader
|
||||||
|
$(TESTS_VADER_DIR): |
||||||
|
mkdir -p $(dir $@)
|
||||||
|
git clone -q --depth=1 -b display-source-with-exceptions https://github.com/blueyed/vader.vim $@
|
||||||
|
TESTS_FUGITIVE_DIR:=$(NEOMAKE_TESTS_DEP_PLUGINS_DIR)/vim-fugitive
|
||||||
|
$(TESTS_FUGITIVE_DIR): |
||||||
|
mkdir -p $(dir $@)
|
||||||
|
git clone -q --depth=1 https://github.com/tpope/vim-fugitive $@
|
||||||
|
|
||||||
|
DEP_PLUGINS=$(TESTS_VADER_DIR) $(TESTS_FUGITIVE_DIR)
|
||||||
|
|
||||||
|
TEST_VIMRC:=tests/vim/vimrc
|
||||||
|
|
||||||
|
testwatch: override export VADER_OPTIONS+=-q |
||||||
|
testwatch: |
||||||
|
contrib/run-tests-watch
|
||||||
|
|
||||||
|
testwatchx: override export VADER_OPTIONS+=-x |
||||||
|
testwatchx: testwatch |
||||||
|
|
||||||
|
testx: override VADER_OPTIONS+=-x |
||||||
|
testx: test |
||||||
|
testnvimx: override VADER_OPTIONS+=-x |
||||||
|
testnvimx: testnvim |
||||||
|
testvimx: override VADER_OPTIONS+=-x |
||||||
|
testvimx: testvim |
||||||
|
|
||||||
|
# Set Neovim logfile destination to prevent `.nvimlog` being created.
|
||||||
|
testnvim: export NVIM_LOG_FILE:=/dev/stderr |
||||||
|
testnvim: TEST_VIM:=nvim |
||||||
|
testnvim: TEST_VIM_PREFIX+=VADER_OUTPUT_FILE=/dev/stderr |
||||||
|
testnvim: | build/vim-test-home $(DEP_PLUGINS) |
||||||
|
$(call func-run-vim)
|
||||||
|
|
||||||
|
testvim: TEST_VIM:=vim |
||||||
|
testvim: | build/vim-test-home $(DEP_PLUGINS) |
||||||
|
$(call func-run-vim)
|
||||||
|
|
||||||
|
# Add coloring to Vader's output:
|
||||||
|
# 1. failures (includes pending) in red "(X)"
|
||||||
|
# 2. test case header in bold "(2/2)"
|
||||||
|
# 3. Neomake's debug log messages in less intense grey
|
||||||
|
# 4. non-Neomake log lines (e.g. from :Log) in bold/bright yellow.
|
||||||
|
_SED_HIGHLIGHT_ERRORS:=| contrib/highlight-log --compact vader
|
||||||
|
# Need to close stdin to fix spurious 'sed: couldn't write X items to stdout: Resource temporarily unavailable'.
|
||||||
|
# NOTE: uses </dev/null instead of <&-, because Vim behaves different then:
|
||||||
|
# - test "Automake restarts if popup menu is visible" hangs (https://github.com/vim/vim/issues/1320)
|
||||||
|
# - running the command from "make testvim" directly (i.e. without "make")
|
||||||
|
# triggers half the screen to be cleared in the end
|
||||||
|
# Vim requires stdin to be closed for feedkeys to stay in insert mode, at
|
||||||
|
# least in Docker on CircleCI.
|
||||||
|
_REDIR_STDOUT:=2>&1 >/dev/null </dev/null
|
||||||
|
|
||||||
|
# Neovim needs a valid HOME (https://github.com/neovim/neovim/issues/5277).
|
||||||
|
# Vim hangs with /dev/null on Windows (native Vim via MSYS2).
|
||||||
|
TEST_VIM_PREFIX+=HOME=$(CURDIR)/build/vim-test-home
|
||||||
|
|
||||||
|
# Neovim might quit after ~5s with stdin being closed. Use --headless mode to
|
||||||
|
# work around this.
|
||||||
|
# > Vim: Error reading input, exiting...
|
||||||
|
# > Vim: Finished.
|
||||||
|
# For Vim `-s /dev/null` is used to skip the 2s delay with warning
|
||||||
|
# "Vim: Warning: Output is not to a terminal".
|
||||||
|
COVERAGE_FILE:=.coverage_covimerage
|
||||||
|
_COVIMERAGE=$(if $(filter-out 0,$(NEOMAKE_DO_COVERAGE)),covimerage run --data-file $(COVERAGE_FILE) --append --no-report ,)
|
||||||
|
define func-run-vim |
||||||
|
$(info Using: $(shell $(TEST_VIM_PREFIX) "$(TEST_VIM)" --version | head -n2))
|
||||||
|
($(_COVIMERAGE)$(if $(TEST_VIM_PREFIX),env $(TEST_VIM_PREFIX) ,)"$(TEST_VIM)" \
|
||||||
|
$(if $(IS_NEOVIM),$(if $(_REDIR_STDOUT),--headless,),-X $(if $(_REDIR_STDOUT),-s /dev/null,)) \
|
||||||
|
--noplugin -Nu $(TEST_VIMRC) -i NONE $(VIM_ARGS) $(_REDIR_STDOUT)) $(_SED_HIGHLIGHT_ERRORS)
|
||||||
|
endef |
||||||
|
|
||||||
|
# Interactive tests, keep Vader open.
|
||||||
|
_run_interactive: VADER:=Vader |
||||||
|
_run_interactive: _REDIR_STDOUT:= |
||||||
|
_run_interactive: |
||||||
|
$(call func-run-vim)
|
||||||
|
|
||||||
|
testvim_interactive: TEST_VIM:=vim -X |
||||||
|
testvim_interactive: _run_interactive |
||||||
|
|
||||||
|
testnvim_interactive: TEST_VIM:=nvim |
||||||
|
testnvim_interactive: _run_interactive |
||||||
|
|
||||||
|
|
||||||
|
# Manually invoke Vim, using the test setup. This helps with building tests.
|
||||||
|
runvim: VIM_ARGS:= |
||||||
|
runvim: testvim_interactive |
||||||
|
|
||||||
|
runnvim: VIM_ARGS:= |
||||||
|
runnvim: testnvim_interactive |
||||||
|
|
||||||
|
# Add targets for .vader files, absolute and relative.
|
||||||
|
# This can be used with `b:dispatch = ':Make %'` in Vim.
|
||||||
|
TESTS:=$(wildcard tests/*.vader tests/*/*.vader)
|
||||||
|
uniq = $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1)))
|
||||||
|
_TESTS_REL_AND_ABS:=$(call uniq,$(abspath $(TESTS)) $(TESTS))
|
||||||
|
FILE_TEST_TARGET=$(if $(IS_NEOVIM),testnvim,testvim)
|
||||||
|
$(_TESTS_REL_AND_ABS): |
||||||
|
$(MAKE) --no-print-directory $(FILE_TEST_TARGET) VADER_ARGS='$@'
|
||||||
|
.PHONY: $(_TESTS_REL_AND_ABS) |
||||||
|
|
||||||
|
testcoverage: COVERAGE_VADER_ARGS:=tests/main.vader $(wildcard tests/isolated/*.vader) |
||||||
|
testcoverage: |
||||||
|
$(RM) $(COVERAGE_FILE)
|
||||||
|
@ret=0; \
|
||||||
|
for testfile in $(COVERAGE_VADER_ARGS); do \
|
||||||
|
$(MAKE) --no-print-directory test VADER_ARGS=$$testfile NEOMAKE_DO_COVERAGE=1 || (( ++ret )); \
|
||||||
|
done; \
|
||||||
|
exit $$ret
|
||||||
|
|
||||||
|
tags: |
||||||
|
ctags -R --langmap=vim:+.vader
|
||||||
|
.PHONY: tags |
||||||
|
|
||||||
|
# Linters, called from .travis.yml.
|
||||||
|
LINT_ARGS:=./plugin ./autoload
|
||||||
|
|
||||||
|
# Vint.
|
||||||
|
VINT_BIN=$(shell command -v vint 2>/dev/null || echo build/vint/bin/vint)
|
||||||
|
build/vint: | build |
||||||
|
$(shell command -v virtualenv 2>/dev/null || echo python3 -m venv) $@
|
||||||
|
build/vint/bin/vint: | build/vint |
||||||
|
build/vint/bin/pip install --quiet vim-vint
|
||||||
|
vint: | $(VINT_BIN) |
||||||
|
$| --color $(LINT_ARGS)
|
||||||
|
vint-errors: | $(VINT_BIN) |
||||||
|
$| --color --error $(LINT_ARGS)
|
||||||
|
|
||||||
|
# vimlint
|
||||||
|
VIMLINT_BIN=$(shell command -v vimlint 2>/dev/null || echo build/vimlint/bin/vimlint.sh -l build/vimlint -p build/vimlparser)
|
||||||
|
build/vimlint/bin/vimlint.sh: build/vimlint build/vimlparser |
||||||
|
build/vimlint: | build |
||||||
|
git clone -q --depth=1 https://github.com/syngan/vim-vimlint $@
|
||||||
|
build/vimlparser: | build |
||||||
|
git clone -q --depth=1 https://github.com/ynkdir/vim-vimlparser $@
|
||||||
|
VIMLINT_OPTIONS=-u -e EVL102.l:_=1 -e 'EVL103.a:_.*=1'
|
||||||
|
vimlint: | $(firstword $(VIMLINT_BIN)) |
||||||
|
$(VIMLINT_BIN) $(VIMLINT_OPTIONS) $(LINT_ARGS)
|
||||||
|
vimlint-errors: | $(firstword VIMLINT_BIN) |
||||||
|
$(VIMLINT_BIN) $(VIMLINT_OPTIONS) -E $(LINT_ARGS)
|
||||||
|
|
||||||
|
build build/vim-test-home: |
||||||
|
mkdir $@
|
||||||
|
build/vim-test-home: | build |
||||||
|
build/vimhelplint: | build |
||||||
|
cd build \
|
||||||
|
&& wget -O- https://github.com/machakann/vim-vimhelplint/archive/master.tar.gz \
|
||||||
|
| tar xz \
|
||||||
|
&& mv vim-vimhelplint-master vimhelplint
|
||||||
|
vimhelplint: | $(if $(VIMHELPLINT_DIR),,build/vimhelplint) |
||||||
|
contrib/vimhelplint doc/neomake.txt
|
||||||
|
|
||||||
|
# Run tests in dockerized Vims.
|
||||||
|
DOCKER_REPO:=neomake/vims-for-tests
|
||||||
|
DOCKER_TAG:=47
|
||||||
|
NEOMAKE_DOCKER_IMAGE?=
|
||||||
|
DOCKER_IMAGE:=$(if $(NEOMAKE_DOCKER_IMAGE),$(NEOMAKE_DOCKER_IMAGE),$(DOCKER_REPO):$(DOCKER_TAG))
|
||||||
|
DOCKER_STREAMS:=-ti
|
||||||
|
DOCKER_ARGS:=
|
||||||
|
DOCKER=docker run $(DOCKER_STREAMS) --rm \
|
||||||
|
-v $(PWD):/testplugin \
|
||||||
|
-w /testplugin \
|
||||||
|
-e NEOMAKE_TEST_NO_COLORSCHEME \
|
||||||
|
$(DOCKER_ARGS) $(DOCKER_IMAGE)
|
||||||
|
docker_image: |
||||||
|
docker build -f Dockerfile.tests -t $(DOCKER_REPO):$(DOCKER_TAG) .
|
||||||
|
docker_push: |
||||||
|
docker push $(DOCKER_REPO):$(DOCKER_TAG)
|
||||||
|
docker_update_latest: |
||||||
|
docker tag $(DOCKER_REPO):$(DOCKER_TAG) $(DOCKER_REPO):latest
|
||||||
|
docker push $(DOCKER_REPO):latest
|
||||||
|
docker_update_image: |
||||||
|
@git diff --cached --exit-code >/dev/null || { echo "WARN: git index is not clean."; }
|
||||||
|
@if git diff --exit-code -- Makefile >/dev/null; then \
|
||||||
|
sed -i '/^DOCKER_TAG:=/s/:=.*/:=$(shell echo $$(($(DOCKER_TAG)+1)))/' Makefile; \
|
||||||
|
else \
|
||||||
|
echo "WARN: Makefile is not clean. Not updating."; \
|
||||||
|
fi
|
||||||
|
@if git diff --exit-code -- Dockerfile.tests >/dev/null; then \
|
||||||
|
sed -i '/^ENV NEOMAKE_DOCKERFILE_UPDATE=/s/=.*/=$(shell date +%Y-%m-%d)/' Dockerfile.tests; \
|
||||||
|
else \
|
||||||
|
echo "WARN: Dockerfile.tests is not clean. Not updating."; \
|
||||||
|
fi
|
||||||
|
make docker_image
|
||||||
|
make docker_test DOCKER_VIM=vim81
|
||||||
|
@echo "Done. Use 'make docker_push' to push it, and then update .circleci/config.yml."
|
||||||
|
|
||||||
|
DOCKER_VIMS:=vim73 vim74-trusty vim74-xenial vim80 vim81 \
|
||||||
|
neovim-v0.1.7 neovim-v0.3.8 neovim-master vim-master
|
||||||
|
_DOCKER_VIM_TARGETS:=$(addprefix docker_test-,$(DOCKER_VIMS))
|
||||||
|
|
||||||
|
docker_test_all: $(_DOCKER_VIM_TARGETS) |
||||||
|
|
||||||
|
$(_DOCKER_VIM_TARGETS): |
||||||
|
$(MAKE) docker_test DOCKER_VIM=$(patsubst docker_test-%,%,$@)
|
||||||
|
|
||||||
|
_docker_test: DOCKER_VIM:=vim81 |
||||||
|
_docker_test: DOCKER_MAKE_TARGET=$(DOCKER_MAKE_TEST_TARGET) \
|
||||||
|
TEST_VIM='/vim-build/bin/$(DOCKER_VIM)' \
|
||||||
|
VADER_OPTIONS="$(VADER_OPTIONS)" VADER_ARGS="$(VADER_ARGS)" \
|
||||||
|
_REDIR_STDOUT="$(_REDIR_STDOUT)" \
|
||||||
|
$(DOCKER_MAKE_TEST_ARGS)
|
||||||
|
_docker_test: docker_make |
||||||
|
docker_test: DOCKER_MAKE_TEST_TARGET:=test |
||||||
|
docker_test: DOCKER_STREAMS:=-t |
||||||
|
docker_test: _docker_test |
||||||
|
|
||||||
|
docker_test_interactive: DOCKER_MAKE_TEST_TARGET:=test_interactive |
||||||
|
docker_test_interactive: DOCKER_STREAMS:=-ti |
||||||
|
docker_test_interactive: _docker_test |
||||||
|
|
||||||
|
docker_testcoverage: DOCKER_MAKE_TEST_TARGET:=testcoverage |
||||||
|
# Pick up VADER_ARGS from command line for COVERAGE_VADER_ARGS.
|
||||||
|
docker_testcoverage: DOCKER_MAKE_TEST_ARGS:=$(if $(filter command line,$(origin COVERAGE_VADER_ARGS)),COVERAGE_VADER_ARGS="$(COVERAGE_VADER_ARGS)",$(if $(filter command line,$(origin VADER_ARGS)),COVERAGE_VADER_ARGS="$(VADER_ARGS)",)) |
||||||
|
docker_testcoverage: DOCKER_STREAMS:=-t |
||||||
|
docker_testcoverage: _docker_test |
||||||
|
sed -i 's~/testplugin/~$(CURDIR)/~g' $(COVERAGE_FILE)
|
||||||
|
coverage report -m
|
||||||
|
|
||||||
|
docker_run: DOCKER_ARGS:=-e PATH=/vim-build/bin/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin |
||||||
|
docker_run: $(DEP_PLUGINS) |
||||||
|
docker_run: |
||||||
|
$(DOCKER) $(if $(DOCKER_RUN),$(DOCKER_RUN),bash)
|
||||||
|
|
||||||
|
# Pass down/through MAKEFLAGS explicitly (not available in Docker env).
|
||||||
|
docker_make: DOCKER_RUN=$(MAKE) -$(MAKEFLAGS) $(DOCKER_MAKE_TARGET) |
||||||
|
docker_make: docker_run |
||||||
|
|
||||||
|
docker_check: DOCKER_MAKE_TARGET=check_docker |
||||||
|
docker_check: docker_make |
||||||
|
|
||||||
|
docker_vimhelplint: |
||||||
|
$(MAKE) docker_make DOCKER_MAKE_TARGET=vimhelplint
|
||||||
|
|
||||||
|
_ECHO_DOCKER_VIMS:=ls /vim-build/bin | grep vim | sort
|
||||||
|
docker_list_vims: |
||||||
|
docker run --rm $(DOCKER_IMAGE) $(_ECHO_DOCKER_VIMS)
|
||||||
|
|
||||||
|
check_lint_diff: |
||||||
|
@# NOTE: does not see changed files for builds on master.
|
||||||
|
@set -e; \
|
||||||
|
echo "Looking for changed files (to origin/master)."; \
|
||||||
|
CHANGED_VIM_FILES=($$(git diff-tree --no-commit-id --name-only --diff-filter=AM -r origin/master.. \
|
||||||
|
| grep '\.vim$$' | grep -v '^tests/fixtures')) || true; \
|
||||||
|
ret=0; \
|
||||||
|
if [ "$${#CHANGED_VIM_FILES[@]}" -eq 0 ]; then \
|
||||||
|
echo 'No .vim files changed.'; \
|
||||||
|
else \
|
||||||
|
MAKE_ARGS="LINT_ARGS=$${CHANGED_VIM_FILES[*]}"; \
|
||||||
|
echo "== Running \"make vimlint $$MAKE_ARGS\" =="; \
|
||||||
|
$(MAKE) --no-print-directory vimlint "$$MAKE_ARGS" || (( ret+=1 )); \
|
||||||
|
echo "== Running \"make vint $$MAKE_ARGS\" =="; \
|
||||||
|
$(MAKE) --no-print-directory vint "$$MAKE_ARGS" || (( ret+=2 )); \
|
||||||
|
fi; \
|
||||||
|
if ! git diff-tree --quiet --exit-code --diff-filter=AM -r origin/master.. -- doc/neomake.txt; then \
|
||||||
|
echo "== Running \"make vimhelplint\" for changed doc/neomake.txt =="; \
|
||||||
|
$(MAKE) --no-print-directory vimhelplint || (( ret+=4 )); \
|
||||||
|
fi; \
|
||||||
|
exit $$ret
|
||||||
|
|
||||||
|
check_lint: vimlint vint vimhelplint |
||||||
|
|
||||||
|
# Checks to be run within the Docker image.
|
||||||
|
check_docker: |
||||||
|
@:; set -e; ret=0; \
|
||||||
|
echo '== Checking for DOCKER_VIMS to be in sync'; \
|
||||||
|
vims=$$($(_ECHO_DOCKER_VIMS)); \
|
||||||
|
docker_vims="$$(printf '%s\n' $(DOCKER_VIMS) | sort)"; \
|
||||||
|
if ! [ "$$vims" = "$$docker_vims" ]; then \
|
||||||
|
echo "DOCKER_VIMS is out of sync with Vims in image."; \
|
||||||
|
diff <(echo "$$vims") <(echo "$$docker_vims"); \
|
||||||
|
(( ret+=8 )); \
|
||||||
|
fi; \
|
||||||
|
exit $$ret
|
||||||
|
|
||||||
|
# Like CircleCI runs them.
|
||||||
|
check_in_docker: DOCKER_MAKE_TARGET=checkqa |
||||||
|
check_in_docker: docker_make |
||||||
|
|
||||||
|
# Run in CircleCI.
|
||||||
|
checkqa: |
||||||
|
$(MAKE) -k check check_docker check_lint_diff
|
||||||
|
|
||||||
|
check: |
||||||
|
@:; set -e; ret=0; \
|
||||||
|
[ $$TERM = dumb ] && export TERM=xterm; \
|
||||||
|
echo_bold() { tput bold; echo "$$@"; tput sgr0; }; \
|
||||||
|
echo '== Checking that all tests are included'; \
|
||||||
|
for f in $(filter-out all.vader main.vader isolated.vader,$(notdir $(shell git ls-files tests/*.vader))); do \
|
||||||
|
if ! grep -q "^Include.*: $$f" tests/main.vader; then \
|
||||||
|
echo_bold "Test not included in main.vader: $$f" >&2; ret=1; \
|
||||||
|
fi; \
|
||||||
|
done; \
|
||||||
|
for f in $(notdir $(shell git ls-files tests/isolated/*.vader)); do \
|
||||||
|
if ! grep -q "^Include.*: isolated/$$f" tests/isolated.vader; then \
|
||||||
|
echo_bold "Test not included in isolated.vader: $$f" >&2; ret=1; \
|
||||||
|
fi; \
|
||||||
|
done; \
|
||||||
|
echo '== Checking for absent Before sections in tests'; \
|
||||||
|
if grep '^Before:' tests/*.vader; then \
|
||||||
|
echo_bold "Before: should not be used in tests itself, because it overrides the global one."; \
|
||||||
|
(( ret+=2 )); \
|
||||||
|
fi; \
|
||||||
|
echo '== Checking for absent :Log calls'; \
|
||||||
|
if git --no-pager grep --line-number --color --perl-regexp '^(\s*au.*\b)?\s*Log\b' \
|
||||||
|
-- :^tests/include/init.vim :^tests/include/setup.vader; then \
|
||||||
|
echo_bold "Found Log commands."; \
|
||||||
|
(( ret+=4 )); \
|
||||||
|
fi; \
|
||||||
|
echo '== Checking tests'; \
|
||||||
|
output="$$(grep --line-number --color AssertThrows -A1 tests/*.vader)"; \
|
||||||
|
output="$(echo "$$output" \
|
||||||
|
| grep -E '^[^[:space:]]+- ' \
|
||||||
|
| grep -v g:vader_exception | sed -e s/-/:/ -e s/-// || true)"; \
|
||||||
|
if [[ -n "$$output" ]]; then \
|
||||||
|
echo_bold 'AssertThrows used without checking g:vader_exception:' >&2; \
|
||||||
|
echo "$$output" >&2; \
|
||||||
|
(( ret+=16 )); \
|
||||||
|
fi; \
|
||||||
|
echo '== Running custom checks'; \
|
||||||
|
tput bold; \
|
||||||
|
contrib/vim-checks $(LINT_ARGS) || (( ret+= 16 )); \
|
||||||
|
tput sgr0; \
|
||||||
|
exit $$ret
|
||||||
|
|
||||||
|
NEOMAKE_LOG:=/tmp/neomake.log
|
||||||
|
tail_log: |
||||||
|
fifo=$(shell mktemp -u); \
|
||||||
|
mkfifo $$fifo; \
|
||||||
|
tail -f $(NEOMAKE_LOG) \
|
||||||
|
| $(CURDIR)/contrib/highlight-log >> $$fifo & \
|
||||||
|
less --force --chop-long-lines +F $$fifo
|
||||||
|
|
||||||
|
clean: |
||||||
|
$(RM) -r build
|
||||||
|
.PHONY: clean |
||||||
|
|
||||||
|
# Fixtures {{{
|
||||||
|
|
||||||
|
# A function to define targets/rules for fixture generation.
|
||||||
|
# Args:
|
||||||
|
# 1: the tool (bin) and input/output dir.
|
||||||
|
# 2: arguments for the tool
|
||||||
|
# NOTE: uses "sed -i.bak" for MacOS's default sed.
|
||||||
|
define func-generate-fixture |
||||||
|
tests/fixtures/output/$1: |
||||||
|
mkdir -p $$@
|
||||||
|
tests/fixtures/output/$1/%.stderr tests/fixtures/output/$1/%.stdout tests/fixtures/output/$1/%.exitcode: tests/fixtures/input/$1/% | tests/fixtures/output/$1 |
||||||
|
@baseout=tests/fixtures/output/$1/$$*; \
|
||||||
|
echo "Generating $$$$baseout"; \
|
||||||
|
$1 $2 $$< >$$$$baseout.stdout 2>$$$$baseout.stderr; \
|
||||||
|
ret=$$$$?; \
|
||||||
|
printf $$$$ret > $$$$baseout.exitcode; \
|
||||||
|
if ! [ -f $$$$baseout.stdout ]; then \
|
||||||
|
echo "Missing output: $$$$baseout.stdout." >&2; exit 1; \
|
||||||
|
fi; \
|
||||||
|
sed -i.bak -e "s~$(CURDIR)/~/tmp/neomake-tests/~g" \
|
||||||
|
$$$$baseout.stdout $$$$baseout.stderr; \
|
||||||
|
$(RM) $$$$baseout.stdout.bak $$$$baseout.stderr.bak
|
||||||
|
endef |
||||||
|
|
||||||
|
# Call and eval the above function to generate rules for different tools.
|
||||||
|
$(eval $(call func-generate-fixture,puppet,parser validate --color=false)) |
||||||
|
$(eval $(call func-generate-fixture,puppet-lint,--log-format "%{path}:%{line}:%{column}:%{kind}:[%{check}] %{message}")) |
||||||
|
$(eval $(call func-generate-fixture,xmllint,--xinclude --postvalid --noout)) |
||||||
|
$(eval $(call func-generate-fixture,zsh,-n)) |
||||||
|
|
||||||
|
_FIXTURES_INPUT:=$(wildcard tests/fixtures/input/*/*)
|
||||||
|
_FIXTURES_OUTPUT:=$(patsubst tests/fixtures/input/%,tests/fixtures/output/%,$(addsuffix .stdout,$(_FIXTURES_INPUT)) $(addsuffix .stderr,$(_FIXTURES_INPUT)))
|
||||||
|
|
||||||
|
fixtures: $(_FIXTURES_OUTPUT) |
||||||
|
.PHONY: fixtures |
||||||
|
|
||||||
|
fixtures-rebuild: |
||||||
|
$(RM) tests/fixtures/output/*/*.stdout tests/fixtures/output/*/*.stderr
|
||||||
|
$(MAKE) --keep-going fixtures
|
||||||
|
.PHONY: fixtures-rebuild |
||||||
|
# }}}
|
||||||
|
|
||||||
|
.PHONY: vint vint-errors vimlint vimlint-errors |
||||||
|
.PHONY: test testnvim testvim testnvim_interactive testvim_interactive |
||||||
|
.PHONY: runvim runnvim tags _run_tests |
@ -0,0 +1,188 @@ |
|||||||
|
# [](#neomake) |
||||||
|
|
||||||
|
[](https://circleci.com/gh/neomake/neomake) |
||||||
|
[](https://codecov.io/gh/neomake/neomake) |
||||||
|
[](https://coveralls.io/github/neomake/neomake) |
||||||
|
|
||||||
|
Neomake is a plugin for [Vim]/[Neovim] to asynchronously run programs. |
||||||
|
|
||||||
|
You can use it instead of the built-in `:make` command (since it can pick |
||||||
|
up your `'makeprg'` setting), but its focus is on providing an extra layer |
||||||
|
of makers based on the current file (type) or project. |
||||||
|
Its origin is a proof-of-concept for [Syntastic] to be asynchronous. |
||||||
|
|
||||||
|
## Requirements |
||||||
|
|
||||||
|
### Neovim |
||||||
|
|
||||||
|
With Neovim any release will do (after 0.0.0-alpha+201503292107). |
||||||
|
|
||||||
|
### Vim |
||||||
|
|
||||||
|
The minimal Vim version supported by Neomake is 7.4.503 (although if you don't |
||||||
|
use `g:neomake_logfile` older versions will probably work fine as well). |
||||||
|
|
||||||
|
You need Vim 8.0.0027 or later for asynchronous features. |
||||||
|
|
||||||
|
## Installation |
||||||
|
|
||||||
|
Use your preferred installation method for Vim plugins. |
||||||
|
|
||||||
|
With [vim-plug](https://github.com/junegunn/vim-plug) that would mean to add |
||||||
|
the following to your vimrc: |
||||||
|
|
||||||
|
```vim |
||||||
|
Plug 'neomake/neomake' |
||||||
|
``` |
||||||
|
|
||||||
|
## Setup |
||||||
|
|
||||||
|
If you want to run Neomake automatically (in file mode), you can configure it |
||||||
|
in your `vimrc` by using `neomake#configure#automake`, e.g. by picking one of: |
||||||
|
|
||||||
|
```vim |
||||||
|
" When writing a buffer (no delay). |
||||||
|
call neomake#configure#automake('w') |
||||||
|
" When writing a buffer (no delay), and on normal mode changes (after 750ms). |
||||||
|
call neomake#configure#automake('nw', 750) |
||||||
|
" When reading a buffer (after 1s), and when writing (no delay). |
||||||
|
call neomake#configure#automake('rw', 1000) |
||||||
|
" Full config: when writing or reading a buffer, and on changes in insert and |
||||||
|
" normal mode (after 1s; no delay when writing). |
||||||
|
call neomake#configure#automake('nrwi', 500) |
||||||
|
``` |
||||||
|
|
||||||
|
(Any function calls like these need to come after indicating the end of plugins |
||||||
|
to your plugin manager, e.g. after `call plug#end()` with vim-plug.) |
||||||
|
|
||||||
|
### Advanced setup |
||||||
|
|
||||||
|
The author liked to use the following, which uses different modes based on if |
||||||
|
your laptop runs on battery (for MacOS or Linux): |
||||||
|
|
||||||
|
```vim |
||||||
|
function! MyOnBattery() |
||||||
|
if has('macunix') |
||||||
|
return match(system('pmset -g batt'), "Now drawing from 'Battery Power'") != -1 |
||||||
|
elsif has('unix') |
||||||
|
return readfile('/sys/class/power_supply/AC/online') == ['0'] |
||||||
|
endif |
||||||
|
return 0 |
||||||
|
endfunction |
||||||
|
|
||||||
|
if MyOnBattery() |
||||||
|
call neomake#configure#automake('w') |
||||||
|
else |
||||||
|
call neomake#configure#automake('nw', 1000) |
||||||
|
endif |
||||||
|
``` |
||||||
|
|
||||||
|
See `:help neomake-automake` (in [doc/neomake.txt](doc/neomake.txt)) for more |
||||||
|
information, e.g. how to configure it based on certain autocommands explicitly, |
||||||
|
and for details about which events get used for the different string-based |
||||||
|
modes. |
||||||
|
|
||||||
|
## Usage |
||||||
|
|
||||||
|
When calling `:Neomake` manually (or automatically through |
||||||
|
`neomake#configure#automake` (see above)) it will populate the window's |
||||||
|
location list with any issues that get reported by the maker(s). |
||||||
|
|
||||||
|
You can then navigate them using the built-in methods like `:lwindow` / |
||||||
|
`:lopen` (to view the list) and `:lprev` / `:lnext` to go back and forth. |
||||||
|
|
||||||
|
You can configure Neomake to open the list automatically: |
||||||
|
|
||||||
|
```vim |
||||||
|
let g:neomake_open_list = 2 |
||||||
|
``` |
||||||
|
|
||||||
|
Please refer to [`:help neomake.txt`] for more details on configuration. |
||||||
|
|
||||||
|
### Maker types |
||||||
|
|
||||||
|
There are two types of makers: file makers (acting on the current buffer) and |
||||||
|
project makers (acting globally). |
||||||
|
|
||||||
|
You invoke file makers using `:Neomake`, and project makers using `:Neomake!`. |
||||||
|
|
||||||
|
See [`:help neomake.txt`] for more details. |
||||||
|
|
||||||
|
### Manually run a maker |
||||||
|
|
||||||
|
You can run a specific maker on the current file by specifying the maker's |
||||||
|
name, e.g. `:Neomake jshint` (you can use Vim's completion here to complete |
||||||
|
maker names). |
||||||
|
|
||||||
|
## Default makers |
||||||
|
|
||||||
|
For a list of default makers please see the |
||||||
|
[Makers page in the wiki](https://github.com/neomake/neomake/wiki/Makers). |
||||||
|
|
||||||
|
# Contributing |
||||||
|
|
||||||
|
If you find this plugin useful, please contribute your maker recipes to the |
||||||
|
repository! Check out `autoload/neomake/makers/**/*.vim` for existing makers. |
||||||
|
|
||||||
|
This is a community driven project, and maintainers are wanted. |
||||||
|
Please contact [@blueyed](https://github.com/blueyed) if you are interested. |
||||||
|
You should have a good profile of issue triaging and PRs on this repo already. |
||||||
|
|
||||||
|
## Hacking / Testing |
||||||
|
|
||||||
|
We are using [Vader](https://github.com/junegunn/vader.vim) for our tests. |
||||||
|
|
||||||
|
### Logging |
||||||
|
|
||||||
|
Set `let g:neomake_logfile = '/tmp/neomake.log'` (dynamically or in your vimrc) |
||||||
|
to enable debug logging to the given file. |
||||||
|
From Neomake's source tree you can then run `make tail_log`, which will color |
||||||
|
the output and pipe it into `less`, which folds long lines by default and will |
||||||
|
follow the output (like `tail -f`). |
||||||
|
You can use Ctrl-C to interrupt for scrolling etc, and then F to follow again. |
||||||
|
|
||||||
|
### Running tests |
||||||
|
|
||||||
|
#### Run all tests against your local Neovim and Vim |
||||||
|
|
||||||
|
make test |
||||||
|
|
||||||
|
#### Run a specific test file |
||||||
|
|
||||||
|
make tests/integration.vader |
||||||
|
|
||||||
|
#### Run some specific tests for Vim |
||||||
|
|
||||||
|
make testvim VADER_ARGS=tests/integration.vader |
||||||
|
|
||||||
|
### Dockerized tests |
||||||
|
|
||||||
|
The `docker_test` target runs tests for a specific Vim version. |
||||||
|
See `Dockerfile.tests` for the Vim versions provided in the Docker image. |
||||||
|
|
||||||
|
The image for this gets pulled from Docker Hub via |
||||||
|
[neomake/vims-for-tests](https://hub.docker.com/r/neomake/vims-for-tests/). |
||||||
|
|
||||||
|
NOTE: the Docker image used for tests does not include (different versions) |
||||||
|
of Neovim at the moment. |
||||||
|
|
||||||
|
#### Run all tests for Vim 8.0.586 |
||||||
|
|
||||||
|
make docker_test DOCKER_VIM=vim-8.0.586 |
||||||
|
|
||||||
|
#### Run all tests against all Vims in the Docker image |
||||||
|
|
||||||
|
make docker_test_all |
||||||
|
|
||||||
|
## Donate |
||||||
|
|
||||||
|
* Bitcoin: 1JscK5VaHyBhdE2ayVr63hDc6Mx94m9Y7R |
||||||
|
* Flattr: []( |
||||||
|
https://flattr.com/submit/auto?user_id=blueyed&url=https://github.com/neomake/neomake&title=Neomake&language=en_GB&tags=github&category=software) |
||||||
|
|
||||||
|
[Neovim]: http://neovim.org/ |
||||||
|
[Vim]: http://vim.org/ |
||||||
|
[Syntastic]: https://github.com/scrooloose/syntastic |
||||||
|
[cargo]: https://github.com/neomake/neomake/blob/master/autoload/neomake/makers/cargo.vim |
||||||
|
[mvn]: https://github.com/neomake/neomake/blob/master/autoload/neomake/makers/mvn.vim |
||||||
|
[`:help neomake.txt`]: doc/neomake.txt |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,307 @@ |
|||||||
|
if !exists('s:action_queue') |
||||||
|
let s:action_queue = [] |
||||||
|
endif |
||||||
|
if !exists('s:action_queue_registered_events') |
||||||
|
let s:action_queue_registered_events = [] |
||||||
|
endif |
||||||
|
let s:action_queue_timer_timeouts = get(g:, 'neomake_action_queue_timeouts', {1: 100, 2: 200, 3: 500}) |
||||||
|
|
||||||
|
let g:neomake#action_queue#processed = {} |
||||||
|
let g:neomake#action_queue#not_processed = {} |
||||||
|
let g:neomake#action_queue#any_event = [] |
||||||
|
|
||||||
|
let g:neomake#action_queue#_s = s: |
||||||
|
|
||||||
|
function! s:actionname(funcref) abort |
||||||
|
let s = string(a:funcref) |
||||||
|
let r = matchstr(s, '\v^^function\(''\zs.*\ze''\)$') |
||||||
|
if empty(r) |
||||||
|
return s |
||||||
|
endif |
||||||
|
return substitute(r, '\v^(\<SNR\>\d+_|s:)', '', '') |
||||||
|
endfunction |
||||||
|
|
||||||
|
" Queue an action to be processed later for autocmd a:event or through a timer |
||||||
|
" for a:event=Timer. |
||||||
|
" It will call a:data[0], with a:data[1] as args (where the first should be |
||||||
|
" a jobinfo object). The callback should return 1 if it was successful, |
||||||
|
" with 0 it will be re-queued. |
||||||
|
" When called recursively (queuing the same event/data again, it will be |
||||||
|
" re-queued also). |
||||||
|
function! neomake#action_queue#add(events, data) abort |
||||||
|
let job_or_make_info = a:data[1][0] |
||||||
|
if a:events is# g:neomake#action_queue#any_event |
||||||
|
call neomake#log#debug(printf('Queuing action %s for any event.', |
||||||
|
\ s:actionname(a:data[0])), job_or_make_info) |
||||||
|
else |
||||||
|
call neomake#log#debug(printf('Queuing action %s for %s.', |
||||||
|
\ s:actionname(a:data[0]), join(a:events, ', ')), job_or_make_info) |
||||||
|
endif |
||||||
|
|
||||||
|
for event in a:events |
||||||
|
if event ==# 'Timer' |
||||||
|
if !has_key(job_or_make_info, 'action_queue_timer_tries') |
||||||
|
let job_or_make_info.action_queue_timer_tries = {'count': 1, 'data': a:data[0]} |
||||||
|
else |
||||||
|
let job_or_make_info.action_queue_timer_tries.count += 1 |
||||||
|
endif |
||||||
|
if has_key(s:action_queue_timer_timeouts, job_or_make_info.action_queue_timer_tries.count) |
||||||
|
let timeout = s:action_queue_timer_timeouts[job_or_make_info.action_queue_timer_tries.count] |
||||||
|
else |
||||||
|
throw printf('Neomake: Giving up handling Timer callbacks after %d attempts. Please report this. See :messages for more information.', len(s:action_queue_timer_timeouts)) |
||||||
|
endif |
||||||
|
if has('timers') |
||||||
|
if exists('s:action_queue_timer') |
||||||
|
call timer_stop(s:action_queue_timer) |
||||||
|
endif |
||||||
|
let s:action_queue_timer = timer_start(timeout, function('s:process_action_queue_timer_cb')) |
||||||
|
call neomake#log#debug(printf( |
||||||
|
\ 'Retrying Timer event in %dms (timer %d).', |
||||||
|
\ timeout, s:action_queue_timer), job_or_make_info) |
||||||
|
else |
||||||
|
call neomake#log#debug('Retrying Timer event on CursorHold(I).', job_or_make_info) |
||||||
|
if !exists('#neomake_event_queue#CursorHold') |
||||||
|
let s:action_queue_registered_events += ['CursorHold', 'CursorHoldI'] |
||||||
|
augroup neomake_event_queue |
||||||
|
exe 'autocmd CursorHold,CursorHoldI * call s:process_action_queue('''.event.''')' |
||||||
|
augroup END |
||||||
|
endif |
||||||
|
endif |
||||||
|
else |
||||||
|
if !exists('#neomake_event_queue#'.event) |
||||||
|
let s:action_queue_registered_events += [event] |
||||||
|
augroup neomake_event_queue |
||||||
|
exe 'autocmd '.event.' * call s:process_action_queue('''.event.''')' |
||||||
|
augroup END |
||||||
|
endif |
||||||
|
endif |
||||||
|
endfor |
||||||
|
call add(s:action_queue, [a:events, a:data]) |
||||||
|
return g:neomake#action_queue#not_processed |
||||||
|
endfunction |
||||||
|
|
||||||
|
" Remove any queued actions for a jobinfo or make_info object. |
||||||
|
function! neomake#action_queue#clean(job_or_make_info) abort |
||||||
|
let len_before = len(s:action_queue) |
||||||
|
call filter(s:action_queue, 'v:val[1][1][0] != a:job_or_make_info') |
||||||
|
let removed = len_before - len(s:action_queue) |
||||||
|
if removed |
||||||
|
call s:clean_action_queue_events() |
||||||
|
call neomake#log#debug(printf( |
||||||
|
\ 'Removed %d action queue entries.', |
||||||
|
\ removed), a:job_or_make_info) |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
|
||||||
|
" Remove given action for a jobinfo or make_info object. |
||||||
|
function! neomake#action_queue#remove(job_or_make_info, action) abort |
||||||
|
let len_before = len(s:action_queue) |
||||||
|
call filter(s:action_queue, 'v:val[1][1][0] != a:job_or_make_info || v:val[1][0] != a:action') |
||||||
|
let removed = len_before - len(s:action_queue) |
||||||
|
if removed |
||||||
|
call s:clean_action_queue_events() |
||||||
|
call neomake#log#debug(printf( |
||||||
|
\ 'Removed %d action queue entries for %s.', |
||||||
|
\ removed, s:actionname(a:action)), a:job_or_make_info) |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:process_action_queue_timer_cb(...) abort |
||||||
|
call neomake#log#debug(printf( |
||||||
|
\ 'action queue: callback for Timer queue (%d).', s:action_queue_timer)) |
||||||
|
unlet s:action_queue_timer |
||||||
|
call s:process_action_queue('Timer') |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:process_action_queue(event) abort |
||||||
|
let queue = s:action_queue |
||||||
|
let q_for_this_event = [] |
||||||
|
let i = 0 |
||||||
|
if g:neomake#core#_ignore_autocommands |
||||||
|
call neomake#log#debug(printf('action queue: skip processing for %s (ignore_autocommands=%d).', |
||||||
|
\ a:event, g:neomake#core#_ignore_autocommands), |
||||||
|
\ {'bufnr': bufnr('%'), 'winnr': winnr()}) |
||||||
|
return |
||||||
|
endif |
||||||
|
for [events, v] in queue |
||||||
|
if index(events, a:event) != -1 || events is# g:neomake#action_queue#any_event |
||||||
|
call add(q_for_this_event, [i, v]) |
||||||
|
endif |
||||||
|
let i += 1 |
||||||
|
endfor |
||||||
|
call neomake#log#debug(printf('action queue: processing for %s (%d items).', |
||||||
|
\ a:event, len(q_for_this_event)), {'bufnr': bufnr('%'), 'winnr': winnr()}) |
||||||
|
|
||||||
|
let processed = [] |
||||||
|
let removed = 0 |
||||||
|
let stop_processing = {'make_id': [], 'job_id': []} |
||||||
|
for [idx_q_for_this_event, data] in q_for_this_event |
||||||
|
let job_or_make_info = data[1][0] |
||||||
|
let current_event = remove(queue, idx_q_for_this_event - removed) |
||||||
|
let removed += 1 |
||||||
|
|
||||||
|
let make_id_job_id = {} " make_id/job_id relevant to re-queue following. |
||||||
|
if has_key(job_or_make_info, 'make_id') |
||||||
|
if has_key(job_or_make_info, 'options') |
||||||
|
let make_id_job_id = { |
||||||
|
\ 'make_id': job_or_make_info.make_id, |
||||||
|
\ } |
||||||
|
else |
||||||
|
let make_id_job_id = { |
||||||
|
\ 'make_id': job_or_make_info.make_id, |
||||||
|
\ 'job_id': job_or_make_info.id, |
||||||
|
\ } |
||||||
|
endif |
||||||
|
endif |
||||||
|
|
||||||
|
" Skip/re-queue entries for same make/job. |
||||||
|
let skip = 0 |
||||||
|
for [prop_name, prop_value] in items(make_id_job_id) |
||||||
|
if index(stop_processing[prop_name], prop_value) != -1 |
||||||
|
call neomake#log#debug(printf('action queue: skipping %s for not processed %s.', |
||||||
|
\ s:actionname(data[0]), prop_name), job_or_make_info) |
||||||
|
call add(queue, current_event) |
||||||
|
let skip = 1 |
||||||
|
break |
||||||
|
endif |
||||||
|
endfor |
||||||
|
if skip |
||||||
|
continue |
||||||
|
endif |
||||||
|
|
||||||
|
call neomake#log#debug(printf('action queue: calling %s.', |
||||||
|
\ s:actionname(data[0])), job_or_make_info) |
||||||
|
let queue_before_call = copy(queue) |
||||||
|
try |
||||||
|
" Call the queued action. On failure they should have requeued |
||||||
|
" themselves already. |
||||||
|
let rv = call(data[0], data[1]) |
||||||
|
catch |
||||||
|
if v:exception =~# '^Neomake: ' |
||||||
|
let error = substitute(v:exception, '^Neomake: ', '', '') |
||||||
|
else |
||||||
|
let error = printf('Error during action queue processing: %s.', |
||||||
|
\ v:exception) |
||||||
|
endif |
||||||
|
call neomake#log#exception(error, job_or_make_info) |
||||||
|
|
||||||
|
" Cancel job in case its action failed to get re-queued after X |
||||||
|
" attempts. |
||||||
|
if has_key(job_or_make_info, 'id') |
||||||
|
call neomake#CancelJob(job_or_make_info.id) |
||||||
|
endif |
||||||
|
continue |
||||||
|
endtry |
||||||
|
if rv is# g:neomake#action_queue#processed |
||||||
|
let processed += [data] |
||||||
|
continue |
||||||
|
endif |
||||||
|
|
||||||
|
if rv is# g:neomake#action_queue#not_processed |
||||||
|
if a:event !=# 'Timer' && has_key(job_or_make_info, 'action_queue_timer_tries') |
||||||
|
call neomake#log#debug('s:process_action_queue: decrementing timer tries for non-Timer event.', job_or_make_info) |
||||||
|
let job_or_make_info.action_queue_timer_tries.count -= 1 |
||||||
|
endif |
||||||
|
|
||||||
|
" Requeue any entries for the same job. |
||||||
|
let i = 0 |
||||||
|
for q in queue_before_call |
||||||
|
for [prop_name, prop_value] in items(make_id_job_id) |
||||||
|
" Assert current_event != q |
||||||
|
if get(q[1][1][0], prop_name) == prop_value |
||||||
|
call neomake#log#debug(printf('action queue: re-queuing %s for not processed %s.', |
||||||
|
\ s:actionname(q[1][0]), prop_name), job_or_make_info) |
||||||
|
call add(queue, remove(queue, i)) |
||||||
|
let i -= 1 |
||||||
|
break |
||||||
|
endif |
||||||
|
endfor |
||||||
|
let i += 1 |
||||||
|
endfor |
||||||
|
for [prop_name, prop_value] in items(make_id_job_id) |
||||||
|
call add(stop_processing[prop_name], prop_value) |
||||||
|
endfor |
||||||
|
else |
||||||
|
let args_str = neomake#utils#Stringify(data[1]) |
||||||
|
throw printf('Internal Neomake error: hook function %s(%s) returned unexpected value (%s)', data[0], args_str, rv) |
||||||
|
endif |
||||||
|
endfor |
||||||
|
call neomake#log#debug(printf('action queue: processed %d items.', |
||||||
|
\ len(processed)), {'bufnr': bufnr('%')}) |
||||||
|
|
||||||
|
call s:clean_action_queue_events() |
||||||
|
endfunction |
||||||
|
|
||||||
|
if has('timers') |
||||||
|
function! s:get_left_events() abort |
||||||
|
let r = {} |
||||||
|
for [events, _] in s:action_queue |
||||||
|
for event in events |
||||||
|
let r[event] = 1 |
||||||
|
endfor |
||||||
|
endfor |
||||||
|
return keys(r) |
||||||
|
endfunction |
||||||
|
else |
||||||
|
function! s:get_left_events() abort |
||||||
|
let r = {} |
||||||
|
for [events, _] in s:action_queue |
||||||
|
for event in events |
||||||
|
if event ==# 'Timer' |
||||||
|
let r['CursorHold'] = 1 |
||||||
|
let r['CursorHoldI'] = 1 |
||||||
|
else |
||||||
|
let r[event] = 1 |
||||||
|
endif |
||||||
|
endfor |
||||||
|
endfor |
||||||
|
return keys(r) |
||||||
|
endfunction |
||||||
|
endif |
||||||
|
|
||||||
|
function! neomake#action_queue#get_queued_actions(jobinfo) abort |
||||||
|
" Check if there are any queued actions for this job. |
||||||
|
let queued_actions = [] |
||||||
|
for [events, v] in s:action_queue |
||||||
|
if v[1][0] == a:jobinfo |
||||||
|
let queued_actions += [[s:actionname(v[0]), events]] |
||||||
|
endif |
||||||
|
endfor |
||||||
|
return queued_actions |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:clean_action_queue_events() abort |
||||||
|
let left_events = s:get_left_events() |
||||||
|
|
||||||
|
if empty(left_events) |
||||||
|
if exists('#neomake_event_queue') |
||||||
|
autocmd! neomake_event_queue |
||||||
|
augroup! neomake_event_queue |
||||||
|
endif |
||||||
|
else |
||||||
|
let clean_events = [] |
||||||
|
for event in s:action_queue_registered_events |
||||||
|
if index(left_events, event) == -1 |
||||||
|
let clean_events += [event] |
||||||
|
endif |
||||||
|
endfor |
||||||
|
if !empty(clean_events) |
||||||
|
augroup neomake_event_queue |
||||||
|
for event in clean_events |
||||||
|
if exists('#neomake_event_queue#'.event) |
||||||
|
exe 'au! '.event |
||||||
|
endif |
||||||
|
endfor |
||||||
|
augroup END |
||||||
|
endif |
||||||
|
endif |
||||||
|
let s:action_queue_registered_events = left_events |
||||||
|
|
||||||
|
if index(left_events, 'Timer') == -1 |
||||||
|
if exists('s:action_queue_timer') |
||||||
|
call timer_stop(s:action_queue_timer) |
||||||
|
unlet s:action_queue_timer |
||||||
|
endif |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
" vim: ts=4 sw=4 et |
@ -0,0 +1,322 @@ |
|||||||
|
" Compatibility wrappers for different (Neo)Vim versions and platforms. |
||||||
|
|
||||||
|
if neomake#utils#IsRunningWindows() |
||||||
|
let g:neomake#compat#dev_null = 'NUL' |
||||||
|
else |
||||||
|
let g:neomake#compat#dev_null = '/dev/null' |
||||||
|
endif |
||||||
|
|
||||||
|
if v:version >= 704 |
||||||
|
function! neomake#compat#getbufvar(buf, key, def) abort |
||||||
|
return getbufvar(a:buf, a:key, a:def) |
||||||
|
endfunction |
||||||
|
function! neomake#compat#getwinvar(win, key, def) abort |
||||||
|
return getwinvar(a:win, a:key, a:def) |
||||||
|
endfunction |
||||||
|
else |
||||||
|
function! neomake#compat#getbufvar(buf, key, def) abort |
||||||
|
return get(getbufvar(a:buf, ''), a:key, a:def) |
||||||
|
endfunction |
||||||
|
function! neomake#compat#getwinvar(win, key, def) abort |
||||||
|
return get(getwinvar(a:win, ''), a:key, a:def) |
||||||
|
endfunction |
||||||
|
endif |
||||||
|
|
||||||
|
unlockvar neomake#compat#json_true |
||||||
|
unlockvar neomake#compat#json_false |
||||||
|
unlockvar neomake#compat#json_null |
||||||
|
unlockvar neomake#compat#json_none |
||||||
|
|
||||||
|
if exists('v:none') |
||||||
|
let neomake#compat#json_none = v:none |
||||||
|
else |
||||||
|
let neomake#compat#json_none = [] |
||||||
|
endif |
||||||
|
|
||||||
|
if exists('*json_decode') |
||||||
|
let neomake#compat#json_true = v:true |
||||||
|
let neomake#compat#json_false = v:false |
||||||
|
let neomake#compat#json_null = v:null |
||||||
|
|
||||||
|
if has('nvim') |
||||||
|
function! neomake#compat#json_decode(json) abort |
||||||
|
if a:json is# '' |
||||||
|
" Prevent Neovim from throwing E474: Attempt to decode a blank string. |
||||||
|
return g:neomake#compat#json_none |
||||||
|
endif |
||||||
|
return json_decode(a:json) |
||||||
|
endfunction |
||||||
|
else |
||||||
|
function! neomake#compat#json_decode(json) abort |
||||||
|
return json_decode(a:json) |
||||||
|
endfunction |
||||||
|
endif |
||||||
|
else |
||||||
|
let neomake#compat#json_true = 1 |
||||||
|
let neomake#compat#json_false = 0 |
||||||
|
function! s:json_null() abort |
||||||
|
endfunction |
||||||
|
let neomake#compat#json_null = [function('s:json_null')] |
||||||
|
|
||||||
|
" Via Syntastic (https://github.com/vim-syntastic/syntastic/blob/6fb14d624b6081459360fdbba743f82cf84c8f92/autoload/syntastic/preprocess.vim#L576-L607), |
||||||
|
" based on https://github.com/MarcWeber/vim-addon-json-encoding/blob/master/autoload/json_encoding.vim. |
||||||
|
" @vimlint(EVL102, 1, l:true) |
||||||
|
" @vimlint(EVL102, 1, l:false) |
||||||
|
" @vimlint(EVL102, 1, l:null) |
||||||
|
function! neomake#compat#json_decode(json) abort " {{{2 |
||||||
|
if a:json ==# '' |
||||||
|
return g:neomake#compat#json_none |
||||||
|
endif |
||||||
|
|
||||||
|
" The following is inspired by https://github.com/MarcWeber/vim-addon-manager and |
||||||
|
" http://stackoverflow.com/questions/17751186/iterating-over-a-string-in-vimscript-or-parse-a-json-file/19105763#19105763 |
||||||
|
" A hat tip to Marc Weber for this trick |
||||||
|
" Replace newlines, which eval() does not like. |
||||||
|
let json = substitute(a:json, "\n", '', 'g') |
||||||
|
if substitute(json, '\v\"%(\\.|[^"\\])*\"|true|false|null|[+-]?\d+%(\.\d+%([Ee][+-]?\d+)?)?', '', 'g') !~# "[^,:{}[\\] \t]" |
||||||
|
" JSON artifacts |
||||||
|
let true = g:neomake#compat#json_true |
||||||
|
let false = g:neomake#compat#json_false |
||||||
|
let null = g:neomake#compat#json_null |
||||||
|
|
||||||
|
try |
||||||
|
let object = eval(json) |
||||||
|
catch |
||||||
|
throw 'Neomake: Failed to parse JSON input: '.v:exception |
||||||
|
endtry |
||||||
|
else |
||||||
|
throw 'Neomake: Failed to parse JSON input: invalid input' |
||||||
|
endif |
||||||
|
|
||||||
|
return object |
||||||
|
endfunction " }}}2 |
||||||
|
" @vimlint(EVL102, 0, l:true) |
||||||
|
" @vimlint(EVL102, 0, l:false) |
||||||
|
" @vimlint(EVL102, 0, l:null) |
||||||
|
endif |
||||||
|
|
||||||
|
lockvar neomake#compat#json_true |
||||||
|
lockvar neomake#compat#json_false |
||||||
|
lockvar neomake#compat#json_null |
||||||
|
|
||||||
|
if exists('*uniq') |
||||||
|
function! neomake#compat#uniq(l) abort |
||||||
|
return uniq(a:l) |
||||||
|
endfunction |
||||||
|
else |
||||||
|
function! neomake#compat#uniq(l) abort |
||||||
|
let n = len(a:l) |
||||||
|
if n < 2 |
||||||
|
return a:l |
||||||
|
endif |
||||||
|
let prev = a:l[0] |
||||||
|
let idx = 1 |
||||||
|
while idx < n |
||||||
|
if a:l[idx] ==# prev && type(a:l[idx]) == type(prev) |
||||||
|
call remove(a:l, idx) |
||||||
|
let n -= 1 |
||||||
|
else |
||||||
|
let prev = a:l[idx] |
||||||
|
let idx += 1 |
||||||
|
endif |
||||||
|
endwhile |
||||||
|
return a:l |
||||||
|
endfunction |
||||||
|
endif |
||||||
|
|
||||||
|
if exists('*reltimefloat') |
||||||
|
function! neomake#compat#reltimefloat() abort |
||||||
|
return reltimefloat(reltime()) |
||||||
|
endfunction |
||||||
|
else |
||||||
|
function! neomake#compat#reltimefloat() abort |
||||||
|
let t = split(reltimestr(reltime()), '\V.') |
||||||
|
return str2float(t[0] . '.' . t[1]) |
||||||
|
endfunction |
||||||
|
endif |
||||||
|
|
||||||
|
" Wrapper around systemlist() that supports a list for a:cmd. |
||||||
|
" It returns an empty string on error. |
||||||
|
" NOTE: Neovim before 0.2.0 would throw an error (which is caught), but it |
||||||
|
" does not set v:shell_error! |
||||||
|
function! neomake#compat#systemlist(cmd) abort |
||||||
|
if empty(a:cmd) |
||||||
|
return [] |
||||||
|
endif |
||||||
|
if has('nvim') && exists('*systemlist') |
||||||
|
" @vimlint(EVL108, 1) |
||||||
|
if !has('nvim-0.2.0') |
||||||
|
try |
||||||
|
return systemlist(a:cmd) |
||||||
|
catch /^Vim\%((\a\+)\)\=:E902/ |
||||||
|
return '' |
||||||
|
endtry |
||||||
|
endif |
||||||
|
" @vimlint(EVL108, 0) |
||||||
|
return systemlist(a:cmd) |
||||||
|
endif |
||||||
|
|
||||||
|
if type(a:cmd) == type([]) |
||||||
|
let cmd = join(map(a:cmd, 'neomake#utils#shellescape(v:val)')) |
||||||
|
else |
||||||
|
let cmd = a:cmd |
||||||
|
endif |
||||||
|
if exists('*systemlist') |
||||||
|
return systemlist(cmd) |
||||||
|
endif |
||||||
|
return split(system(cmd), '\n') |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#compat#globpath_list(path, pattern, suf) abort |
||||||
|
if v:version >= 705 || (v:version == 704 && has('patch279')) |
||||||
|
return globpath(a:path, a:pattern, a:suf, 1) |
||||||
|
endif |
||||||
|
return split(globpath(a:path, a:pattern, a:suf), '\n') |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#compat#glob_list(pattern) abort |
||||||
|
if v:version <= 703 |
||||||
|
return split(glob(a:pattern, 1), '\n') |
||||||
|
endif |
||||||
|
return glob(a:pattern, 1, 1) |
||||||
|
endfunction |
||||||
|
|
||||||
|
if neomake#utils#IsRunningWindows() |
||||||
|
" Windows needs a shell to handle PATH/%PATHEXT% etc. |
||||||
|
function! neomake#compat#get_argv(exe, args, args_is_list) abort |
||||||
|
let prefix = &shell.' '.&shellcmdflag.' ' |
||||||
|
if a:args_is_list |
||||||
|
if a:exe ==# &shell && get(a:args, 0) ==# &shellcmdflag |
||||||
|
" Remove already existing &shell/&shellcmdflag from e.g. NeomakeSh. |
||||||
|
let argv = join(a:args[1:]) |
||||||
|
else |
||||||
|
let argv = join(map(copy([a:exe] + a:args), 'neomake#utils#shellescape(v:val)')) |
||||||
|
endif |
||||||
|
else |
||||||
|
let argv = a:exe . (empty(a:args) ? '' : ' '.a:args) |
||||||
|
if argv[0:len(prefix)-1] ==# prefix |
||||||
|
return argv |
||||||
|
endif |
||||||
|
endif |
||||||
|
return prefix.argv |
||||||
|
endfunction |
||||||
|
elseif has('nvim') |
||||||
|
function! neomake#compat#get_argv(exe, args, args_is_list) abort |
||||||
|
if a:args_is_list |
||||||
|
return [a:exe] + a:args |
||||||
|
endif |
||||||
|
return a:exe . (empty(a:args) ? '' : ' '.a:args) |
||||||
|
endfunction |
||||||
|
elseif neomake#has_async_support() " Vim-async. |
||||||
|
function! neomake#compat#get_argv(exe, args, args_is_list) abort |
||||||
|
if a:args_is_list |
||||||
|
return [a:exe] + a:args |
||||||
|
endif |
||||||
|
" Use a shell to handle argv properly (Vim splits at spaces). |
||||||
|
let argv = a:exe . (empty(a:args) ? '' : ' '.a:args) |
||||||
|
return [&shell, &shellcmdflag, argv] |
||||||
|
endfunction |
||||||
|
else |
||||||
|
" Vim (synchronously), via system(). |
||||||
|
function! neomake#compat#get_argv(exe, args, args_is_list) abort |
||||||
|
if a:args_is_list |
||||||
|
return join(map(copy([a:exe] + a:args), 'neomake#utils#shellescape(v:val)')) |
||||||
|
endif |
||||||
|
return a:exe . (empty(a:args) ? '' : ' '.a:args) |
||||||
|
endfunction |
||||||
|
endif |
||||||
|
|
||||||
|
if v:version >= 704 || (v:version == 703 && has('patch831')) |
||||||
|
function! neomake#compat#gettabwinvar(t, w, v, d) abort |
||||||
|
return gettabwinvar(a:t, a:w, a:v, a:d) |
||||||
|
endfunction |
||||||
|
else |
||||||
|
" Wrapper around gettabwinvar that has no default (older Vims). |
||||||
|
function! neomake#compat#gettabwinvar(t, w, v, d) abort |
||||||
|
let r = gettabwinvar(a:t, a:w, a:v) |
||||||
|
if r is# '' |
||||||
|
unlet r |
||||||
|
let r = a:d |
||||||
|
endif |
||||||
|
return r |
||||||
|
endfunction |
||||||
|
endif |
||||||
|
|
||||||
|
" Not really necessary for now, but allows to overwriting and extending. |
||||||
|
if exists('*nvim_get_mode') |
||||||
|
function! neomake#compat#get_mode() abort |
||||||
|
let mode = nvim_get_mode() |
||||||
|
return mode.mode |
||||||
|
endfunction |
||||||
|
else |
||||||
|
function! neomake#compat#get_mode() abort |
||||||
|
return mode(1) |
||||||
|
endfunction |
||||||
|
endif |
||||||
|
|
||||||
|
function! neomake#compat#in_completion() abort |
||||||
|
if pumvisible() |
||||||
|
return 1 |
||||||
|
endif |
||||||
|
if has('patch-8.0.0283') |
||||||
|
let mode = mode(1) |
||||||
|
if mode[1] ==# 'c' || mode[1] ==# 'x' |
||||||
|
return 1 |
||||||
|
endif |
||||||
|
endif |
||||||
|
return 0 |
||||||
|
endfunction |
||||||
|
|
||||||
|
let s:prev_windows = [] |
||||||
|
if exists('*win_getid') |
||||||
|
function! neomake#compat#save_prev_windows() abort |
||||||
|
call add(s:prev_windows, [win_getid(winnr('#')), win_getid(winnr())]) |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#compat#restore_prev_windows() abort |
||||||
|
" Go back, maintaining the '#' window (CTRL-W_p). |
||||||
|
let [aw_id, pw_id] = remove(s:prev_windows, 0) |
||||||
|
let pw = win_id2win(pw_id) |
||||||
|
if !pw |
||||||
|
call neomake#log#debug(printf( |
||||||
|
\ 'Cannot restore previous windows (previous window with ID %d not found).', |
||||||
|
\ pw_id)) |
||||||
|
elseif winnr() != pw |
||||||
|
let aw = win_id2win(aw_id) |
||||||
|
if aw |
||||||
|
exec aw . 'wincmd w' |
||||||
|
endif |
||||||
|
exec pw . 'wincmd w' |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
else |
||||||
|
function! neomake#compat#save_prev_windows() abort |
||||||
|
call add(s:prev_windows, [winnr('#'), winnr()]) |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#compat#restore_prev_windows() abort |
||||||
|
" Go back, maintaining the '#' window (CTRL-W_p). |
||||||
|
let [aw, pw] = remove(s:prev_windows, 0) |
||||||
|
if pw > winnr('$') |
||||||
|
call neomake#log#debug(printf( |
||||||
|
\ 'Cannot restore previous windows (%d > %d).', |
||||||
|
\ pw, winnr('$'))) |
||||||
|
elseif winnr() != pw |
||||||
|
if aw |
||||||
|
exec aw . 'wincmd w' |
||||||
|
endif |
||||||
|
exec pw . 'wincmd w' |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
endif |
||||||
|
|
||||||
|
if v:version >= 704 || (v:version == 703 && has('patch442')) |
||||||
|
function! neomake#compat#doautocmd(event) abort |
||||||
|
exec 'doautocmd <nomodeline> ' . a:event |
||||||
|
endfunction |
||||||
|
else |
||||||
|
function! neomake#compat#doautocmd(event) abort |
||||||
|
exec 'doautocmd ' . a:event |
||||||
|
endfunction |
||||||
|
endif |
||||||
|
" vim: ts=4 sw=4 et |
@ -0,0 +1,192 @@ |
|||||||
|
" Config API. |
||||||
|
|
||||||
|
let g:neomake#config#_defaults = { |
||||||
|
\ 'maker_defaults': { |
||||||
|
\ 'buffer_output': 1, |
||||||
|
\ 'output_stream': 'both', |
||||||
|
\ 'remove_invalid_entries': 0, |
||||||
|
\ }} |
||||||
|
lockvar g:neomake#config#_defaults |
||||||
|
|
||||||
|
let g:neomake#config#undefined = {} |
||||||
|
lockvar! g:neomake#config#undefined |
||||||
|
|
||||||
|
" Resolve a:name (split on dots) and (optionally) init a:dict accordingly. |
||||||
|
function! s:resolve_name(dict, name, init) abort |
||||||
|
let parts = type(a:name) == type([]) ? a:name : split(a:name, '\.') |
||||||
|
let c = a:dict |
||||||
|
for p in parts[0:-2] |
||||||
|
if !has_key(c, p) |
||||||
|
if !a:init |
||||||
|
return [g:neomake#config#undefined, ''] |
||||||
|
endif |
||||||
|
let c[p] = {} |
||||||
|
endif |
||||||
|
if type(c[p]) != type({}) |
||||||
|
return [g:neomake#config#undefined, ''] |
||||||
|
endif |
||||||
|
let c = c[p] |
||||||
|
endfor |
||||||
|
return [c, parts[-1]] |
||||||
|
endfunction |
||||||
|
|
||||||
|
" Get a:name (list of keys) from a:dict, using a:prefixes. |
||||||
|
function! s:get(dict, parts, prefixes) abort |
||||||
|
for prefix in a:prefixes |
||||||
|
let [c, k] = s:resolve_name(a:dict, prefix + a:parts[0:-1], 0) |
||||||
|
if has_key(c, k) |
||||||
|
return [prefix, get(c, k)] |
||||||
|
endif |
||||||
|
endfor |
||||||
|
return [[], g:neomake#config#undefined] |
||||||
|
endfunction |
||||||
|
|
||||||
|
" Get a:name (string (split on dots), or list of keys) from config. |
||||||
|
" See neomake#config#get_with_source for args. |
||||||
|
function! neomake#config#get(name, ...) abort |
||||||
|
return call('neomake#config#get_with_source', [a:name] + a:000)[0] |
||||||
|
endfunction |
||||||
|
|
||||||
|
" Get a:name (string (split on dots), or list of keys) from config, with |
||||||
|
" information about the setting's source ('buffer', 'tab', 'global', 'maker', |
||||||
|
" 'default'). |
||||||
|
" Optional args: |
||||||
|
" - a:1: default value |
||||||
|
" - a:2: context: defaults to {'ft': &filetype} |
||||||
|
" - maker: a maker dict (where maker.name is used from for prefixes, and |
||||||
|
" as a lookup itself) |
||||||
|
" - ft: filetype string (use an empty string to ignore it) |
||||||
|
" - bufnr: buffer number (use an empty string to ignore it) |
||||||
|
" - maker_only: should settings get looked up only in the maker context? |
||||||
|
" (i.e. with maker.name prefix in general and in context.maker) |
||||||
|
" - log_source: additional information to log. |
||||||
|
function! neomake#config#get_with_source(name, ...) abort |
||||||
|
let context = a:0 > 1 ? a:2 : {'ft': &filetype, 'bufnr': bufnr('%')} |
||||||
|
let parts = type(a:name) == type([]) ? a:name : split(a:name, '\.') |
||||||
|
|
||||||
|
let prefixes = [[]] |
||||||
|
if has_key(context, 'ft') && !empty(context.ft) |
||||||
|
for ft in neomake#utils#get_config_fts(context.ft, '.') |
||||||
|
call insert(prefixes, ['ft', ft], 0) |
||||||
|
endfor |
||||||
|
endif |
||||||
|
|
||||||
|
let maker_name = get(get(context, 'maker', {}), 'name', '') |
||||||
|
let maker_only = get(context, 'maker_only', 0) |
||||||
|
if parts[0][0:1] ==# 'b:' |
||||||
|
if !has_key(context, 'bufnr') |
||||||
|
let context.bufnr = bufnr('%') |
||||||
|
endif |
||||||
|
let parts[0] = parts[0][2:-1] |
||||||
|
if context.bufnr is# '' |
||||||
|
let lookups = [] |
||||||
|
else |
||||||
|
let lookups = [['buffer', getbufvar(context.bufnr, 'neomake')]] |
||||||
|
endif |
||||||
|
call add(lookups, ['maker', get(context, 'maker', {})]) |
||||||
|
elseif empty(maker_name) && maker_only |
||||||
|
let lookups = [['maker', get(context, 'maker', {})]] |
||||||
|
else |
||||||
|
let lookups = (has_key(context, 'bufnr') && context.bufnr isnot# '' |
||||||
|
\ ? [['buffer', getbufvar(context.bufnr, 'neomake')]] |
||||||
|
\ : []) + [ |
||||||
|
\ ['tab', get(t:, 'neomake', {})], |
||||||
|
\ ['global', get(g:, 'neomake', {})], |
||||||
|
\ ['maker', get(context, 'maker', {})]] |
||||||
|
if !empty(maker_name) |
||||||
|
if maker_only |
||||||
|
if parts[0] !=# maker_name |
||||||
|
call map(prefixes, 'add(v:val, maker_name)') |
||||||
|
endif |
||||||
|
else |
||||||
|
for prefix in reverse(copy(prefixes)) |
||||||
|
call insert(prefixes, prefix + [maker_name], 0) |
||||||
|
endfor |
||||||
|
endif |
||||||
|
endif |
||||||
|
endif |
||||||
|
|
||||||
|
for [source, lookup] in lookups |
||||||
|
if !empty(lookup) |
||||||
|
if source ==# 'maker' |
||||||
|
let maker_prefixes = map(copy(prefixes), '!empty(v:val) && v:val[-1] ==# maker_name ? v:val[:-2] : v:val') |
||||||
|
let maker_setting_parts = parts[0] == maker_name ? parts[1:] : parts |
||||||
|
let [prefix, l:R] = s:get(lookup, maker_setting_parts, maker_prefixes) |
||||||
|
else |
||||||
|
let [prefix, l:R] = s:get(lookup, parts, prefixes) |
||||||
|
endif |
||||||
|
if R isnot# g:neomake#config#undefined |
||||||
|
let log_name = join(map(copy(parts), "substitute(v:val, '\\.', '|', '')"), '.') |
||||||
|
let log_source = get(context, 'log_source', '') |
||||||
|
call neomake#log#debug(printf( |
||||||
|
\ "Using setting %s=%s from '%s'%s%s.", |
||||||
|
\ log_name, string(R), source, |
||||||
|
\ empty(prefix) ? '' : ' (prefix: '.string(prefix).')', |
||||||
|
\ empty(log_source) ? '' : ' ('.log_source.')'), |
||||||
|
\ context) |
||||||
|
return [R, source] |
||||||
|
endif |
||||||
|
unlet R " for Vim without patch-7.4.1546 |
||||||
|
endif |
||||||
|
unlet lookup " for Vim without patch-7.4.1546 |
||||||
|
endfor |
||||||
|
|
||||||
|
" Return default. |
||||||
|
if a:0 |
||||||
|
return [a:1, 'default'] |
||||||
|
elseif has_key(g:neomake#config#_defaults, a:name) |
||||||
|
return [copy(g:neomake#config#_defaults[a:name]), 'default'] |
||||||
|
endif |
||||||
|
return [g:neomake#config#undefined, 'default'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
|
||||||
|
" Set a:name in a:dict to a:value, after resolving it (split on dots). |
||||||
|
function! s:set(dict, name, value) abort |
||||||
|
let [c, k] = s:resolve_name(a:dict, a:name, 1) |
||||||
|
let c[k] = a:value |
||||||
|
return c |
||||||
|
endfunction |
||||||
|
|
||||||
|
" Set a:name (resolved on dots) to a:value in the config. |
||||||
|
function! neomake#config#set(name, value) abort |
||||||
|
let parts = type(a:name) == type([]) ? a:name : split(a:name, '\.') |
||||||
|
if parts[0] =~# '^b:' |
||||||
|
let parts[0] = parts[0][2:-1] |
||||||
|
return neomake#config#set_buffer(bufnr('%'), parts, a:value) |
||||||
|
endif |
||||||
|
if !has_key(g:, 'neomake') |
||||||
|
let g:neomake = {} |
||||||
|
endif |
||||||
|
return s:set(g:neomake, parts, a:value) |
||||||
|
endfunction |
||||||
|
|
||||||
|
" Set a:name (resolved on dots) to a:value for buffer a:bufnr. |
||||||
|
function! neomake#config#set_buffer(bufnr, name, value) abort |
||||||
|
let bufnr = +a:bufnr |
||||||
|
let bneomake = getbufvar(bufnr, 'neomake') |
||||||
|
if bneomake is# '' |
||||||
|
unlet bneomake " for Vim without patch-7.4.1546 |
||||||
|
let bneomake = {} |
||||||
|
call setbufvar(bufnr, 'neomake', bneomake) |
||||||
|
endif |
||||||
|
return s:set(bneomake, a:name, a:value) |
||||||
|
endfunction |
||||||
|
|
||||||
|
" Set a:name (resolved on dots) to a:value in a:scope. |
||||||
|
" This is meant for advanced usage, e.g.: |
||||||
|
" set_scope(t:, 'neomake.disabled', 1) |
||||||
|
function! neomake#config#set_dict(dict, name, value) abort |
||||||
|
return s:set(a:dict, a:name, a:value) |
||||||
|
endfunction |
||||||
|
|
||||||
|
" Unset a:name (resolved on dots). |
||||||
|
" This is meant for advanced usage, e.g.: |
||||||
|
" unset_dict(t:, 'neomake.disabled', 1) |
||||||
|
function! neomake#config#unset_dict(dict, name) abort |
||||||
|
let [c, k] = s:resolve_name(a:dict, a:name, 0) |
||||||
|
if has_key(c, k) |
||||||
|
unlet c[k] |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
" vim: ts=4 sw=4 et |
@ -0,0 +1,775 @@ |
|||||||
|
" Default settings, setup in global config dict. |
||||||
|
let s:default_settings = { |
||||||
|
\ 'ignore_filetypes': ['startify'], |
||||||
|
\ } |
||||||
|
let g:neomake = get(g:, 'neomake', {}) |
||||||
|
let g:neomake.automake = get(g:neomake, 'automake', {}) |
||||||
|
call extend(g:neomake.automake, s:default_settings, 'keep') |
||||||
|
|
||||||
|
if !exists('s:timer_info') |
||||||
|
let s:timer_info = {} |
||||||
|
let s:timer_by_bufnr = {} |
||||||
|
endif |
||||||
|
|
||||||
|
let s:default_delay = has('timers') ? 500 : 0 |
||||||
|
|
||||||
|
" A mapping of configured buffers with cached settings (maker_jobs). |
||||||
|
let s:configured_buffers = {} |
||||||
|
" A list of configured/used autocommands. |
||||||
|
let s:registered_events = [] |
||||||
|
|
||||||
|
" TextChanged gets triggered in this case when loading a buffer (Vim |
||||||
|
" issue #2742). |
||||||
|
let s:need_to_skip_first_textchanged = !has('nvim-0.3.2') && has('patch-8.0.1494') && !has('patch-8.0.1633') |
||||||
|
|
||||||
|
|
||||||
|
" TODO: allow for namespaces, and prefer 'automake' here. |
||||||
|
" TODO: handle bufnr! (getbufvar) |
||||||
|
function! s:get_setting(name, default) abort |
||||||
|
return get(get(b:, 'neomake', {}), a:name, |
||||||
|
\ get(get(t:, 'neomake', {}), a:name, |
||||||
|
\ get(get(g:, 'neomake', {}), a:name, a:default))) |
||||||
|
endfunction |
||||||
|
|
||||||
|
|
||||||
|
function! s:debug_log(msg, ...) abort |
||||||
|
let context = {'bufnr': bufnr('%')} |
||||||
|
if a:0 |
||||||
|
call extend(context, a:1) |
||||||
|
endif |
||||||
|
call neomake#log#debug(printf('automake: %s.', a:msg), context) |
||||||
|
endfunction |
||||||
|
|
||||||
|
" Check if buffer's tick (or ft) changed. |
||||||
|
function! s:tick_changed(context) abort |
||||||
|
let bufnr = +a:context.bufnr |
||||||
|
let ft = get(a:context, 'ft', getbufvar(bufnr, '&filetype')) |
||||||
|
let prev_tick = getbufvar(bufnr, '_neomake_automake_tick') |
||||||
|
let r = 1 |
||||||
|
if empty(prev_tick) |
||||||
|
call s:debug_log('tick changed (new)') |
||||||
|
else |
||||||
|
let cur_tick = [getbufvar(bufnr, 'changedtick'), ft] |
||||||
|
if cur_tick == prev_tick |
||||||
|
call s:debug_log('tick is unchanged') |
||||||
|
return 0 |
||||||
|
endif |
||||||
|
endif |
||||||
|
return r |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#configure#_update_automake_tick(bufnr, ft) abort |
||||||
|
if has_key(s:configured_buffers, a:bufnr) |
||||||
|
let tick = getbufvar(a:bufnr, 'changedtick') |
||||||
|
call s:debug_log('updating tick: '.tick) |
||||||
|
call setbufvar(a:bufnr, '_neomake_automake_tick', [tick, a:ft]) |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#configure#_reset_automake_cancelations(bufnr) abort |
||||||
|
if has_key(s:configured_buffers, a:bufnr) |
||||||
|
call setbufvar(a:bufnr, '_neomake_cancelations', [0, 0]) |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:update_cancel_rate(bufnr, via_timer) abort |
||||||
|
let canceled = getbufvar(a:bufnr, '_neomake_cancelations', [0, 0]) |
||||||
|
if a:via_timer |
||||||
|
let canceled[0] += 1 |
||||||
|
else |
||||||
|
let canceled[1] += 1 |
||||||
|
endif |
||||||
|
call setbufvar(a:bufnr, '_neomake_cancelations', canceled) |
||||||
|
return canceled |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:handle_changed_buffer(make_id, event) abort |
||||||
|
" Cleanup always. |
||||||
|
if exists('b:_neomake_automake_changed_context') |
||||||
|
let [make_id, prev_tick, changedtick, context] = b:_neomake_automake_changed_context |
||||||
|
|
||||||
|
if s:need_to_skip_first_textchanged && a:event ==# 'TextChanged' |
||||||
|
if !get(b:, '_neomake_seen_TextChanged', 0) |
||||||
|
call s:debug_log('ignoring first TextChanged') |
||||||
|
let b:_neomake_seen_TextChanged = 1 |
||||||
|
return |
||||||
|
endif |
||||||
|
endif |
||||||
|
|
||||||
|
if changedtick == b:changedtick |
||||||
|
call s:debug_log(printf('handle_changed_buffer: %s: tick was not changed', a:event)) |
||||||
|
return |
||||||
|
endif |
||||||
|
|
||||||
|
unlet b:_neomake_automake_changed_context |
||||||
|
augroup neomake_automake_abort |
||||||
|
au! * <buffer> |
||||||
|
augroup END |
||||||
|
else |
||||||
|
return |
||||||
|
endif |
||||||
|
|
||||||
|
if make_id != a:make_id |
||||||
|
call neomake#log#warning(printf('automake: handle_changed_buffer: mismatched make_id: %d != %d.', make_id, a:make_id)) |
||||||
|
return |
||||||
|
endif |
||||||
|
|
||||||
|
let window_make_ids = get(w:, 'neomake_make_ids', []) |
||||||
|
if index(window_make_ids, a:make_id) == -1 |
||||||
|
return |
||||||
|
endif |
||||||
|
|
||||||
|
call setbufvar(context.bufnr, '_neomake_automake_tick', prev_tick) |
||||||
|
call filter(b:_neomake_automake_make_ids, 'v:val != '.a:make_id) |
||||||
|
call s:update_cancel_rate(context.bufnr, 0) |
||||||
|
|
||||||
|
call s:debug_log(printf('buffer was changed (%s), canceling make', a:event), {'make_id': a:make_id}) |
||||||
|
call neomake#CancelMake(a:make_id) |
||||||
|
|
||||||
|
if a:event ==# 'TextChangedI' |
||||||
|
call s:debug_log('queueing make restart for InsertLeave', {'make_id': a:make_id}) |
||||||
|
let b:_neomake_postponed_automake_context = [1, context] |
||||||
|
augroup neomake_automake_retry |
||||||
|
au! * <buffer> |
||||||
|
autocmd InsertLeave <buffer> call s:do_postponed_automake(2) |
||||||
|
augroup END |
||||||
|
elseif context.delay |
||||||
|
call s:debug_log(printf('restarting timer for original event %s', context.event), {'make_id': a:make_id}) |
||||||
|
if has_key(context, '_via_timer_cb') |
||||||
|
unlet context._via_timer_cb |
||||||
|
endif |
||||||
|
if has_key(context, 'pos') |
||||||
|
unlet context.pos |
||||||
|
endif |
||||||
|
call s:neomake_do_automake(context) |
||||||
|
else |
||||||
|
call s:debug_log(printf('restarting for original event (%s) without delay', context.event)) |
||||||
|
call s:neomake_do_automake(context) |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:neomake_do_automake(context) abort |
||||||
|
let bufnr = +a:context.bufnr |
||||||
|
|
||||||
|
if !get(a:context, '_via_timer_cb') && a:context.delay |
||||||
|
if exists('s:timer_by_bufnr[bufnr]') |
||||||
|
let timer = s:timer_by_bufnr[bufnr] |
||||||
|
call s:stop_timer(timer) |
||||||
|
call s:debug_log(printf('stopped existing timer: %d', timer), {'bufnr': bufnr}) |
||||||
|
call s:update_cancel_rate(bufnr, 1) |
||||||
|
endif |
||||||
|
if !s:tick_changed(a:context) |
||||||
|
call s:debug_log('buffer was not changed', {'bufnr': bufnr}) |
||||||
|
return |
||||||
|
endif |
||||||
|
|
||||||
|
" Cancel any already running automake runs. |
||||||
|
let prev_make_ids = getbufvar(bufnr, '_neomake_automake_make_ids') |
||||||
|
if !empty(prev_make_ids) |
||||||
|
call s:debug_log(printf('stopping previous make runs: %s', join(prev_make_ids, ', '))) |
||||||
|
for prev_make_id in prev_make_ids |
||||||
|
call neomake#CancelMake(prev_make_id) |
||||||
|
endfor |
||||||
|
let canceled = s:update_cancel_rate(bufnr, 0) |
||||||
|
else |
||||||
|
let canceled = getbufvar(bufnr, '_neomake_cancelations', [0, 0]) |
||||||
|
endif |
||||||
|
|
||||||
|
let delay = a:context.delay |
||||||
|
|
||||||
|
" Increase delay for canceled/restarted timers, and canceled makes. |
||||||
|
" IDEA: take into account the mean duration of this make run. |
||||||
|
if canceled[0] || canceled[1] |
||||||
|
let [mult_timers, mult_makes, max_delay] = neomake#config#get('automake.cancelation_delay', [0.2, 0.5, 3000], {'bufnr': bufnr}) |
||||||
|
let cancel_rate = 1 + (canceled[0]*mult_timers + canceled[1]*mult_makes) |
||||||
|
let delay = min([max_delay, float2nr(ceil(delay * cancel_rate))]) |
||||||
|
call s:debug_log(printf('increasing delay (%d/%d canceled timers/makes, rate=%.2f): %d => %d/%d', canceled[0], canceled[1], cancel_rate, a:context.delay, delay, max_delay)) |
||||||
|
endif |
||||||
|
|
||||||
|
let timer = timer_start(delay, function('s:automake_delayed_cb')) |
||||||
|
let s:timer_info[timer] = a:context |
||||||
|
if !has_key(a:context, 'pos') |
||||||
|
let s:timer_info[timer].pos = s:get_position_context() |
||||||
|
endif |
||||||
|
let s:timer_by_bufnr[bufnr] = timer |
||||||
|
call s:debug_log(printf('started timer (%dms): %d', delay, timer), |
||||||
|
\ {'bufnr': a:context.bufnr}) |
||||||
|
return |
||||||
|
endif |
||||||
|
|
||||||
|
let ft = getbufvar(bufnr, '&filetype') |
||||||
|
let event = a:context.event |
||||||
|
|
||||||
|
call s:debug_log('neomake_do_automake: '.event, {'bufnr': bufnr}) |
||||||
|
if !s:tick_changed({'event': event, 'bufnr': bufnr, 'ft': ft}) |
||||||
|
call s:debug_log('buffer was not changed', {'bufnr': bufnr}) |
||||||
|
return |
||||||
|
endif |
||||||
|
let prev_tick = getbufvar(bufnr, '_neomake_automake_tick') |
||||||
|
|
||||||
|
call s:debug_log(printf('enabled makers: %s', join(map(copy(a:context.maker_jobs), 'v:val.maker.name'), ', '))) |
||||||
|
let make_options = { |
||||||
|
\ 'file_mode': 1, |
||||||
|
\ 'jobs': deepcopy(a:context.maker_jobs), |
||||||
|
\ 'ft': ft, |
||||||
|
\ 'automake': 1} |
||||||
|
let jobinfos = neomake#Make(make_options) |
||||||
|
|
||||||
|
let started_jobs = filter(copy(jobinfos), "!get(v:val, 'finished', 0)") |
||||||
|
call s:debug_log(printf('started jobs: %s', string(map(copy(started_jobs), 'v:val.id')))) |
||||||
|
if !empty(started_jobs) |
||||||
|
let make_id = jobinfos[0].make_id |
||||||
|
call setbufvar(bufnr, '_neomake_automake_make_ids', |
||||||
|
\ neomake#compat#getbufvar(bufnr, '_neomake_automake_make_ids', []) + [make_id]) |
||||||
|
|
||||||
|
" Setup buffer autocmd to cancel/restart make for changed buffer. |
||||||
|
let events = [] |
||||||
|
for event in ['TextChangedI', 'TextChanged'] |
||||||
|
if a:context.event !=# event |
||||||
|
call add(events, event) |
||||||
|
endif |
||||||
|
endfor |
||||||
|
call setbufvar(bufnr, '_neomake_automake_changed_context', [make_id, prev_tick, getbufvar(bufnr, 'changedtick'), a:context]) |
||||||
|
augroup neomake_automake_abort |
||||||
|
exe printf('au! * <buffer=%d>', bufnr) |
||||||
|
for event in events |
||||||
|
exe printf('autocmd %s <buffer=%d> call s:handle_changed_buffer(%s, %s)', |
||||||
|
\ event, bufnr, string(make_id), string(event)) |
||||||
|
endfor |
||||||
|
augroup END |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:get_position_context() abort |
||||||
|
let w = exists('*win_getid') ? win_getid() : winnr() |
||||||
|
return [w, getpos('.'), neomake#compat#get_mode()] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:automake_delayed_cb(timer) abort |
||||||
|
let timer_info = s:timer_info[a:timer] |
||||||
|
unlet s:timer_info[a:timer] |
||||||
|
unlet s:timer_by_bufnr[timer_info.bufnr] |
||||||
|
|
||||||
|
if !bufexists(timer_info.bufnr) |
||||||
|
call s:debug_log(printf('buffer does not exist anymore for timer %d', a:timer), |
||||||
|
\ {'bufnr': timer_info.bufnr}) |
||||||
|
return |
||||||
|
endif |
||||||
|
|
||||||
|
call s:debug_log(printf('callback for timer %d (via %s)', string(a:timer), timer_info.event), |
||||||
|
\ {'bufnr': timer_info.bufnr}) |
||||||
|
|
||||||
|
let bufnr = bufnr('%') |
||||||
|
if timer_info.bufnr != bufnr |
||||||
|
call s:debug_log(printf('buffer changed: %d => %d, queueing make restart for BufEnter,WinEnter', |
||||||
|
\ timer_info.bufnr, bufnr)) |
||||||
|
let restart_context = copy(timer_info) |
||||||
|
call setbufvar(restart_context.bufnr, '_neomake_postponed_automake_context', [1, restart_context]) |
||||||
|
let b:_neomake_postponed_automake_context = [1, restart_context] |
||||||
|
augroup neomake_automake_retry |
||||||
|
exe 'au! * <buffer='.timer_info.bufnr.'>' |
||||||
|
exe 'autocmd BufEnter,WinEnter <buffer='.restart_context.bufnr.'> call s:do_postponed_automake(2)' |
||||||
|
augroup END |
||||||
|
return |
||||||
|
endif |
||||||
|
|
||||||
|
if neomake#compat#in_completion() |
||||||
|
call s:debug_log('postponing automake during completion') |
||||||
|
if has_key(timer_info, 'pos') |
||||||
|
unlet timer_info.pos |
||||||
|
endif |
||||||
|
let b:_neomake_postponed_automake_context = [0, timer_info] |
||||||
|
|
||||||
|
augroup neomake_automake_retry |
||||||
|
au! * <buffer> |
||||||
|
autocmd CompleteDone <buffer> call s:do_postponed_automake(1) |
||||||
|
autocmd InsertLeave <buffer> call s:do_postponed_automake(2) |
||||||
|
augroup END |
||||||
|
return |
||||||
|
endif |
||||||
|
|
||||||
|
" Verify context/position is the same. |
||||||
|
" This is meant to give an additional delay after e.g. TextChanged. |
||||||
|
" Only events with delay are coming here, so this does not affect |
||||||
|
" BufWritePost etc typically. |
||||||
|
if !empty(timer_info.pos) |
||||||
|
let current_context = s:get_position_context() |
||||||
|
if current_context != timer_info.pos |
||||||
|
if current_context[2] != timer_info.pos[2] |
||||||
|
" Mode was changed. |
||||||
|
if current_context[2][0] ==# 'i' && timer_info.event !=# 'TextChangedI' |
||||||
|
" Changed to insert mode, trigger on InsertLeave. |
||||||
|
call s:debug_log(printf('context/position changed: %s => %s, restarting on InsertLeave', |
||||||
|
\ string(timer_info.pos), string(current_context))) |
||||||
|
let context = copy(timer_info) |
||||||
|
let context.delay = 0 |
||||||
|
unlet context.pos |
||||||
|
call s:update_cancel_rate(bufnr, 1) |
||||||
|
let b:_neomake_postponed_automake_context = [1, context] |
||||||
|
augroup neomake_automake_retry |
||||||
|
au! * <buffer> |
||||||
|
autocmd InsertLeave <buffer> call s:do_postponed_automake(2) |
||||||
|
augroup END |
||||||
|
return |
||||||
|
endif |
||||||
|
endif |
||||||
|
call s:debug_log(printf('context/position changed: %s => %s, restarting', |
||||||
|
\ string(timer_info.pos), string(current_context))) |
||||||
|
unlet timer_info.pos |
||||||
|
call s:update_cancel_rate(bufnr, 1) |
||||||
|
call s:neomake_do_automake(timer_info) |
||||||
|
return |
||||||
|
endif |
||||||
|
endif |
||||||
|
" endif |
||||||
|
|
||||||
|
let context = copy(timer_info) |
||||||
|
let context._via_timer_cb = 1 |
||||||
|
call s:neomake_do_automake(context) |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:do_postponed_automake(step) abort |
||||||
|
if exists('b:_neomake_postponed_automake_context') |
||||||
|
let context = b:_neomake_postponed_automake_context |
||||||
|
|
||||||
|
if context[0] == a:step - 1 |
||||||
|
if a:step == 2 |
||||||
|
call s:debug_log('re-starting postponed automake') |
||||||
|
let context[1].pos = s:get_position_context() |
||||||
|
call s:neomake_do_automake(context[1]) |
||||||
|
else |
||||||
|
let context[0] = a:step |
||||||
|
return |
||||||
|
endif |
||||||
|
else |
||||||
|
call s:debug_log('postponed automake: unexpected step '.a:step.', cleaning up') |
||||||
|
endif |
||||||
|
unlet b:_neomake_postponed_automake_context |
||||||
|
else |
||||||
|
call s:debug_log('missing context information for postponed automake') |
||||||
|
endif |
||||||
|
" Cleanup. |
||||||
|
augroup neomake_automake_retry |
||||||
|
autocmd! * <buffer> |
||||||
|
augroup END |
||||||
|
endfunction |
||||||
|
|
||||||
|
" Parse/get events dict from args. |
||||||
|
" a:config: config dict to write into. |
||||||
|
" a:string_or_dict_config: a string or dict describing the config. |
||||||
|
" a:1: default delay. |
||||||
|
function! s:parse_events_from_args(config, string_or_dict_config, ...) abort |
||||||
|
" Get default delay from a:1. |
||||||
|
if a:0 |
||||||
|
if has('timers') |
||||||
|
let delay = a:1 |
||||||
|
else |
||||||
|
if a:1 != 0 |
||||||
|
call neomake#log#warning('automake: timer support is required for delayed events.') |
||||||
|
endif |
||||||
|
let delay = 0 |
||||||
|
endif |
||||||
|
else |
||||||
|
let delay = s:default_delay |
||||||
|
endif |
||||||
|
|
||||||
|
if type(a:string_or_dict_config) == type({}) |
||||||
|
let events = copy(a:string_or_dict_config) |
||||||
|
|
||||||
|
" Validate events. |
||||||
|
for [event, config] in items(events) |
||||||
|
if !exists('##'.event) |
||||||
|
call neomake#log#error(printf( |
||||||
|
\ 'automake: event %s does not exist.', event)) |
||||||
|
unlet events[event] |
||||||
|
continue |
||||||
|
endif |
||||||
|
|
||||||
|
if get(config, 'delay', 0) && !has('timers') |
||||||
|
call neomake#log#error(printf( |
||||||
|
\ 'automake: timer support is required for automaking, removing event %s.', |
||||||
|
\ event)) |
||||||
|
unlet events[event] |
||||||
|
endif |
||||||
|
endfor |
||||||
|
call neomake#config#set_dict(a:config, 'automake.events', events) |
||||||
|
if a:0 |
||||||
|
let a:config.automake_delay = a:1 |
||||||
|
endif |
||||||
|
else |
||||||
|
" Map string config to events dict. |
||||||
|
let modes = a:string_or_dict_config |
||||||
|
let events = {} |
||||||
|
let default_with_delay = {} |
||||||
|
|
||||||
|
" Insert mode. |
||||||
|
if modes =~# 'i' |
||||||
|
if exists('##TextChangedI') && has('timers') |
||||||
|
let events['TextChangedI'] = default_with_delay |
||||||
|
else |
||||||
|
call s:debug_log('using CursorHoldI instead of TextChangedI') |
||||||
|
let events['CursorHoldI'] = (delay != 0 ? {'delay': 0} : {}) |
||||||
|
endif |
||||||
|
endif |
||||||
|
" Normal mode. |
||||||
|
if modes =~# 'n' |
||||||
|
if exists('##TextChanged') && has('timers') |
||||||
|
let events['TextChanged'] = default_with_delay |
||||||
|
if !has_key(events, 'TextChangedI') |
||||||
|
" Run when leaving insert mode, since only TextChangedI would be triggered |
||||||
|
" for `ciw` etc. |
||||||
|
let events['InsertLeave'] = default_with_delay |
||||||
|
endif |
||||||
|
else |
||||||
|
call s:debug_log('using CursorHold instead of TextChanged') |
||||||
|
let events['CursorHold'] = (delay != 0 ? {'delay': 0} : {}) |
||||||
|
let events['InsertLeave'] = (delay != 0 ? {'delay': 0} : {}) |
||||||
|
endif |
||||||
|
endif |
||||||
|
" On writes. |
||||||
|
if modes =~# 'w' |
||||||
|
let events['BufWritePost'] = (delay != 0 ? {'delay': 0} : {}) |
||||||
|
endif |
||||||
|
" On reads. |
||||||
|
if modes =~# 'r' |
||||||
|
let events['BufWinEnter'] = {} |
||||||
|
let events['FileType'] = {} |
||||||
|
|
||||||
|
" When a file was changed outside of Vim. |
||||||
|
" TODO: test |
||||||
|
let events['FileChangedShellPost'] = {} |
||||||
|
" XXX: FileType might work better, at least when wanting to skip filetypes. |
||||||
|
" let events['FileType'] = {'delay': a:0 > 1 ? delay : 0} |
||||||
|
endif |
||||||
|
endif |
||||||
|
|
||||||
|
call neomake#config#set_dict(a:config, 'automake.events', events) |
||||||
|
if a:0 |
||||||
|
let a:config.automake_delay = delay |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
|
||||||
|
" Setup automake for buffer (current, or options.bufnr). |
||||||
|
" a:1: delay |
||||||
|
" a:2: options ('bufnr', 'makers') / or list of makers TODO |
||||||
|
function! neomake#configure#automake_for_buffer(string_or_dict_config, ...) abort |
||||||
|
let options = {} |
||||||
|
if a:0 |
||||||
|
let options.delay = a:1 |
||||||
|
endif |
||||||
|
let bufnr = bufnr('%') |
||||||
|
if a:0 > 1 |
||||||
|
if type(a:2) == type([]) |
||||||
|
let options.makers = a:2 |
||||||
|
else |
||||||
|
call extend(options, a:2) |
||||||
|
if has_key(options, 'bufnr') |
||||||
|
let bufnr = options.bufnr |
||||||
|
unlet options.bufnr |
||||||
|
endif |
||||||
|
endif |
||||||
|
endif |
||||||
|
return call('s:configure_buffer', [bufnr, a:string_or_dict_config, options]) |
||||||
|
endfunction |
||||||
|
|
||||||
|
" Workaround for getbufvar not having support for defaults. |
||||||
|
function! s:getbufvar(bufnr, name, default) abort |
||||||
|
let b_dict = getbufvar(+a:bufnr, '') |
||||||
|
if empty(b_dict) |
||||||
|
" NOTE: it is an empty string for non-existing buffers. |
||||||
|
return a:default |
||||||
|
endif |
||||||
|
return get(b_dict, a:name, a:default) |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:is_buffer_ignored(bufnr) abort |
||||||
|
" TODO: blacklist/whitelist. |
||||||
|
let bufnr = +a:bufnr |
||||||
|
let buftype = getbufvar(bufnr, '&buftype') |
||||||
|
if !empty(buftype) |
||||||
|
call s:debug_log(printf('ignoring buffer with buftype=%s', buftype), {'bufnr': bufnr}) |
||||||
|
return 1 |
||||||
|
endif |
||||||
|
|
||||||
|
let ft = getbufvar(bufnr, '&filetype') |
||||||
|
if index(neomake#config#get('automake.ignore_filetypes', []), ft) != -1 |
||||||
|
call s:debug_log(printf('ignoring buffer with filetype=%s', ft), {'bufnr': bufnr}) |
||||||
|
return 1 |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
|
||||||
|
if exists('##OptionSet') |
||||||
|
function! s:update_buffer_options() abort |
||||||
|
let bufnr = bufnr('%') |
||||||
|
call s:maybe_reconfigure_buffer(bufnr) |
||||||
|
endfunction |
||||||
|
augroup neomake_automake_update |
||||||
|
au! |
||||||
|
au OptionSet buftype call s:update_buffer_options() |
||||||
|
augroup END |
||||||
|
endif |
||||||
|
|
||||||
|
" a:1: string or dict describing the events |
||||||
|
" a:2: options ('delay', 'makers') |
||||||
|
function! s:configure_buffer(bufnr, ...) abort |
||||||
|
let bufnr = +a:bufnr |
||||||
|
let ft = getbufvar(bufnr, '&filetype') |
||||||
|
let config = s:getbufvar(bufnr, 'neomake', {}) |
||||||
|
let old_config = deepcopy(config) |
||||||
|
if a:0 |
||||||
|
let args = [config, a:1] |
||||||
|
if a:0 > 1 && has_key(a:2, 'delay') |
||||||
|
let args += [a:2.delay] |
||||||
|
endif |
||||||
|
call call('s:parse_events_from_args', args) |
||||||
|
call setbufvar(bufnr, 'neomake', config) |
||||||
|
|
||||||
|
let implicit_config = {'custom': 1, 'ignore': 0} |
||||||
|
else |
||||||
|
let implicit_config = {'custom': 0, 'ignore': s:is_buffer_ignored(bufnr)} |
||||||
|
endif |
||||||
|
|
||||||
|
" Register the buffer, and remember if it is custom. |
||||||
|
if has_key(s:configured_buffers, bufnr) |
||||||
|
let old_registration = copy(get(s:configured_buffers, bufnr, {})) |
||||||
|
call extend(s:configured_buffers[bufnr], implicit_config, 'force') |
||||||
|
else |
||||||
|
let s:configured_buffers[bufnr] = implicit_config |
||||||
|
|
||||||
|
augroup neomake_automake_clean |
||||||
|
autocmd BufWipeout <buffer> call s:neomake_automake_clean(expand('<abuf>')) |
||||||
|
augroup END |
||||||
|
endif |
||||||
|
|
||||||
|
if implicit_config.ignore |
||||||
|
return s:configured_buffers[bufnr] |
||||||
|
endif |
||||||
|
|
||||||
|
let s:configured_buffers[bufnr].events_config = neomake#config#get('automake.events', {}) |
||||||
|
|
||||||
|
" Create jobs. |
||||||
|
let options = a:0 > 1 ? a:2 : {} |
||||||
|
if has_key(options, 'makers') |
||||||
|
let makers = neomake#map_makers(options.makers, ft, 0) |
||||||
|
let source = 'options' |
||||||
|
else |
||||||
|
let [makers, source] = neomake#config#get_with_source('automake.enabled_makers') |
||||||
|
if makers is g:neomake#config#undefined |
||||||
|
unlet makers |
||||||
|
let makers = neomake#GetEnabledMakers(ft) |
||||||
|
else |
||||||
|
let makers = neomake#map_makers(makers, ft, 0) |
||||||
|
endif |
||||||
|
endif |
||||||
|
let options = {'file_mode': 1, 'ft': ft, 'bufnr': bufnr, 'automake': 1} |
||||||
|
let jobs = neomake#core#create_jobs(options, makers) |
||||||
|
let s:configured_buffers[bufnr].maker_jobs = jobs |
||||||
|
call s:debug_log(printf('configured buffer for ft=%s (%s)', |
||||||
|
\ ft, empty(jobs) ? 'no enabled makers' : join(map(copy(jobs), 'v:val.maker.name'), ', ').' ('.source.')'), {'bufnr': bufnr}) |
||||||
|
if old_config != config |
||||||
|
call s:debug_log('resetting tick because of config changes') |
||||||
|
call setbufvar(bufnr, '_neomake_automake_tick', []) |
||||||
|
elseif exists('old_registration') |
||||||
|
if old_registration != s:configured_buffers[bufnr] |
||||||
|
call s:debug_log('resetting tick because of registration changes') |
||||||
|
call setbufvar(bufnr, '_neomake_automake_tick', []) |
||||||
|
endif |
||||||
|
else |
||||||
|
call s:debug_log('setting tick for new buffer') |
||||||
|
call setbufvar(bufnr, '_neomake_automake_tick', []) |
||||||
|
endif |
||||||
|
|
||||||
|
if a:0 |
||||||
|
" Setup autocommands etc (when called manually)?! |
||||||
|
call neomake#configure#automake() |
||||||
|
endif |
||||||
|
return config |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:maybe_reconfigure_buffer(bufnr) abort |
||||||
|
if has_key(s:configured_buffers, a:bufnr) && !s:configured_buffers[a:bufnr].custom |
||||||
|
call s:configure_buffer(a:bufnr) |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
|
||||||
|
" Called from autocommands. |
||||||
|
function! s:neomake_automake(event, bufnr) abort |
||||||
|
let disabled = neomake#config#get_with_source('disabled', 0) |
||||||
|
if disabled[0] |
||||||
|
call s:debug_log(printf('disabled (%s)', disabled[1])) |
||||||
|
return |
||||||
|
endif |
||||||
|
let bufnr = +a:bufnr |
||||||
|
|
||||||
|
if has_key(s:configured_buffers, bufnr) |
||||||
|
let buffer_config = s:configured_buffers[bufnr] |
||||||
|
else |
||||||
|
" Register the buffer, and remember that it's automatic. |
||||||
|
let buffer_config = s:configure_buffer(bufnr) |
||||||
|
endif |
||||||
|
if get(buffer_config, 'ignore', 0) |
||||||
|
" NOTE: might be too verbose. |
||||||
|
call s:debug_log('buffer is ignored') |
||||||
|
return |
||||||
|
endif |
||||||
|
|
||||||
|
if s:need_to_skip_first_textchanged && a:event ==# 'TextChanged' |
||||||
|
if !getbufvar(bufnr, '_neomake_seen_TextChanged', 0) |
||||||
|
call s:debug_log('ignoring first TextChanged') |
||||||
|
call setbufvar(bufnr, '_neomake_seen_TextChanged', 1) |
||||||
|
return |
||||||
|
endif |
||||||
|
endif |
||||||
|
|
||||||
|
call s:debug_log(printf('handling event %s', a:event), {'bufnr': bufnr}) |
||||||
|
|
||||||
|
if empty(s:configured_buffers[bufnr].maker_jobs) |
||||||
|
call s:debug_log('no enabled makers', {'bufnr': bufnr}) |
||||||
|
return |
||||||
|
endif |
||||||
|
|
||||||
|
call s:debug_log(printf('automake for event %s', a:event), {'bufnr': bufnr}) |
||||||
|
let config = s:configured_buffers[bufnr].events_config |
||||||
|
if !has_key(config, a:event) |
||||||
|
call s:debug_log('event is not registered', {'bufnr': bufnr}) |
||||||
|
return |
||||||
|
endif |
||||||
|
let config = config[a:event] |
||||||
|
|
||||||
|
let event = a:event |
||||||
|
let bufnr = +a:bufnr |
||||||
|
" TODO: rename to neomake.automake.delay |
||||||
|
let delay = get(config, 'delay', s:get_setting('automake_delay', s:default_delay)) |
||||||
|
let context = { |
||||||
|
\ 'delay': delay, |
||||||
|
\ 'bufnr': bufnr, |
||||||
|
\ 'event': a:event, |
||||||
|
\ 'maker_jobs': s:configured_buffers[bufnr].maker_jobs, |
||||||
|
\ } |
||||||
|
if event ==# 'BufWinEnter' |
||||||
|
" Ignore context, so that e.g. with vim-stay restoring the view |
||||||
|
" (cursor position), it will still be triggered. |
||||||
|
let context.pos = [] |
||||||
|
endif |
||||||
|
call s:neomake_do_automake(context) |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:stop_timer(timer) abort |
||||||
|
let timer_info = s:timer_info[a:timer] |
||||||
|
unlet s:timer_info[a:timer] |
||||||
|
unlet s:timer_by_bufnr[timer_info.bufnr] |
||||||
|
call timer_stop(+a:timer) |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:stop_timers() abort |
||||||
|
let timers = keys(s:timer_info) |
||||||
|
if !empty(timers) |
||||||
|
call s:debug_log(printf('stopping timers: %s', join(timers, ', '))) |
||||||
|
for timer in timers |
||||||
|
call s:stop_timer(timer) |
||||||
|
endfor |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#configure#reset_automake() abort |
||||||
|
for bufnr in keys(s:configured_buffers) |
||||||
|
call s:neomake_automake_clean(bufnr) |
||||||
|
endfor |
||||||
|
let s:registered_events = [] |
||||||
|
call s:stop_timers() |
||||||
|
call neomake#configure#automake() |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:neomake_automake_clean(bufnr) abort |
||||||
|
if has_key(s:timer_by_bufnr, a:bufnr) |
||||||
|
let timer = s:timer_by_bufnr[a:bufnr] |
||||||
|
call s:stop_timer(timer) |
||||||
|
call s:debug_log('stopped timer for cleaned buffer: '.timer) |
||||||
|
endif |
||||||
|
if has_key(s:configured_buffers, a:bufnr) |
||||||
|
unlet s:configured_buffers[a:bufnr] |
||||||
|
augroup neomake_automake_clean |
||||||
|
exe printf('au! * <buffer=%d>', a:bufnr) |
||||||
|
augroup END |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#configure#disable_automake() abort |
||||||
|
call s:debug_log('disabling globally') |
||||||
|
call s:stop_timers() |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#configure#disable_automake_for_buffer(bufnr) abort |
||||||
|
call s:debug_log(printf('disabling buffer %d', a:bufnr)) |
||||||
|
if has_key(s:timer_by_bufnr, a:bufnr) |
||||||
|
let timer = s:timer_by_bufnr[a:bufnr] |
||||||
|
call s:stop_timer(timer) |
||||||
|
call s:debug_log('stopped timer for buffer: '.timer) |
||||||
|
endif |
||||||
|
if has_key(s:configured_buffers, a:bufnr) |
||||||
|
let s:configured_buffers[a:bufnr].disabled = 1 |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#configure#enable_automake_for_buffer(bufnr) abort |
||||||
|
if exists('s:configured_buffers[a:bufnr].disabled') |
||||||
|
call s:debug_log(printf('Re-enabled buffer %d', a:bufnr)) |
||||||
|
unlet s:configured_buffers[a:bufnr].disabled |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#configure#reset_automake_for_buffer(...) abort |
||||||
|
let bufnr = a:0 ? +a:1 : bufnr('%') |
||||||
|
call s:neomake_automake_clean(bufnr) |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#configure#automake(...) abort |
||||||
|
call s:debug_log(printf('configuring automake: %s', string(a:000))) |
||||||
|
if !exists('g:neomake') |
||||||
|
let g:neomake = {} |
||||||
|
endif |
||||||
|
if a:0 |
||||||
|
call call('s:parse_events_from_args', [g:neomake] + a:000) |
||||||
|
endif |
||||||
|
|
||||||
|
let disabled_globally = get(get(g:, 'neomake', {}), 'disabled', 0) |
||||||
|
if disabled_globally |
||||||
|
let s:registered_events = [] |
||||||
|
else |
||||||
|
let s:registered_events = keys(get(get(g:neomake, 'automake', {}), 'events', {})) |
||||||
|
endif |
||||||
|
" Keep custom configured buffers. |
||||||
|
call filter(s:configured_buffers, 'v:val.custom') |
||||||
|
for b in keys(s:configured_buffers) |
||||||
|
if empty(s:configured_buffers[b].maker_jobs) |
||||||
|
continue |
||||||
|
endif |
||||||
|
if get(s:configured_buffers[b], 'disabled', 0) |
||||||
|
continue |
||||||
|
endif |
||||||
|
let b_cfg = neomake#config#get('b:automake.events', {}) |
||||||
|
for event_config in items(b_cfg) |
||||||
|
let event = event_config[0] |
||||||
|
if index(s:registered_events, event) == -1 |
||||||
|
call add(s:registered_events, event) |
||||||
|
endif |
||||||
|
endfor |
||||||
|
endfor |
||||||
|
call s:debug_log('registered events: '.join(s:registered_events, ', ')) |
||||||
|
|
||||||
|
augroup neomake_automake |
||||||
|
au! |
||||||
|
for event in s:registered_events |
||||||
|
exe 'autocmd '.event." * call s:neomake_automake('".event."', expand('<abuf>'))" |
||||||
|
endfor |
||||||
|
augroup END |
||||||
|
if empty(s:registered_events) |
||||||
|
augroup! neomake_automake |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
|
||||||
|
augroup neomake_automake_base |
||||||
|
au! |
||||||
|
autocmd FileType * call s:maybe_reconfigure_buffer(expand('<abuf>')) |
||||||
|
augroup END |
||||||
|
" vim: ts=4 sw=4 et |
@ -0,0 +1,127 @@ |
|||||||
|
let g:neomake#core#valid_maker_name_pattern = '\v^\w+$' |
||||||
|
|
||||||
|
let g:neomake#core#_ignore_autocommands = 0 |
||||||
|
|
||||||
|
function! neomake#core#create_jobs(options, makers) abort |
||||||
|
let args = [a:options, a:makers] |
||||||
|
let jobs = call('s:bind_makers_for_job', args) |
||||||
|
return jobs |
||||||
|
endfunction |
||||||
|
|
||||||
|
" Map/bind a:makers to a list of job options, using a:options. |
||||||
|
function! s:bind_makers_for_job(options, makers) abort |
||||||
|
let r = [] |
||||||
|
for maker in a:makers |
||||||
|
let options = copy(a:options) |
||||||
|
try |
||||||
|
let maker = neomake#core#instantiate_maker(maker, options, 1) |
||||||
|
catch /^Neomake: skip_job: / |
||||||
|
let msg = substitute(v:exception, '^Neomake: skip_job: ', '', '') |
||||||
|
call neomake#log#debug(printf('%s: skipping job: %s.', |
||||||
|
\ maker.name, msg), options) |
||||||
|
continue |
||||||
|
catch /^Neomake: / |
||||||
|
let error = substitute(v:exception, '^Neomake: ', '', '').'.' |
||||||
|
call neomake#log#error(error, options) |
||||||
|
continue |
||||||
|
endtry |
||||||
|
if !empty(maker) |
||||||
|
let options.maker = maker |
||||||
|
let r += [options] |
||||||
|
endif |
||||||
|
endfor |
||||||
|
return r |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#core#instantiate_maker(maker, options, check_exe) abort |
||||||
|
let maker = a:maker |
||||||
|
let options = a:options |
||||||
|
let ft = get(options, 'ft', '') |
||||||
|
let bufnr = get(options, 'bufnr', '') |
||||||
|
|
||||||
|
" Call InitForJob function in maker object, if any. |
||||||
|
let l:Init = neomake#utils#GetSetting('InitForJob', maker, g:neomake#config#undefined, ft, bufnr) |
||||||
|
if empty(Init) |
||||||
|
" Deprecated: should use InitForJob instead. |
||||||
|
if has_key(maker, 'fn') |
||||||
|
unlet Init " vim73 |
||||||
|
let l:Init = maker.fn |
||||||
|
call neomake#log#warn_once(printf("Please use 'InitForJob' instead of 'fn' for maker %s.", maker.name), |
||||||
|
\ printf('deprecated-fn-%s', maker.name)) |
||||||
|
endif |
||||||
|
endif |
||||||
|
if !empty(Init) |
||||||
|
let returned_maker = call(Init, [options], maker) |
||||||
|
if returned_maker isnot# 0 |
||||||
|
" This conditional assignment allows to both return a copy |
||||||
|
" (factory), while also can be used as a init method. |
||||||
|
let maker = returned_maker |
||||||
|
endif |
||||||
|
endif |
||||||
|
|
||||||
|
if has_key(maker, '_bind_args') |
||||||
|
call maker._bind_args() |
||||||
|
if type(maker.exe) != type('') |
||||||
|
let error = printf('Non-string given for executable of maker %s: type %s', |
||||||
|
\ maker.name, type(maker.exe)) |
||||||
|
if !get(maker, 'auto_enabled', 0) |
||||||
|
throw 'Neomake: '.error |
||||||
|
endif |
||||||
|
call neomake#log#debug(error.'.', options) |
||||||
|
return {} |
||||||
|
endif |
||||||
|
if a:check_exe && !executable(maker.exe) |
||||||
|
if get(maker, 'auto_enabled', 0) |
||||||
|
call neomake#log#debug(printf( |
||||||
|
\ 'Exe (%s) of auto-configured maker %s is not executable, skipping.', maker.exe, maker.name), options) |
||||||
|
else |
||||||
|
let error = printf('Exe (%s) of maker %s is not executable', maker.exe, maker.name) |
||||||
|
throw 'Neomake: '.error |
||||||
|
endif |
||||||
|
return {} |
||||||
|
endif |
||||||
|
endif |
||||||
|
return maker |
||||||
|
endfunction |
||||||
|
|
||||||
|
" Base class for command makers. |
||||||
|
let g:neomake#core#command_maker_base = {} |
||||||
|
|
||||||
|
function! g:neomake#core#command_maker_base._get_fname_for_args(jobinfo) abort dict |
||||||
|
" Append file? (defaults to jobinfo.file_mode, project/global makers should set it to 0) |
||||||
|
let append_file = neomake#utils#GetSetting('append_file', self, a:jobinfo.file_mode, a:jobinfo.ft, a:jobinfo.bufnr) |
||||||
|
" Use stdin? (checked here always to work without setting "uses_filename"). |
||||||
|
let uses_stdin = neomake#utils#GetSetting('uses_stdin', self, g:neomake#config#undefined, a:jobinfo.ft, a:jobinfo.bufnr) |
||||||
|
if uses_stdin isnot g:neomake#config#undefined |
||||||
|
let a:jobinfo.uses_stdin = uses_stdin |
||||||
|
call neomake#log#debug(printf('Using uses_stdin (%s) from setting.', |
||||||
|
\ a:jobinfo.uses_stdin), a:jobinfo) |
||||||
|
endif |
||||||
|
" Use/generate a filename? (defaults to 1 if tempfile_name is set) |
||||||
|
let uses_filename = append_file || neomake#utils#GetSetting('uses_filename', self, has_key(self, 'tempfile_name'), a:jobinfo.ft, a:jobinfo.bufnr) |
||||||
|
if append_file || uses_filename || !empty(uses_stdin) |
||||||
|
let filename = self._get_fname_for_buffer(a:jobinfo) |
||||||
|
if append_file |
||||||
|
return filename |
||||||
|
endif |
||||||
|
endif |
||||||
|
return '' |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! g:neomake#core#command_maker_base._get_argv(_jobinfo) abort dict |
||||||
|
return neomake#compat#get_argv(self.exe, self.args, type(self.args) == type([])) |
||||||
|
endfunction |
||||||
|
|
||||||
|
" Get tabnr and winnr for a given make ID. |
||||||
|
function! neomake#core#get_tabwin_for_makeid(make_id) abort |
||||||
|
let curtab = tabpagenr() |
||||||
|
for t in [curtab] + range(1, curtab-1) + range(curtab+1, tabpagenr('$')) |
||||||
|
for w in range(1, tabpagewinnr(t, '$')) |
||||||
|
if index(neomake#compat#gettabwinvar(t, w, 'neomake_make_ids', []), a:make_id) != -1 |
||||||
|
return [t, w] |
||||||
|
endif |
||||||
|
endfor |
||||||
|
endfor |
||||||
|
return [-1, -1] |
||||||
|
endfunction |
||||||
|
" vim: ts=4 sw=4 et |
@ -0,0 +1,274 @@ |
|||||||
|
" Debug/feedback helpers. |
||||||
|
|
||||||
|
function! neomake#debug#pprint(d, ...) abort |
||||||
|
return call('s:pprint', [a:d] + a:000) |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:pprint(v, ...) abort |
||||||
|
let indent = a:0 ? a:1 : '' |
||||||
|
if type(a:v) ==# type({}) |
||||||
|
if empty(a:v) |
||||||
|
return '{}' |
||||||
|
endif |
||||||
|
let r = "{\n" |
||||||
|
for [k, l:V] in items(a:v) |
||||||
|
let r .= printf("%s %s: %s,\n", |
||||||
|
\ indent, |
||||||
|
\ string(k), |
||||||
|
\ s:pprint(neomake#utils#fix_self_ref(V), indent . ' ')) |
||||||
|
unlet V " old-vim |
||||||
|
endfor |
||||||
|
let r .= indent.'}' |
||||||
|
return r |
||||||
|
elseif type(a:v) ==# type([]) |
||||||
|
if empty(a:v) |
||||||
|
return '[]' |
||||||
|
endif |
||||||
|
let r = '['."\n".join(map(copy(a:v), 'indent." ".s:pprint(v:val, indent." ")'), ",\n").",\n".indent.']' |
||||||
|
return r |
||||||
|
endif |
||||||
|
return string(a:v) |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#debug#validate_maker(maker) abort |
||||||
|
let issues = {'errors': [], 'warnings': []} |
||||||
|
|
||||||
|
if has_key(a:maker, 'process_json') && has_key(a:maker, 'process_output') |
||||||
|
let issues.warnings += ['maker has process_json and process_output, but only process_json will be used.'] |
||||||
|
let check_process = ['process_json'] |
||||||
|
else |
||||||
|
let check_process = ['process_json', 'process_output'] |
||||||
|
endif |
||||||
|
|
||||||
|
for f in check_process |
||||||
|
if has_key(a:maker, f) |
||||||
|
if has_key(a:maker, 'mapexpr') |
||||||
|
let issues.warnings += [printf( |
||||||
|
\ 'maker has mapexpr, but only %s will be used.', |
||||||
|
\ f)] |
||||||
|
endif |
||||||
|
if has_key(a:maker, 'postprocess') |
||||||
|
let issues.warnings += [printf( |
||||||
|
\ 'maker has postprocess, but only %s will be used.', |
||||||
|
\ f)] |
||||||
|
endif |
||||||
|
if has_key(a:maker, 'errorformat') |
||||||
|
let issues.warnings += [printf( |
||||||
|
\ 'maker has errorformat, but only %s will be used.', |
||||||
|
\ f)] |
||||||
|
endif |
||||||
|
endif |
||||||
|
endfor |
||||||
|
|
||||||
|
let jobinfo = neomake#jobinfo#new() |
||||||
|
try |
||||||
|
let maker = neomake#core#instantiate_maker(a:maker, jobinfo, 0) |
||||||
|
if !executable(maker.exe) |
||||||
|
let t = get(maker, 'auto_enabled', 0) ? 'warnings' : 'errors' |
||||||
|
let issues[t] += [printf("maker's exe (%s) is not executable.", maker.exe)] |
||||||
|
endif |
||||||
|
catch /^Neomake: / |
||||||
|
let issues.errors += [substitute(v:exception, '^Neomake: ', '', '').'.'] |
||||||
|
endtry |
||||||
|
|
||||||
|
if has_key(a:maker, 'name') |
||||||
|
if a:maker.name !~# g:neomake#core#valid_maker_name_pattern |
||||||
|
call add(issues['errors'], printf( |
||||||
|
\ 'Invalid maker name: %s (should match %s)', |
||||||
|
\ string(a:maker.name), |
||||||
|
\ string(g:neomake#core#valid_maker_name_pattern))) |
||||||
|
endif |
||||||
|
endif |
||||||
|
|
||||||
|
return issues |
||||||
|
endfunction |
||||||
|
|
||||||
|
" Optional arg: ft |
||||||
|
function! s:get_makers_info(...) abort |
||||||
|
let maker_names = call('neomake#GetEnabledMakers', a:000) |
||||||
|
if empty(maker_names) |
||||||
|
return ['None.'] |
||||||
|
endif |
||||||
|
let maker_defaults = g:neomake#config#_defaults['maker_defaults'] |
||||||
|
let r = [] |
||||||
|
for maker_name in maker_names |
||||||
|
let maker = call('neomake#GetMaker', [maker_name] + a:000) |
||||||
|
let r += [' - '.maker.name] |
||||||
|
let r += map(s:get_maker_info(maker, maker_defaults), "' '.v:val") |
||||||
|
endfor |
||||||
|
return r |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:get_maker_info(maker, ...) abort |
||||||
|
let maker_defaults = a:0 ? a:1 : {} |
||||||
|
let maker = a:maker |
||||||
|
let r = [] |
||||||
|
for [k, l:V] in sort(copy(items(maker))) |
||||||
|
if k !=# 'name' && k !=# 'ft' && k !~# '^_' |
||||||
|
if !has_key(maker_defaults, k) |
||||||
|
\ || type(V) != type(maker_defaults[k]) |
||||||
|
\ || V !=# maker_defaults[k] |
||||||
|
let r += [' - '.k.': '.string(V)] |
||||||
|
endif |
||||||
|
endif |
||||||
|
unlet V " vim73 |
||||||
|
endfor |
||||||
|
|
||||||
|
let issues = neomake#debug#validate_maker(maker) |
||||||
|
if !empty(issues) |
||||||
|
for type in sort(copy(keys(issues))) |
||||||
|
let items = issues[type] |
||||||
|
if !empty(items) |
||||||
|
let r += [' - '.toupper(type) . ':'] |
||||||
|
for issue in items |
||||||
|
let r += [' - ' . issue] |
||||||
|
endfor |
||||||
|
endif |
||||||
|
endfor |
||||||
|
endif |
||||||
|
|
||||||
|
if type(maker.exe) == type('') && executable(maker.exe) |
||||||
|
let version_arg = get(maker, 'version_arg', '--version') |
||||||
|
let exe = exists('*exepath') ? exepath(maker.exe) : maker.exe |
||||||
|
let version_output = neomake#compat#systemlist([exe, version_arg]) |
||||||
|
if empty(version_output) |
||||||
|
let version_output = [printf( |
||||||
|
\ 'failed to get version information (%s)', |
||||||
|
\ v:shell_error)] |
||||||
|
endif |
||||||
|
let r += [printf(' - version information (%s %s): %s', |
||||||
|
\ exe, |
||||||
|
\ version_arg, |
||||||
|
\ join(version_output, "\n "))] |
||||||
|
endif |
||||||
|
return r |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:get_fts_with_makers() abort |
||||||
|
return neomake#compat#uniq(sort(map(split(globpath(escape(&runtimepath, ' '), |
||||||
|
\ 'autoload/neomake/makers/ft/*.vim'), "\n"), |
||||||
|
\ 'fnamemodify(v:val, ":t:r")'))) |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#debug#get_maker_info(maker_name) abort |
||||||
|
let source = '' |
||||||
|
let maker = neomake#get_maker_by_name(a:maker_name, &filetype) |
||||||
|
if empty(maker) |
||||||
|
let maker = neomake#get_maker_by_name(a:maker_name) |
||||||
|
if empty(maker) |
||||||
|
let fts = filter(s:get_fts_with_makers(), 'v:val != &filetype') |
||||||
|
for ft in fts |
||||||
|
let maker = neomake#get_maker_by_name(a:maker_name, ft) |
||||||
|
if !empty(maker) |
||||||
|
let source = 'filetype '.ft |
||||||
|
break |
||||||
|
endif |
||||||
|
endfor |
||||||
|
else |
||||||
|
let source = 'project maker' |
||||||
|
endif |
||||||
|
endif |
||||||
|
if empty(maker) |
||||||
|
call neomake#log#error(printf('Maker not found: %s.', a:maker_name)) |
||||||
|
return [] |
||||||
|
endif |
||||||
|
let maker = neomake#create_maker_object(maker, &filetype) |
||||||
|
return [maker.name . (empty(source) ? '' : ' ('.source.')')] |
||||||
|
\ + s:get_maker_info(maker) |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#debug#display_info(...) abort |
||||||
|
let bang = a:0 ? a:1 : 0 |
||||||
|
if a:0 > 1 |
||||||
|
let maker_name = a:2 |
||||||
|
let lines = neomake#debug#get_maker_info(maker_name) |
||||||
|
else |
||||||
|
let lines = neomake#debug#_get_info_lines() |
||||||
|
endif |
||||||
|
if bang |
||||||
|
try |
||||||
|
call setreg('+', join(lines, "\n"), 'l') |
||||||
|
catch |
||||||
|
call neomake#log#error(printf( |
||||||
|
\ 'Could not set clipboard: %s.', v:exception)) |
||||||
|
return |
||||||
|
endtry |
||||||
|
echom 'Copied Neomake info to clipboard ("+).' |
||||||
|
else |
||||||
|
echon join(lines, "\n") |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:trim(s) abort |
||||||
|
return substitute(a:s, '\v^[ \t\r\n]+|[ \t\r\n]+$', '', 'g') |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#debug#_get_info_lines() abort |
||||||
|
let r = [] |
||||||
|
let ft = &filetype |
||||||
|
|
||||||
|
let r += ['#### Neomake debug information'] |
||||||
|
let r += [''] |
||||||
|
let r += ['Async support: '.neomake#has_async_support()] |
||||||
|
let r += ['Current filetype: '.ft] |
||||||
|
let r += ['Windows: '.neomake#utils#IsRunningWindows()] |
||||||
|
let r += ['[shell, shellcmdflag, shellslash]: '.string([&shell, &shellcmdflag, &shellslash])] |
||||||
|
let r += [join(map(split(neomake#utils#redir('verb set makeprg?'), '\n'), 's:trim(v:val)'), ', ')] |
||||||
|
|
||||||
|
let r += [''] |
||||||
|
let r += ['##### Enabled makers'] |
||||||
|
let r += [''] |
||||||
|
let r += ['For the current filetype ("'.ft.'", used with :Neomake):'] |
||||||
|
let r += s:get_makers_info(ft) |
||||||
|
if empty(ft) |
||||||
|
let r += ['NOTE: the current buffer does not have a filetype.'] |
||||||
|
else |
||||||
|
let conf_ft = neomake#utils#get_ft_confname(ft) |
||||||
|
let r += ['NOTE: you can define g:neomake_'.conf_ft.'_enabled_makers' |
||||||
|
\ .' to configure it (or b:neomake_'.conf_ft.'_enabled_makers).'] |
||||||
|
endif |
||||||
|
let r += [''] |
||||||
|
let r += ['For the project (used with :Neomake!):'] |
||||||
|
let r += s:get_makers_info() |
||||||
|
let r += ['NOTE: you can define g:neomake_enabled_makers to configure it.'] |
||||||
|
let r += [''] |
||||||
|
let r += ['Default maker settings:'] |
||||||
|
for [k, v] in items(neomake#config#get('maker_defaults')) |
||||||
|
let r += [' - '.k.': '.string(v)] |
||||||
|
unlet! v " Fix variable type mismatch with Vim 7.3. |
||||||
|
endfor |
||||||
|
let r += [''] |
||||||
|
let r += ['##### Settings'] |
||||||
|
let r += [''] |
||||||
|
let r += ['###### New-style (dict, overrides old-style)'] |
||||||
|
let r += [''] |
||||||
|
let r += ['```'] |
||||||
|
|
||||||
|
let r += ['g:neomake: '.(exists('g:neomake') ? s:pprint(g:neomake) : 'unset')] |
||||||
|
let r += ['b:neomake: '.(exists('b:neomake') ? s:pprint(b:neomake) : 'unset')] |
||||||
|
let r += ['```'] |
||||||
|
let r += [''] |
||||||
|
let r += ['###### Old-style'] |
||||||
|
let r += [''] |
||||||
|
let r += ['```'] |
||||||
|
for [k, V] in sort(items(filter(copy(g:), "v:key =~# '^neomake_'"))) |
||||||
|
let r += ['g:'.k.' = '.string(V)] |
||||||
|
unlet! V " Fix variable type mismatch with Vim 7.3. |
||||||
|
endfor |
||||||
|
let r += [''] |
||||||
|
let r += ['```'] |
||||||
|
let r += ["\n"] |
||||||
|
let r += ['#### :version'] |
||||||
|
let r += [''] |
||||||
|
let r += ['```'] |
||||||
|
let r += split(neomake#utils#redir('version'), '\n') |
||||||
|
let r += ['```'] |
||||||
|
let r += [''] |
||||||
|
let r += ['#### :messages'] |
||||||
|
let r += [''] |
||||||
|
let r += ['```'] |
||||||
|
let r += split(neomake#utils#redir('messages'), '\n') |
||||||
|
let r += ['```'] |
||||||
|
return r |
||||||
|
endfunction |
||||||
|
" vim: ts=4 sw=4 et |
@ -0,0 +1,155 @@ |
|||||||
|
" vim: ts=4 sw=4 et |
||||||
|
|
||||||
|
let s:highlights = {'file': {}, 'project': {}} |
||||||
|
let s:highlight_types = { |
||||||
|
\ 'E': 'NeomakeError', |
||||||
|
\ 'W': 'NeomakeWarning', |
||||||
|
\ 'I': 'NeomakeInfo', |
||||||
|
\ 'M': 'NeomakeMessage' |
||||||
|
\ } |
||||||
|
|
||||||
|
let s:nvim_api = exists('*nvim_buf_add_highlight') |
||||||
|
|
||||||
|
" Used in tests. |
||||||
|
function! neomake#highlights#_get() abort |
||||||
|
return s:highlights |
||||||
|
endfunction |
||||||
|
|
||||||
|
if s:nvim_api |
||||||
|
function! s:InitBufHighlights(type, buf) abort |
||||||
|
if !bufexists(a:buf) |
||||||
|
" The buffer might be wiped by now: prevent 'Invalid buffer id'. |
||||||
|
return |
||||||
|
endif |
||||||
|
if has_key(s:highlights[a:type], a:buf) |
||||||
|
call nvim_buf_clear_highlight(a:buf, s:highlights[a:type][a:buf], 0, -1) |
||||||
|
else |
||||||
|
let s:highlights[a:type][a:buf] = nvim_buf_add_highlight(a:buf, 0, '', 0, 0, -1) |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:reset(type, buf) abort |
||||||
|
if has_key(s:highlights[a:type], a:buf) |
||||||
|
call nvim_buf_clear_highlight(a:buf, s:highlights[a:type][a:buf], 0, -1) |
||||||
|
unlet s:highlights[a:type][a:buf] |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
else |
||||||
|
function! s:InitBufHighlights(type, buf) abort |
||||||
|
let s:highlights[a:type][a:buf] = { |
||||||
|
\ 'NeomakeError': [], |
||||||
|
\ 'NeomakeWarning': [], |
||||||
|
\ 'NeomakeInfo': [], |
||||||
|
\ 'NeomakeMessage': [] |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:reset(type, buf) abort |
||||||
|
if has_key(s:highlights[a:type], a:buf) |
||||||
|
unlet s:highlights[a:type][a:buf] |
||||||
|
call neomake#highlights#ShowHighlights() |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
endif |
||||||
|
|
||||||
|
function! neomake#highlights#ResetFile(buf) abort |
||||||
|
call s:reset('file', a:buf) |
||||||
|
endfunction |
||||||
|
function! neomake#highlights#ResetProject(...) abort |
||||||
|
if a:0 " deprecated a:buf |
||||||
|
call neomake#log#warn_once('neomake#highlights#ResetProject does not use a:buf anymore.', |
||||||
|
\ 'deprecated-highlight-resetproject') |
||||||
|
endif |
||||||
|
for buf in keys(s:highlights['project']) |
||||||
|
call s:reset('project', +buf) |
||||||
|
endfor |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#highlights#AddHighlight(entry, type) abort |
||||||
|
" Some makers use line 0 for file warnings (which cannot be highlighted, |
||||||
|
" e.g. cpplint with "no copyright" warnings). |
||||||
|
if a:entry.lnum == 0 |
||||||
|
return |
||||||
|
endif |
||||||
|
|
||||||
|
if !has_key(s:highlights[a:type], a:entry.bufnr) |
||||||
|
call s:InitBufHighlights(a:type, a:entry.bufnr) |
||||||
|
endif |
||||||
|
let hi = get(s:highlight_types, toupper(a:entry.type), 'NeomakeError') |
||||||
|
|
||||||
|
if a:entry.col > 0 && get(g:, 'neomake_highlight_columns', 1) |
||||||
|
let length = get(a:entry, 'length', 1) |
||||||
|
if s:nvim_api |
||||||
|
call nvim_buf_add_highlight(a:entry.bufnr, s:highlights[a:type][a:entry.bufnr], hi, a:entry.lnum - 1, a:entry.col - 1, a:entry.col + length - 1) |
||||||
|
else |
||||||
|
call add(s:highlights[a:type][a:entry.bufnr][hi], [a:entry.lnum, a:entry.col, length]) |
||||||
|
endif |
||||||
|
elseif get(g:, 'neomake_highlight_lines', 0) |
||||||
|
if s:nvim_api |
||||||
|
call nvim_buf_add_highlight(a:entry.bufnr, s:highlights[a:type][a:entry.bufnr], hi, a:entry.lnum - 1, 0, -1) |
||||||
|
else |
||||||
|
call add(s:highlights[a:type][a:entry.bufnr][hi], a:entry.lnum) |
||||||
|
endif |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
|
||||||
|
if s:nvim_api |
||||||
|
function! neomake#highlights#ShowHighlights() abort |
||||||
|
endfunction |
||||||
|
else |
||||||
|
function! neomake#highlights#ShowHighlights() abort |
||||||
|
if exists('w:neomake_highlights') |
||||||
|
for highlight in w:neomake_highlights |
||||||
|
try |
||||||
|
call matchdelete(highlight) |
||||||
|
catch /^Vim\%((\a\+)\)\=:E803/ |
||||||
|
endtry |
||||||
|
endfor |
||||||
|
endif |
||||||
|
let w:neomake_highlights = [] |
||||||
|
|
||||||
|
let buf = bufnr('%') |
||||||
|
for type in ['file', 'project'] |
||||||
|
for [hi, locs] in items(filter(copy(get(s:highlights[type], buf, {})), '!empty(v:val)')) |
||||||
|
if exists('*matchaddpos') |
||||||
|
call add(w:neomake_highlights, matchaddpos(hi, locs)) |
||||||
|
else |
||||||
|
for loc in locs |
||||||
|
if len(loc) == 1 |
||||||
|
call add(w:neomake_highlights, matchadd(hi, '\%' . loc[0] . 'l')) |
||||||
|
else |
||||||
|
call add(w:neomake_highlights, matchadd(hi, '\%' . loc[0] . 'l\%' . loc[1] . 'c.\{' . loc[2] . '}')) |
||||||
|
endif |
||||||
|
endfor |
||||||
|
endif |
||||||
|
endfor |
||||||
|
endfor |
||||||
|
endfunction |
||||||
|
endif |
||||||
|
|
||||||
|
function! neomake#highlights#DefineHighlights() abort |
||||||
|
for [group, link] in items({ |
||||||
|
\ 'NeomakeError': 'SpellBad', |
||||||
|
\ 'NeomakeWarning': 'SpellCap', |
||||||
|
\ 'NeomakeInfo': 'NeomakeWarning', |
||||||
|
\ 'NeomakeMessage': 'NeomakeWarning' |
||||||
|
\ }) |
||||||
|
if !neomake#utils#highlight_is_defined(group) |
||||||
|
exe 'highlight link '.group.' '.link |
||||||
|
endif |
||||||
|
endfor |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:wipe_highlights(bufnr) abort |
||||||
|
for type in ['file', 'project'] |
||||||
|
if has_key(s:highlights[type], a:bufnr) |
||||||
|
unlet s:highlights[type][a:bufnr] |
||||||
|
endif |
||||||
|
endfor |
||||||
|
endfunction |
||||||
|
augroup neomake_highlights |
||||||
|
au! |
||||||
|
autocmd BufWipeout * call s:wipe_highlights(expand('<abuf>')) |
||||||
|
augroup END |
||||||
|
|
||||||
|
call neomake#highlights#DefineHighlights() |
@ -0,0 +1,93 @@ |
|||||||
|
let s:jobinfo_base = { |
||||||
|
\ 'cd_back_cmd': '', |
||||||
|
\ 'pending_output': [], |
||||||
|
\ 'file_mode': 1, |
||||||
|
\ } |
||||||
|
function! s:jobinfo_base.get_pid() abort |
||||||
|
if has_key(self, 'vim_job') |
||||||
|
let info = job_info(self.vim_job) |
||||||
|
if info.status ==# 'run' |
||||||
|
return info.process |
||||||
|
endif |
||||||
|
return -1 |
||||||
|
endif |
||||||
|
try |
||||||
|
return jobpid(self.nvim_job) |
||||||
|
catch /^Vim(return):E900:/ |
||||||
|
return -1 |
||||||
|
endtry |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:jobinfo_base.as_string() abort |
||||||
|
let extra = [] |
||||||
|
for k in ['canceled', 'finished'] |
||||||
|
if get(self, k, 0) |
||||||
|
let extra += [k] |
||||||
|
endif |
||||||
|
endfor |
||||||
|
return printf('Job %d: %s%s', self.id, self.name, |
||||||
|
\ empty(extra) ? '' : ' ['.join(extra, ', ').']') |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:jobinfo_base.cd_back() abort |
||||||
|
if !empty(self.cd_back_cmd) |
||||||
|
exe self.cd_back_cmd |
||||||
|
let self.cd_back_cmd = '' |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:jobinfo_base.cd(...) abort |
||||||
|
if a:0 |
||||||
|
if has_key(self, 'cd_from_setting') |
||||||
|
call neomake#log#debug(printf( |
||||||
|
\ 'jobinfo.cd(): keeping cwd from setting: %s.', |
||||||
|
\ string(self.cd_from_setting)), self) |
||||||
|
return '' |
||||||
|
endif |
||||||
|
let dir = a:1 |
||||||
|
else |
||||||
|
let maker = self.maker |
||||||
|
let dir = neomake#utils#GetSetting('cwd', maker, '', self.ft, self.bufnr, 1) |
||||||
|
if !empty(dir) |
||||||
|
let self.cd_from_setting = dir |
||||||
|
endif |
||||||
|
endif |
||||||
|
|
||||||
|
if dir !=# '' |
||||||
|
if dir[0:1] ==# '%:' |
||||||
|
let dir = neomake#utils#fnamemodify(self.bufnr, dir[1:]) |
||||||
|
else |
||||||
|
let dir = expand(dir, 1) |
||||||
|
endif |
||||||
|
let dir = fnamemodify(dir, ':p') |
||||||
|
" NOTE: need to keep trailing backslash with "/" and "X:\" on Windows. |
||||||
|
if dir !=# '/' && dir[-1:] ==# neomake#utils#Slash() && dir[-2] !=# ':' |
||||||
|
let dir = dir[:-2] |
||||||
|
endif |
||||||
|
else |
||||||
|
let dir = get(self, 'cwd', $HOME) |
||||||
|
endif |
||||||
|
|
||||||
|
let cur_wd = getcwd() |
||||||
|
if dir !=# cur_wd |
||||||
|
let [cd_error, cd_back_cmd] = neomake#utils#temp_cd(dir, cur_wd) |
||||||
|
if !empty(cd_error) |
||||||
|
call neomake#log#debug(printf('jobinfo.cd(): error when trying to change cwd to %s: %s.', |
||||||
|
\ dir, cd_error)) |
||||||
|
return cd_error |
||||||
|
endif |
||||||
|
let self.cwd = dir |
||||||
|
let self.cd_back_cmd = cd_back_cmd |
||||||
|
else |
||||||
|
let self.cwd = cur_wd |
||||||
|
endif |
||||||
|
return '' |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#jobinfo#new() abort |
||||||
|
let jobinfo = deepcopy(s:jobinfo_base) |
||||||
|
let jobinfo.bufnr = bufnr('%') |
||||||
|
return jobinfo |
||||||
|
endfunction |
||||||
|
|
||||||
|
" vim: ts=4 sw=4 et |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,170 @@ |
|||||||
|
let s:level_to_name = {0: 'error ', 1: 'warning', 2: 'verbose', 3: 'debug '} |
||||||
|
let s:name_to_level = {'error': 0, 'warning': 1, 'verbose': 2, 'debug': 3} |
||||||
|
let s:short_level_to_name = {0: 'E', 1: 'W', 2: 'V', 3: 'D'} |
||||||
|
let s:is_testing = exists('g:neomake_test_messages') |
||||||
|
let s:pid = getpid() |
||||||
|
|
||||||
|
if !exists('s:last_msg_ts') |
||||||
|
let s:last_msg_ts = neomake#compat#reltimefloat() |
||||||
|
endif |
||||||
|
|
||||||
|
function! s:reltime_lastmsg() abort |
||||||
|
let cur = neomake#compat#reltimefloat() |
||||||
|
let diff = (cur - s:last_msg_ts) |
||||||
|
let s:last_msg_ts = cur |
||||||
|
|
||||||
|
if diff < 0.01 |
||||||
|
return ' ' |
||||||
|
elseif diff < 10 |
||||||
|
let format = '+%.2f' |
||||||
|
elseif diff < 100 |
||||||
|
let format = '+%.1f' |
||||||
|
elseif diff < 100 |
||||||
|
let format = ' +%.0f' |
||||||
|
elseif diff < 1000 |
||||||
|
let format = ' +%.0f' |
||||||
|
else |
||||||
|
let format = '+%.0f' |
||||||
|
endif |
||||||
|
return printf(format, diff) |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:log(level, msg, ...) abort |
||||||
|
let context = a:0 ? a:1 : {} |
||||||
|
let verbosity = neomake#utils#get_verbosity(context) |
||||||
|
let logfile = get(g:, 'neomake_logfile', '') |
||||||
|
|
||||||
|
if !s:is_testing && verbosity < a:level && empty(logfile) |
||||||
|
return |
||||||
|
endif |
||||||
|
|
||||||
|
if a:0 |
||||||
|
if has_key(a:1, 'options') |
||||||
|
let context = copy(a:1.options) |
||||||
|
let context.make_id = a:1.make_id |
||||||
|
else |
||||||
|
let context = copy(a:1) |
||||||
|
endif |
||||||
|
let msg = printf('[%s.%s:%s:%d] %s', |
||||||
|
\ get(context, 'make_id', '-'), |
||||||
|
\ get(context, 'id', '-'), |
||||||
|
\ get(context, 'bufnr', get(context, 'file_mode', 0) ? '?' : '-'), |
||||||
|
\ get(context, 'winnr', winnr()), |
||||||
|
\ a:msg) |
||||||
|
else |
||||||
|
let msg = a:msg |
||||||
|
endif |
||||||
|
|
||||||
|
" Use Vader's log for messages during tests. |
||||||
|
" @vimlint(EVL104, 1, l:timediff) |
||||||
|
if s:is_testing && (verbosity >= a:level || get(g:, 'neomake_test_log_all_messages', 0)) |
||||||
|
let timediff = s:reltime_lastmsg() |
||||||
|
if timediff !=# ' ' |
||||||
|
let test_msg = '['.s:short_level_to_name[a:level].' '.timediff.']: '.msg |
||||||
|
else |
||||||
|
let test_msg = '['.s:level_to_name[a:level].']: '.msg |
||||||
|
endif |
||||||
|
|
||||||
|
if exists('*vader#log') |
||||||
|
" Might not exist with rpcrequest-based nvim test, or throw errors |
||||||
|
" if called too early. |
||||||
|
call vader#log(test_msg) |
||||||
|
endif |
||||||
|
" Only keep context entries that are relevant for / used in the message. |
||||||
|
let context = a:0 |
||||||
|
\ ? extend(filter(copy(context), "index(['id', 'make_id', 'bufnr', 'winnr'], v:key) != -1"), {'winnr': winnr()}, 'keep') |
||||||
|
\ : {} |
||||||
|
call add(g:neomake_test_messages, [a:level, a:msg, context]) |
||||||
|
if index(['.', '!', ')', ']'], a:msg[-1:-1]) == -1 |
||||||
|
let g:neomake_test_errors += ['Log msg does not end with punctuation: "'.a:msg.'".'] |
||||||
|
endif |
||||||
|
elseif verbosity >= a:level |
||||||
|
if verbosity > 2 |
||||||
|
echom 'Neomake: '.msg |
||||||
|
else |
||||||
|
if a:level ==# 0 |
||||||
|
echohl ErrorMsg |
||||||
|
else |
||||||
|
echohl WarningMsg |
||||||
|
endif |
||||||
|
" Use message without context for non-debug msgs. |
||||||
|
echom 'Neomake: '.a:msg |
||||||
|
echohl None |
||||||
|
endif |
||||||
|
endif |
||||||
|
if !empty(logfile) |
||||||
|
if !exists('s:logfile_writefile_opts') |
||||||
|
" Use 'append' with writefile, but only if it is available. Otherwise, just |
||||||
|
" overwrite the file. 'S' is used to disable fsync in Neovim |
||||||
|
" (https://github.com/neovim/neovim/pull/6427). |
||||||
|
if has('patch-7.4.503') |
||||||
|
let s:logfile_writefile_opts = 'aS' |
||||||
|
else |
||||||
|
let s:logfile_writefile_opts = '' |
||||||
|
echohl WarningMsg |
||||||
|
echom 'Neomake: appending to the logfile is not supported in your Vim version.' |
||||||
|
echohl NONE |
||||||
|
endif |
||||||
|
endif |
||||||
|
|
||||||
|
let time = strftime('%H:%M:%S') |
||||||
|
if !exists('timediff') |
||||||
|
let timediff = s:reltime_lastmsg() |
||||||
|
endif |
||||||
|
try |
||||||
|
call writefile([printf('%s %s [%s %s] %s', |
||||||
|
\ time, s:pid, s:short_level_to_name[a:level], timediff, msg)], |
||||||
|
\ logfile, s:logfile_writefile_opts) |
||||||
|
catch |
||||||
|
unlet g:neomake_logfile |
||||||
|
call neomake#log#error(printf('Error when trying to write to logfile %s: %s. Unsetting g:neomake_logfile.', logfile, v:exception)) |
||||||
|
endtry |
||||||
|
endif |
||||||
|
" @vimlint(EVL104, 0, l:timediff) |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#log#error(...) abort |
||||||
|
call call('s:log', [0] + a:000) |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#log#warning(...) abort |
||||||
|
call call('s:log', [1] + a:000) |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#log#info(...) abort |
||||||
|
call call('s:log', [2] + a:000) |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#log#debug(...) abort |
||||||
|
call call('s:log', [3] + a:000) |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#log#debug_obj(msg, obj) abort |
||||||
|
if s:is_testing || neomake#utils#get_verbosity() >= 3 || !empty(get(g:, 'neomake_logfile', '')) |
||||||
|
call neomake#log#debug(a:msg.': '.neomake#utils#Stringify(a:obj).'.') |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#log#exception(error, ...) abort |
||||||
|
let log_context = a:0 ? a:1 : {'bufnr': bufnr('%')} |
||||||
|
echom printf('Neomake error in: %s', v:throwpoint) |
||||||
|
call neomake#log#error(a:error, log_context) |
||||||
|
call neomake#log#debug(printf('(in %s)', v:throwpoint), log_context) |
||||||
|
endfunction |
||||||
|
|
||||||
|
let s:warned = {} |
||||||
|
function! neomake#log#warn_once(msg, key) abort |
||||||
|
if !has_key(s:warned, a:key) |
||||||
|
let s:warned[a:key] = 1 |
||||||
|
echohl WarningMsg |
||||||
|
echom 'Neomake: ' . a:msg |
||||||
|
echohl None |
||||||
|
let v:warningmsg = 'Neomake: '.a:msg |
||||||
|
call neomake#log#debug('Neomake warning: '.a:msg) |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#log#reset_warnings() abort |
||||||
|
let s:warned = {} |
||||||
|
endfunction |
||||||
|
" vim: ts=4 sw=4 et |
@ -0,0 +1,15 @@ |
|||||||
|
" vim: ts=4 sw=4 et |
||||||
|
|
||||||
|
function! neomake#makers#cabal#cabal() abort |
||||||
|
let errorformat = join([ |
||||||
|
\ '%A%f:%l:%c:', |
||||||
|
\ '%A%f:%l:%c: %m', |
||||||
|
\ '%+C %m', |
||||||
|
\ '%-Z%[%^ ]', |
||||||
|
\ ], ',') |
||||||
|
return { |
||||||
|
\ 'exe': 'cabal', |
||||||
|
\ 'args': ['build'], |
||||||
|
\ 'errorformat': errorformat |
||||||
|
\ } |
||||||
|
endfunction |
@ -0,0 +1,39 @@ |
|||||||
|
" vim: ts=4 sw=4 et |
||||||
|
|
||||||
|
" Yet to be determined |
||||||
|
let s:rustup_has_nightly = get(g:, 'neomake_clippy_rustup_has_nightly', -1) |
||||||
|
|
||||||
|
function! neomake#makers#clippy#clippy() abort |
||||||
|
" When rustup and a nightly toolchain is installed, that is used. |
||||||
|
" Otherwise, the default cargo exectuable is used. If this is not part |
||||||
|
" of a nightly rust, this will fail. |
||||||
|
if s:rustup_has_nightly == -1 |
||||||
|
if !executable('rustup') |
||||||
|
let s:rustup_has_nightly = 0 |
||||||
|
call system('rustc --version | grep -q "\-nightly"') |
||||||
|
if v:shell_error |
||||||
|
call neomake#log#warning('Clippy requires a nightly rust installation.') |
||||||
|
endif |
||||||
|
else |
||||||
|
call system('rustup show | grep -q "^nightly-"') |
||||||
|
let s:rustup_has_nightly = !v:shell_error |
||||||
|
endif |
||||||
|
endif |
||||||
|
|
||||||
|
let cargo_maker = neomake#makers#ft#rust#cargo() |
||||||
|
let json_args = ['--message-format=json', '--quiet'] |
||||||
|
|
||||||
|
if s:rustup_has_nightly |
||||||
|
return { |
||||||
|
\ 'exe': 'rustup', |
||||||
|
\ 'args': ['run', 'nightly', 'cargo', 'clippy'] + json_args, |
||||||
|
\ 'process_output': cargo_maker.process_output, |
||||||
|
\ } |
||||||
|
else |
||||||
|
return { |
||||||
|
\ 'exe': 'cargo', |
||||||
|
\ 'args': ['clippy'] + json_args, |
||||||
|
\ 'process_output': cargo_maker.process_output, |
||||||
|
\ } |
||||||
|
endif |
||||||
|
endfunction |
@ -0,0 +1,14 @@ |
|||||||
|
function! neomake#makers#ft#ada#EnabledMakers() abort |
||||||
|
return ['gcc'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#ada#gcc() abort |
||||||
|
return { |
||||||
|
\ 'args': ['-c', '-x', 'ada', '-gnatc'], |
||||||
|
\ 'errorformat': |
||||||
|
\ '%-G%f:%s:,' . |
||||||
|
\ '%f:%l:%c: %m,' . |
||||||
|
\ '%f:%l: %m' |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
" vim: ts=4 sw=4 et |
@ -0,0 +1,9 @@ |
|||||||
|
function! neomake#makers#ft#angular#SupersetOf() abort |
||||||
|
return 'javascript' |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#angular#EnabledMakers() abort |
||||||
|
return ['jshint', 'eslint', 'jscs'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
" vim: ts=4 sw=4 et |
@ -0,0 +1,17 @@ |
|||||||
|
" vim: ts=4 sw=4 et |
||||||
|
|
||||||
|
function! neomake#makers#ft#ansible#EnabledMakers() abort |
||||||
|
return ['ansiblelint', 'yamllint'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#ansible#yamllint() abort |
||||||
|
return neomake#makers#ft#yaml#yamllint() |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#ansible#ansiblelint() abort |
||||||
|
return { |
||||||
|
\ 'exe': 'ansible-lint', |
||||||
|
\ 'args': ['-p', '--nocolor'], |
||||||
|
\ 'errorformat': '%f:%l: [%tANSIBLE%n] %m', |
||||||
|
\ } |
||||||
|
endfunction |
@ -0,0 +1,16 @@ |
|||||||
|
" vim: ts=4 sw=4 et |
||||||
|
|
||||||
|
function! neomake#makers#ft#apiblueprint#EnabledMakers() abort |
||||||
|
return executable('drafter') ? ['drafter'] : [] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#apiblueprint#drafter() abort |
||||||
|
" Drafter only operates on a single file at a time, and therefore doesn't |
||||||
|
" bother to print out a file name with each error. We need to attach this |
||||||
|
" so that the quickfix list can function properly. |
||||||
|
return { |
||||||
|
\ 'args': ['-l', '-u'], |
||||||
|
\ 'errorformat': '%f: %t%[%^:]\\+: (%n) %m; line %l\, column %c%.%#', |
||||||
|
\ 'mapexpr': 'neomake_bufname . ": " . v:val' |
||||||
|
\ } |
||||||
|
endfunction |
@ -0,0 +1,11 @@ |
|||||||
|
function! neomake#makers#ft#applescript#EnabledMakers() abort |
||||||
|
return ['osacompile'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#applescript#osacompile() abort |
||||||
|
return { |
||||||
|
\ 'args': ['-o', g:neomake#compat#dev_null], |
||||||
|
\ 'errorformat': '%f:%l: %trror: %m', |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
" vim: ts=4 sw=4 et |
@ -0,0 +1,28 @@ |
|||||||
|
function! neomake#makers#ft#asciidoc#SupersetOf() abort |
||||||
|
return 'text' |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#asciidoc#EnabledMakers() abort |
||||||
|
let makers = executable('asciidoctor') ? ['asciidoctor'] : ['asciidoc'] |
||||||
|
return makers + neomake#makers#ft#text#EnabledMakers() |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#asciidoc#asciidoc() abort |
||||||
|
return { |
||||||
|
\ 'errorformat': |
||||||
|
\ '%E%\w%\+: %tRROR: %f: line %l: %m,' . |
||||||
|
\ '%E%\w%\+: %tRROR: %f: %m,' . |
||||||
|
\ '%E%\w%\+: FAILED: %f: line %l: %m,' . |
||||||
|
\ '%E%\w%\+: FAILED: %f: %m,' . |
||||||
|
\ '%W%\w%\+: %tARNING: %f: line %l: %m,' . |
||||||
|
\ '%W%\w%\+: %tARNING: %f: %m,' . |
||||||
|
\ '%W%\w%\+: DEPRECATED: %f: line %l: %m,' . |
||||||
|
\ '%W%\w%\+: DEPRECATED: %f: %m', |
||||||
|
\ 'args': ['-o', g:neomake#compat#dev_null], |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#asciidoc#asciidoctor() abort |
||||||
|
return neomake#makers#ft#asciidoc#asciidoc() |
||||||
|
endfunction |
||||||
|
" vim: ts=4 sw=4 et |
@ -0,0 +1,12 @@ |
|||||||
|
function! neomake#makers#ft#beancount#EnabledMakers() abort |
||||||
|
return ['bean_check'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#beancount#bean_check() abort |
||||||
|
return { |
||||||
|
\ 'exe': 'bean-check', |
||||||
|
\ 'errorformat': '%E%f:%l:%m', |
||||||
|
\ 'postprocess': function('neomake#postprocess#compress_whitespace'), |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
" vim: ts=4 sw=4 et |
@ -0,0 +1,16 @@ |
|||||||
|
" vim: ts=4 sw=4 et |
||||||
|
|
||||||
|
function! neomake#makers#ft#bib#EnabledMakers() abort |
||||||
|
return [] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#bib#bibtex() abort |
||||||
|
return { |
||||||
|
\ 'exe': 'bibtex', |
||||||
|
\ 'args': ['-terse', '%:r'], |
||||||
|
\ 'append_file': 0, |
||||||
|
\ 'uses_filename': 0, |
||||||
|
\ 'errorformat': '%E%m---line %l of file %f', |
||||||
|
\ 'cwd': '%:p:h' |
||||||
|
\ } |
||||||
|
endfunction |
@ -0,0 +1,108 @@ |
|||||||
|
" vim: ts=4 sw=4 et |
||||||
|
|
||||||
|
function! neomake#makers#ft#c#EnabledMakers() abort |
||||||
|
let makers = executable('clang') ? ['clang', 'clangtidy', 'clangcheck'] : ['gcc'] |
||||||
|
call add(makers, 'checkpatch') |
||||||
|
call add(makers, 'cppcheck') |
||||||
|
return makers |
||||||
|
endfunction |
||||||
|
|
||||||
|
let g:neomake#makers#ft#c#project_root_files = ['configure', 'CMakeLists.txt'] |
||||||
|
|
||||||
|
function! neomake#makers#ft#c#clang() abort |
||||||
|
" as a single-file maker, include the current directory in the default |
||||||
|
" search path |
||||||
|
return { |
||||||
|
\ 'args': ['-fsyntax-only', '-Wall', '-Wextra', '-I./'], |
||||||
|
\ 'errorformat': |
||||||
|
\ '%-G%f:%s:,' . |
||||||
|
\ '%f:%l:%c: %trror: %m,' . |
||||||
|
\ '%f:%l:%c: %tarning: %m,' . |
||||||
|
\ '%I%f:%l:%c: note: %m,' . |
||||||
|
\ '%f:%l:%c: %m,'. |
||||||
|
\ '%f:%l: %trror: %m,'. |
||||||
|
\ '%f:%l: %tarning: %m,'. |
||||||
|
\ '%I%f:%l: note: %m,'. |
||||||
|
\ '%f:%l: %m' |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#c#clangcheck() abort |
||||||
|
return { |
||||||
|
\ 'exe': 'clang-check', |
||||||
|
\ 'errorformat': |
||||||
|
\ '%-G%f:%s:,' . |
||||||
|
\ '%f:%l:%c: %trror: %m,' . |
||||||
|
\ '%f:%l:%c: %tarning: %m,' . |
||||||
|
\ '%I%f:%l:%c: note: %m,' . |
||||||
|
\ '%f:%l:%c: %m,'. |
||||||
|
\ '%f:%l: %trror: %m,'. |
||||||
|
\ '%f:%l: %tarning: %m,'. |
||||||
|
\ '%I%f:%l: note: %m,'. |
||||||
|
\ '%f:%l: %m', |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#c#gcc() abort |
||||||
|
" as a single-file maker, include the current directory in the default |
||||||
|
" search path |
||||||
|
return { |
||||||
|
\ 'args': ['-fsyntax-only', '-Wall', '-Wextra', '-I./'], |
||||||
|
\ 'errorformat': |
||||||
|
\ '%-G%f:%s:,' . |
||||||
|
\ '%-G%f:%l: %#error: %#(Each undeclared identifier is reported only%.%#,' . |
||||||
|
\ '%-G%f:%l: %#error: %#for each function it appears%.%#,' . |
||||||
|
\ '%-GIn file included%.%#,' . |
||||||
|
\ '%-G %#from %f:%l\,,' . |
||||||
|
\ '%f:%l:%c: %trror: %m,' . |
||||||
|
\ '%f:%l:%c: %tarning: %m,' . |
||||||
|
\ '%I%f:%l:%c: note: %m,' . |
||||||
|
\ '%f:%l:%c: %m,' . |
||||||
|
\ '%f:%l: %trror: %m,' . |
||||||
|
\ '%f:%l: %tarning: %m,'. |
||||||
|
\ '%I%f:%l: note: %m,'. |
||||||
|
\ '%f:%l: %m', |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
" The -p option followed by the path to the build directory should be set in |
||||||
|
" the maker's arguments. That directory should contain the compile command |
||||||
|
" database (compile_commands.json). |
||||||
|
function! neomake#makers#ft#c#clangtidy() abort |
||||||
|
return { |
||||||
|
\ 'exe': 'clang-tidy', |
||||||
|
\ 'errorformat': |
||||||
|
\ '%E%f:%l:%c: fatal error: %m,' . |
||||||
|
\ '%E%f:%l:%c: error: %m,' . |
||||||
|
\ '%W%f:%l:%c: warning: %m,' . |
||||||
|
\ '%-G%\m%\%%(LLVM ERROR:%\|No compilation database found%\)%\@!%.%#,' . |
||||||
|
\ '%E%m', |
||||||
|
\ 'short_name': 'ctdy', |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#c#checkpatch() abort |
||||||
|
return { |
||||||
|
\ 'exe': 'checkpatch.pl', |
||||||
|
\ 'args': ['--no-summary', '--no-tree', '--terse', '--file'], |
||||||
|
\ 'errorformat': |
||||||
|
\ '%f:%l: %tARNING: %m,' . |
||||||
|
\ '%f:%l: %tRROR: %m', |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#c#cppcheck() abort |
||||||
|
" NOTE: '--language=c' should be the first args, it gets replaced in |
||||||
|
" neomake#makers#ft#cpp#cppcheck. |
||||||
|
return { |
||||||
|
\ 'args': ['--language=c', '--quiet', '--enable=warning', |
||||||
|
\ '--template={file}:{line}:{column}:{severity}:{message}'], |
||||||
|
\ 'errorformat': |
||||||
|
\ 'nofile:0:0:%trror:%m,' . |
||||||
|
\ '%f:%l:%c:%trror:%m,' . |
||||||
|
\ 'nofile:0:0:%tarning:%m,'. |
||||||
|
\ '%f:%l:%c:%tarning:%m,'. |
||||||
|
\ 'nofile:0:0:%tnformation:%m,'. |
||||||
|
\ '%f:%l:%c:%tnformation:%m', |
||||||
|
\ } |
||||||
|
endfunction |
@ -0,0 +1,14 @@ |
|||||||
|
" vim: ts=4 sw=4 et |
||||||
|
|
||||||
|
function! neomake#makers#ft#cf3#EnabledMakers() abort |
||||||
|
return ['cfpromises'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#cf3#cfpromises() abort |
||||||
|
return { |
||||||
|
\ 'exe': 'cf-promises', |
||||||
|
\ 'args': ['-cf'], |
||||||
|
\ 'errorformat': |
||||||
|
\ '%E%f:%l:%c: error: %m', |
||||||
|
\ } |
||||||
|
endfunction |
@ -0,0 +1,23 @@ |
|||||||
|
function! neomake#makers#ft#chef#SupersetOf() abort |
||||||
|
return 'ruby' |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#chef#EnabledMakers() abort |
||||||
|
let ruby_makers = neomake#makers#ft#ruby#EnabledMakers() |
||||||
|
return ruby_makers + ['foodcritic', 'cookstyle'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#chef#foodcritic() abort |
||||||
|
return { |
||||||
|
\ 'errorformat': '%WFC%n: %m: %f:%l', |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#chef#cookstyle() abort |
||||||
|
return { |
||||||
|
\ 'args': ['-f', 'emacs'], |
||||||
|
\ 'errorformat': '%f:%l:%c: %t: %m', |
||||||
|
\ 'postprocess': function('neomake#makers#ft#ruby#RubocopEntryProcess'), |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
" vim: ts=4 sw=4 et |
@ -0,0 +1,15 @@ |
|||||||
|
" vim: ts=4 sw=4 et |
||||||
|
|
||||||
|
function! neomake#makers#ft#coffee#EnabledMakers() abort |
||||||
|
return ['coffeelint'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#coffee#coffeelint() abort |
||||||
|
return { |
||||||
|
\ 'args': ['--reporter=csv'], |
||||||
|
\ 'errorformat': '%f\,%l\,%\d%#\,%trror\,%m,' . |
||||||
|
\ '%f\,%l\,%trror\,%m,' . |
||||||
|
\ '%f\,%l\,%\d%#\,%tarn\,%m,' . |
||||||
|
\ '%f\,%l\,%tarn\,%m' |
||||||
|
\ } |
||||||
|
endfunction |
@ -0,0 +1,50 @@ |
|||||||
|
" vim: ts=4 sw=4 et |
||||||
|
|
||||||
|
function! neomake#makers#ft#cpp#EnabledMakers() abort |
||||||
|
let makers = executable('clang++') ? ['clang', 'clangtidy', 'clangcheck'] : ['gcc'] |
||||||
|
call add(makers, 'cppcheck') |
||||||
|
return makers |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#cpp#clang() abort |
||||||
|
let maker = neomake#makers#ft#c#clang() |
||||||
|
let maker.exe = 'clang++' |
||||||
|
let maker.args += ['-std=c++1z'] |
||||||
|
return maker |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#cpp#gcc() abort |
||||||
|
let maker = neomake#makers#ft#c#gcc() |
||||||
|
let maker.exe = 'g++' |
||||||
|
let maker.args += ['-std=c++1z'] |
||||||
|
return maker |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#cpp#clangtidy() abort |
||||||
|
return neomake#makers#ft#c#clangtidy() |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#cpp#clangcheck() abort |
||||||
|
return neomake#makers#ft#c#clangcheck() |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#cpp#cppcheck() abort |
||||||
|
let maker = neomake#makers#ft#c#cppcheck() |
||||||
|
let maker.args[0] = '--language=c++' |
||||||
|
return maker |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#cpp#cpplint() abort |
||||||
|
return { |
||||||
|
\ 'exe': executable('cpplint') ? 'cpplint' : 'cpplint.py', |
||||||
|
\ 'args': ['--verbose=3'], |
||||||
|
\ 'errorformat': |
||||||
|
\ '%A%f:%l: %m [%t],' . |
||||||
|
\ '%-G%.%#', |
||||||
|
\ 'postprocess': function('neomake#makers#ft#cpp#CpplintEntryProcess') |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#cpp#CpplintEntryProcess(entry) abort |
||||||
|
let a:entry.type = str2nr(a:entry.type) < 5 ? 'W' : 'E' |
||||||
|
endfunction |
@ -0,0 +1,25 @@ |
|||||||
|
function! neomake#makers#ft#crystal#EnabledMakers() abort |
||||||
|
return ['crystal', 'ameba'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#crystal#crystal() abort |
||||||
|
" from vim-crystal |
||||||
|
return { |
||||||
|
\ 'args': ['run', '--no-color', '--no-codegen'], |
||||||
|
\ 'errorformat': |
||||||
|
\ '%ESyntax error in line %l: %m,'. |
||||||
|
\ '%ESyntax error in %f:%l: %m,'. |
||||||
|
\ '%EError in %f:%l: %m,'. |
||||||
|
\ '%C%p^,'. |
||||||
|
\ '%-C%.%#' |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#crystal#ameba() abort |
||||||
|
" from vim-crystal |
||||||
|
return { |
||||||
|
\ 'args': ['--format', 'flycheck'], |
||||||
|
\ 'errorformat': '%f:%l:%c: %t: %m' |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
" vim: ts=4 sw=4 et |
@ -0,0 +1,22 @@ |
|||||||
|
" vim: ts=4 sw=4 et |
||||||
|
|
||||||
|
function! neomake#makers#ft#cs#EnabledMakers() abort |
||||||
|
return ['mcs'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#cs#mcs() abort |
||||||
|
return { |
||||||
|
\ 'args': ['--parse', '--unsafe'], |
||||||
|
\ 'errorformat': '%f(%l\,%c): %trror %m', |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#cs#msbuild() abort |
||||||
|
return { |
||||||
|
\ 'exe': 'msbuild', |
||||||
|
\ 'args': ['-nologo', '-v:q', '-property:GenerateFullPaths=true', neomake#utils#FindGlobFile('*.sln')], |
||||||
|
\ 'errorformat': '%E%f(%l\,%c): error CS%n: %m [%.%#],'. |
||||||
|
\ '%W%f(%l\,%c): warning CS%n: %m [%.%#]', |
||||||
|
\ 'append_file' : 0, |
||||||
|
\ } |
||||||
|
endfunction |
@ -0,0 +1,35 @@ |
|||||||
|
scriptencoding utf8 |
||||||
|
|
||||||
|
function! neomake#makers#ft#css#EnabledMakers() abort |
||||||
|
return ['csslint', 'stylelint'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#css#csslint() abort |
||||||
|
return { |
||||||
|
\ 'args': ['--format=compact'], |
||||||
|
\ 'errorformat': |
||||||
|
\ '%-G,'. |
||||||
|
\ '%-G%f: lint free!,'. |
||||||
|
\ '%f: line %l\, col %c\, %trror - %m,'. |
||||||
|
\ '%f: line %l\, col %c\, %tarning - %m,'. |
||||||
|
\ '%f: line %l\, col %c\, %m,'. |
||||||
|
\ '%f: %tarning - %m' |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#css#stylelint() abort |
||||||
|
let maker = { |
||||||
|
\ 'errorformat': |
||||||
|
\ '%-P%f,'. |
||||||
|
\ '%W%*\s%l:%c%*\s✖ %m,'. |
||||||
|
\ '%-Q,'. |
||||||
|
\ '%+EError: No configuration provided for %f,%-C %.%#' |
||||||
|
\ } |
||||||
|
|
||||||
|
function! maker.postprocess(entry) abort |
||||||
|
let a:entry.text = substitute(a:entry.text, '\v\s\s+(.{-})\s*$', ' [\1]', 'g') |
||||||
|
endfunction |
||||||
|
|
||||||
|
return maker |
||||||
|
endfunction |
||||||
|
" vim: ts=4 sw=4 et |
@ -0,0 +1,15 @@ |
|||||||
|
" vim: ts=4 sw=4 et |
||||||
|
|
||||||
|
function! neomake#makers#ft#cuda#EnabledMakers() abort |
||||||
|
return ['nvcc'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#cuda#nvcc() abort |
||||||
|
return { |
||||||
|
\ 'exe': 'nvcc', |
||||||
|
\ 'errorformat': |
||||||
|
\ '%f\(%l\): %trror: %m,'. |
||||||
|
\ '%f\(%l\): %tarning: %m,'. |
||||||
|
\ '%f\(%l\): %m', |
||||||
|
\ } |
||||||
|
endfunction |
@ -0,0 +1,92 @@ |
|||||||
|
" vim: ts=4 sw=4 et |
||||||
|
|
||||||
|
function! neomake#makers#ft#d#EnabledMakers() abort |
||||||
|
" dmd, ldmd, and gdmd all share a common CLI. |
||||||
|
" Ordered in efficiency of compiler |
||||||
|
for m in ['dmd', 'ldmd', 'gdmd'] |
||||||
|
if executable(m) |
||||||
|
return [m] |
||||||
|
endif |
||||||
|
endfor |
||||||
|
return [] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:findDubRoot() abort |
||||||
|
"Look upwards for a dub.json or dub.sdl to find the root |
||||||
|
"I did it like this because it's the only cross platform way I know of |
||||||
|
let tmp_file = findfile('dub.json', '.;') |
||||||
|
if empty(tmp_file) |
||||||
|
let tmp_file = findfile('dub.sdl', '.;') |
||||||
|
endif |
||||||
|
return tmp_file |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:UpdateDub() abort |
||||||
|
"Add dub directories |
||||||
|
let s:dubImports = [] |
||||||
|
let tmp_file = s:findDubRoot() |
||||||
|
if executable('dub') && !empty(tmp_file) |
||||||
|
let tmp_dir = fnamemodify(tmp_file,':p:h') |
||||||
|
let dubCmd = 'dub describe --data=import-paths --annotate ' |
||||||
|
\ .'--skip-registry=all --vquiet --data-list --root=' |
||||||
|
let output = system(dubCmd . tmp_dir) |
||||||
|
if(v:shell_error == 0 && !empty(output)) |
||||||
|
" Is \n portable? |
||||||
|
let s:dubImports = split(output, '\n') |
||||||
|
call map(s:dubImports, "'-I' . v:val") |
||||||
|
endif |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
|
||||||
|
"GDMD does not adhere to dmd's flags or output, but to GCC's. |
||||||
|
"This is for LDMD and dmd only. |
||||||
|
function! s:DmdStyleMaker(args) abort |
||||||
|
"Updating dub paths each make might be slow? |
||||||
|
call s:UpdateDub() |
||||||
|
let args = ['-w', '-wi', '-c', '-o-', '-vcolumns'] + a:args + s:dubImports |
||||||
|
return { |
||||||
|
\ 'args': args, |
||||||
|
\ 'errorformat': |
||||||
|
\ '%f(%l\,%c): %trror: %m,' . |
||||||
|
\ '%f(%l): %trror: %m,' . |
||||||
|
\ '%f(%l\,%c): %tarning: %m,' . |
||||||
|
\ '%f(%l): %tarning: %m,' . |
||||||
|
\ '%f(%l\,%c): Deprecation: %m,' . |
||||||
|
\ '%f(%l): Deprecation: %m,', |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#d#dmd() abort |
||||||
|
let args = [] |
||||||
|
if exists('g:neomake_d_dmd_args_conf') |
||||||
|
call add(args, '-conf=' . expand(g:neomake_d_dmd_args_conf)) |
||||||
|
endif |
||||||
|
return s:DmdStyleMaker(args) |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#d#ldmd() abort |
||||||
|
let args = [] |
||||||
|
if exists('g:neomake_d_ldmd_args_conf') |
||||||
|
call add(args, '-conf=' . expand(g:neomake_d_ldmd_args_conf)) |
||||||
|
endif |
||||||
|
return s:DmdStyleMaker(args) |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#d#gdmd() abort |
||||||
|
let args = ['-c', '-o-', '-fsyntax-only', s:UpdateDub()] |
||||||
|
return { |
||||||
|
\ 'args': args, |
||||||
|
\ 'errorformat': |
||||||
|
\ '%-G%f:%s:,' . |
||||||
|
\ '%-G%f:%l: %#error: %#(Each undeclared identifier is reported only%.%#,' . |
||||||
|
\ '%-G%f:%l: %#error: %#for each function it appears%.%#,' . |
||||||
|
\ '%-GIn file included%.%#,' . |
||||||
|
\ '%-G %#from %f:%l\,,' . |
||||||
|
\ '%f:%l:%c: %trror: %m,' . |
||||||
|
\ '%f:%l:%c: %tarning: %m,' . |
||||||
|
\ '%f:%l:%c: %m,' . |
||||||
|
\ '%f:%l: %trror: %m,' . |
||||||
|
\ '%f:%l: %tarning: %m,'. |
||||||
|
\ '%f:%l: %m', |
||||||
|
\ } |
||||||
|
endfunction |
@ -0,0 +1,8 @@ |
|||||||
|
function! neomake#makers#ft#docbk#EnabledMakers() abort |
||||||
|
return ['xmllint'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#docbk#xmllint() abort |
||||||
|
return neomake#makers#ft#xml#xmllint() |
||||||
|
endfunction |
||||||
|
" vim: ts=4 sw=4 et |
@ -0,0 +1,13 @@ |
|||||||
|
function! neomake#makers#ft#dockerfile#EnabledMakers() abort |
||||||
|
return ['hadolint'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#dockerfile#hadolint() abort |
||||||
|
return { |
||||||
|
\ 'output_stream': 'stdout', |
||||||
|
\ 'uses_stdin': 1, |
||||||
|
\ 'args': ['--format', 'tty'], |
||||||
|
\ 'errorformat': '%f:%l %m', |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
" vim: ts=4 sw=4 et |
@ -0,0 +1,72 @@ |
|||||||
|
" vim: ts=4 sw=4 et |
||||||
|
|
||||||
|
" Credo error types. |
||||||
|
" F -> Refactoring opportunities |
||||||
|
" W -> Warnings |
||||||
|
" C -> Convention violation |
||||||
|
" D -> Software design suggestions |
||||||
|
" R -> Readability suggestions |
||||||
|
" Map structure {CredoError: NeomakeType, ...} |
||||||
|
let s:neomake_elixir_credo_config_typemap = { |
||||||
|
\ 'F': 'W', |
||||||
|
\ 'C': 'W', |
||||||
|
\ 'D': 'I', |
||||||
|
\ 'R': 'I'} |
||||||
|
|
||||||
|
function! neomake#makers#ft#elixir#PostprocessEnforceMaxBufferLine(entry) abort |
||||||
|
let buffer_lines = str2nr(line('$')) |
||||||
|
if (buffer_lines < a:entry.lnum) |
||||||
|
let a:entry.lnum = buffer_lines |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#elixir#PostprocessCredo(entry) abort |
||||||
|
let type = toupper(a:entry.type) |
||||||
|
let type_map = extend(s:neomake_elixir_credo_config_typemap, |
||||||
|
\ get(g:, 'neomake_elixir_credo_config_typemap', {})) |
||||||
|
if has_key(type_map, type) |
||||||
|
let a:entry.type = type_map[type] |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#elixir#EnabledMakers() abort |
||||||
|
return ['mix'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#elixir#elixir() abort |
||||||
|
return { |
||||||
|
\ 'errorformat': |
||||||
|
\ '%E** %s %f:%l: %m,'. |
||||||
|
\ '%W%f:%l: warning: %m' |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#elixir#credo() abort |
||||||
|
return { |
||||||
|
\ 'exe': 'mix', |
||||||
|
\ 'args': ['credo', 'list', '--format=oneline'], |
||||||
|
\ 'postprocess': function('neomake#makers#ft#elixir#PostprocessCredo'), |
||||||
|
\ 'errorformat': |
||||||
|
\'[%t] %. %f:%l:%c %m,' . |
||||||
|
\'[%t] %. %f:%l %m' |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#elixir#mix() abort |
||||||
|
return { |
||||||
|
\ 'exe' : 'mix', |
||||||
|
\ 'args': ['compile', '--warnings-as-errors'], |
||||||
|
\ 'postprocess': function('neomake#makers#ft#elixir#PostprocessEnforceMaxBufferLine'), |
||||||
|
\ 'errorformat': |
||||||
|
\ '** %s %f:%l: %m,'. |
||||||
|
\ '%Ewarning: %m,%C %f:%l,%Z' |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#elixir#dogma() abort |
||||||
|
return { |
||||||
|
\ 'exe': 'mix', |
||||||
|
\ 'args': ['dogma', '--format=flycheck'], |
||||||
|
\ 'errorformat': '%E%f:%l:%c: %.: %m' |
||||||
|
\ } |
||||||
|
endfunction |
@ -0,0 +1,53 @@ |
|||||||
|
" vim: ts=4 sw=4 et |
||||||
|
|
||||||
|
function! neomake#makers#ft#elm#EnabledMakers() abort |
||||||
|
return ['elmMake'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#elm#elmMake() abort |
||||||
|
return { |
||||||
|
\ 'exe': 'elm-make', |
||||||
|
\ 'args': ['--report=json', '--output=' . g:neomake#compat#dev_null], |
||||||
|
\ 'process_output': function('neomake#makers#ft#elm#ElmMakeProcessOutput') |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#elm#ElmMakeProcessOutput(context) abort |
||||||
|
let errors = [] |
||||||
|
" output will be a List, containing either: |
||||||
|
" 1) A success message |
||||||
|
" 2) A string holding a JSON array for both warnings and errors |
||||||
|
|
||||||
|
for line in a:context.output |
||||||
|
if line[0] ==# '[' |
||||||
|
let decoded = neomake#compat#json_decode(line) |
||||||
|
for item in decoded |
||||||
|
if get(item, 'type', '') ==# 'warning' |
||||||
|
let code = 'W' |
||||||
|
else |
||||||
|
let code = 'E' |
||||||
|
endif |
||||||
|
|
||||||
|
let compiler_error = item['tag'] |
||||||
|
let message = item['overview'] |
||||||
|
let filename = item['file'] |
||||||
|
let region_start = item['region']['start'] |
||||||
|
let region_end = item['region']['end'] |
||||||
|
let row = region_start['line'] |
||||||
|
let col = region_start['column'] |
||||||
|
let length = region_end['column'] - region_start['column'] |
||||||
|
|
||||||
|
let error = { |
||||||
|
\ 'text': compiler_error . ' : ' . message, |
||||||
|
\ 'type': code, |
||||||
|
\ 'lnum': row, |
||||||
|
\ 'col': col, |
||||||
|
\ 'length': length, |
||||||
|
\ 'filename': filename, |
||||||
|
\ } |
||||||
|
call add(errors, error) |
||||||
|
endfor |
||||||
|
endif |
||||||
|
endfor |
||||||
|
return errors |
||||||
|
endfunction |
@ -0,0 +1,72 @@ |
|||||||
|
|
||||||
|
function! neomake#makers#ft#erlang#EnabledMakers() abort |
||||||
|
return ['erlc'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#erlang#erlc() abort |
||||||
|
let maker = { |
||||||
|
\ 'errorformat': |
||||||
|
\ '%W%f:%l: Warning: %m,' . |
||||||
|
\ '%E%f:%l: %m' |
||||||
|
\ } |
||||||
|
function! maker.InitForJob(_jobinfo) abort |
||||||
|
let self.args = neomake#makers#ft#erlang#GlobPaths() |
||||||
|
endfunction |
||||||
|
return maker |
||||||
|
endfunction |
||||||
|
|
||||||
|
if !exists('g:neomake_erlang_erlc_target_dir') |
||||||
|
let g:neomake_erlang_erlc_target_dir = tempname() |
||||||
|
endif |
||||||
|
|
||||||
|
function! neomake#makers#ft#erlang#GlobPaths() abort |
||||||
|
" Find project root directory. |
||||||
|
let rebar_config = neomake#utils#FindGlobFile('rebar.config') |
||||||
|
if !empty(rebar_config) |
||||||
|
let root = fnamemodify(rebar_config, ':h') |
||||||
|
else |
||||||
|
" At least try with CWD |
||||||
|
let root = getcwd() |
||||||
|
endif |
||||||
|
let root = fnamemodify(root, ':p') |
||||||
|
let build_dir = root . '_build' |
||||||
|
let ebins = [] |
||||||
|
if isdirectory(build_dir) |
||||||
|
" Pick the rebar3 profile to use |
||||||
|
let default_profile = expand('%') =~# '_SUITE.erl$' ? 'test' : 'default' |
||||||
|
let profile = get(b:, 'neomake_erlang_erlc_rebar3_profile', default_profile) |
||||||
|
let ebins += neomake#compat#glob_list(build_dir . '/' . profile . '/lib/*/ebin') |
||||||
|
let target_dir = build_dir . '/neomake' |
||||||
|
else |
||||||
|
let target_dir = get(b:, 'neomake_erlang_erlc_target_dir', |
||||||
|
\ get(g:, 'neomake_erlang_erlc_target_dir')) |
||||||
|
endif |
||||||
|
" If <root>/_build doesn't exist it might be a rebar2/erlang.mk project |
||||||
|
if isdirectory(root . 'deps') |
||||||
|
let ebins += neomake#compat#glob_list(root . 'deps/*/ebin') |
||||||
|
endif |
||||||
|
" Set g:neomake_erlang_erlc_extra_deps in a project-local .vimrc, e.g.: |
||||||
|
" let g:neomake_erlang_erlc_extra_deps = ['deps.local'] |
||||||
|
" Or just b:neomake_erlang_erlc_extra_deps in a specific buffer. |
||||||
|
let extra_deps_dirs = get(b:, 'neomake_erlang_erlc_extra_deps', |
||||||
|
\ get(g:, 'neomake_erlang_erlc_extra_deps')) |
||||||
|
if !empty(extra_deps_dirs) |
||||||
|
for extra_deps in extra_deps_dirs |
||||||
|
if extra_deps[-1] !=# '/' |
||||||
|
let extra_deps .= '/' |
||||||
|
endif |
||||||
|
let ebins += neomake#compat#glob_list(extra_deps . '*/ebin') |
||||||
|
endfor |
||||||
|
endif |
||||||
|
let args = ['-pa', 'ebin', '-I', 'include', '-I', 'src'] |
||||||
|
for ebin in ebins |
||||||
|
let args += [ '-pa', ebin, |
||||||
|
\ '-I', substitute(ebin, 'ebin$', 'include', '') ] |
||||||
|
endfor |
||||||
|
if !isdirectory(target_dir) |
||||||
|
call mkdir(target_dir, 'p') |
||||||
|
endif |
||||||
|
let args += ['-o', target_dir] |
||||||
|
return args |
||||||
|
endfunction |
||||||
|
" vim: ts=4 sw=4 et |
@ -0,0 +1,16 @@ |
|||||||
|
" vim: ts=4 sw=4 et |
||||||
|
|
||||||
|
function! neomake#makers#ft#fish#EnabledMakers() abort |
||||||
|
return ['fish'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#fish#fish() abort |
||||||
|
return { |
||||||
|
\ 'args': ['-n'], |
||||||
|
\ 'errorformat': |
||||||
|
\ '%C%f (line %l): %s,'. |
||||||
|
\ '%-Gfish: %.%#,'. |
||||||
|
\ '%Z%p^,'. |
||||||
|
\ '%E%m' |
||||||
|
\} |
||||||
|
endfunction |
@ -0,0 +1,32 @@ |
|||||||
|
" vim: ts=4 sw=4 et |
||||||
|
|
||||||
|
function! neomake#makers#ft#fortran#EnabledMakers() abort |
||||||
|
return ['gfortran'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
" Using the errorformat from syntastic |
||||||
|
function! neomake#makers#ft#fortran#ifort() abort |
||||||
|
return { |
||||||
|
\ 'args': ['-syntax-only', '-warn'], |
||||||
|
\ 'errorformat': |
||||||
|
\ '%E%f(%l): error #%n: %m,'. |
||||||
|
\ '%W%f(%l): warning #%n: %m,'. |
||||||
|
\ '%W%f(%l): remark #%n: %m,'. |
||||||
|
\ '%-Z%p^,'. |
||||||
|
\ '%-G%.%#', |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
" Using the errorformat from syntastic |
||||||
|
function! neomake#makers#ft#fortran#gfortran() abort |
||||||
|
return { |
||||||
|
\ 'args': ['-fsyntax-only', '-Wall', '-Wextra'], |
||||||
|
\ 'errorformat': |
||||||
|
\ '%-C %#,'. |
||||||
|
\ '%-C %#%.%#,'. |
||||||
|
\ '%A%f:%l%[.:]%c:,'. |
||||||
|
\ '%Z%\m%\%%(Fatal %\)%\?%trror: %m,'. |
||||||
|
\ '%Z%tarning: %m,'. |
||||||
|
\ '%-G%.%#', |
||||||
|
\ } |
||||||
|
endfunction |
@ -0,0 +1,85 @@ |
|||||||
|
" vim: ts=4 sw=4 et |
||||||
|
|
||||||
|
function! neomake#makers#ft#go#EnabledMakers() abort |
||||||
|
let makers = ['go'] |
||||||
|
if executable('golangci-lint') |
||||||
|
call add(makers, 'golangci_lint') |
||||||
|
elseif executable('gometalinter') |
||||||
|
call add(makers, 'gometalinter') |
||||||
|
else |
||||||
|
call extend(makers, ['golint', 'govet']) |
||||||
|
endif |
||||||
|
return makers |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#go#go() abort |
||||||
|
return { |
||||||
|
\ 'args': [ |
||||||
|
\ 'test', '-c', |
||||||
|
\ '-o', g:neomake#compat#dev_null, |
||||||
|
\ ], |
||||||
|
\ 'append_file': 0, |
||||||
|
\ 'cwd': '%:h', |
||||||
|
\ 'serialize': 1, |
||||||
|
\ 'serialize_abort_on_error': 1, |
||||||
|
\ 'errorformat': |
||||||
|
\ '%W%f:%l: warning: %m,' . |
||||||
|
\ '%E%f:%l:%c:%m,' . |
||||||
|
\ '%E%f:%l:%m,' . |
||||||
|
\ '%C%\s%\+%m,' . |
||||||
|
\ '%-G%.%#\\\[no test files],' . |
||||||
|
\ '%-G#%.%#', |
||||||
|
\ 'postprocess': function('neomake#postprocess#compress_whitespace'), |
||||||
|
\ 'version_arg': 'version', |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#go#golint() abort |
||||||
|
" golint's issues are informational, as they're stylistic (not bugs) |
||||||
|
return { |
||||||
|
\ 'errorformat': |
||||||
|
\ '%I%f:%l:%c: %m,' . |
||||||
|
\ '%-G%.%#' |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#go#govet() abort |
||||||
|
return { |
||||||
|
\ 'exe': 'go', |
||||||
|
\ 'args': ['vet'], |
||||||
|
\ 'append_file': 0, |
||||||
|
\ 'cwd': '%:h', |
||||||
|
\ 'errorformat': |
||||||
|
\ '%Evet: %.%\+: %f:%l:%c: %m,' . |
||||||
|
\ '%W%f:%l: %m,' . |
||||||
|
\ '%-G%.%#' |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#go#gometalinter() abort |
||||||
|
" Only run a subset of gometalinter for speed, users can override with: |
||||||
|
" let g:neomake_go_gometalinter_args = ['--disable-all', '--enable=X', ...] |
||||||
|
" |
||||||
|
" All linters are only warnings, the go compiler will report errors |
||||||
|
return { |
||||||
|
\ 'args': ['--disable-all', '--enable=errcheck', '--enable=megacheck', '--vendor'], |
||||||
|
\ 'append_file': 0, |
||||||
|
\ 'cwd': '%:h', |
||||||
|
\ 'errorformat': |
||||||
|
\ '%f:%l:%c:%t%*[^:]: %m,' . |
||||||
|
\ '%f:%l::%t%*[^:]: %m' |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#go#golangci_lint() abort |
||||||
|
return { |
||||||
|
\ 'exe': 'golangci-lint', |
||||||
|
\ 'args': ['run', '--out-format=line-number', '--print-issued-lines=false'], |
||||||
|
\ 'output_stream': 'stdout', |
||||||
|
\ 'append_file': 0, |
||||||
|
\ 'cwd': '%:h', |
||||||
|
\ 'errorformat': |
||||||
|
\ '%f:%l:%c: %m,' . |
||||||
|
\ '%f:%l: %m' |
||||||
|
\ } |
||||||
|
endfunction |
@ -0,0 +1,13 @@ |
|||||||
|
" vim: ts=4 sw=4 et |
||||||
|
|
||||||
|
function! neomake#makers#ft#haml#EnabledMakers() abort |
||||||
|
return ['hamllint'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#haml#hamllint() abort |
||||||
|
return { |
||||||
|
\ 'exe': 'haml-lint', |
||||||
|
\ 'args': ['--no-color'], |
||||||
|
\ 'errorformat': '%f:%l [%t] %m' |
||||||
|
\ } |
||||||
|
endfunction |
@ -0,0 +1,169 @@ |
|||||||
|
unlet! s:makers |
||||||
|
unlet! s:uses_cabal |
||||||
|
|
||||||
|
function! neomake#makers#ft#haskell#EnabledMakers() abort |
||||||
|
if !exists('s:makers') |
||||||
|
" cache whether each maker is available, to avoid lots of (UI blocking) |
||||||
|
" system calls |
||||||
|
" TODO: figure out how to do all this configuration async instead of |
||||||
|
" caching it--that would allow the user to change directories from |
||||||
|
" within vim and recalculate maker availability without restarting vim |
||||||
|
let commands = ['ghc-mod', 'hdevtools', 'hlint', 'liquid'] |
||||||
|
let s:makers = [] |
||||||
|
let s:jobs = [] |
||||||
|
for command in commands |
||||||
|
" stack may be able to find a maker binary that's not on the normal |
||||||
|
" path so check for that first |
||||||
|
if executable('stack') |
||||||
|
" run the maker command using stack to see whether stack can |
||||||
|
" find it use the help flag to run the maker command without |
||||||
|
" doing anything |
||||||
|
let stack_command = [ |
||||||
|
\ 'stack' |
||||||
|
\ , 'exec' |
||||||
|
\ , '--' |
||||||
|
\ , command |
||||||
|
\ , '--help' |
||||||
|
\ ] |
||||||
|
if has('nvim') |
||||||
|
let job_id = jobstart( |
||||||
|
\ stack_command, |
||||||
|
\ { 'command': command |
||||||
|
\ , 'on_exit': function('s:CheckStackMakerAsync') |
||||||
|
\ }) |
||||||
|
if job_id > 0 |
||||||
|
call add(s:jobs, job_id) |
||||||
|
endif |
||||||
|
else |
||||||
|
call extend(stack_command, ['> /dev/null 2>&1;', 'echo $?']) |
||||||
|
if system(join(stack_command, ' ')) == 0 |
||||||
|
call add(s:makers, substitute(command, '-', '', 'g')) |
||||||
|
endif |
||||||
|
endif |
||||||
|
elseif executable(command) " no stack bin so check for maker bin |
||||||
|
call add(s:makers, substitute(command, '-', '', 'g')) |
||||||
|
endif |
||||||
|
endfor |
||||||
|
if has('nvim') |
||||||
|
call jobwait(s:jobs) |
||||||
|
endif |
||||||
|
endif |
||||||
|
return s:makers |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#haskell#hdevtools() abort |
||||||
|
let params = { |
||||||
|
\ 'exe': 'hdevtools', |
||||||
|
\ 'args': ['check', '-g-Wall'], |
||||||
|
\ 'mapexpr': s:CleanUpSpaceAndBackticks(), |
||||||
|
\ 'errorformat': |
||||||
|
\ '%-Z %#,'. |
||||||
|
\ '%W%f:%l:%v: Warning: %m,'. |
||||||
|
\ '%W%f:%l:%v: Warning:,'. |
||||||
|
\ '%E%f:%l:%v: %m,'. |
||||||
|
\ '%E%>%f:%l:%v:,'. |
||||||
|
\ '%+C %#%m,'. |
||||||
|
\ '%W%>%f:%l:%v:,'. |
||||||
|
\ '%+C %#%tarning: %m,' |
||||||
|
\ } |
||||||
|
" hdevtools needs the GHC-PACKAGE-PATH environment variable to exist |
||||||
|
" when running on a project WITHOUT a cabal file, but it needs the |
||||||
|
" GHC-PACKAGE-PATH to NOT exist when running on a with a project WITH |
||||||
|
" a cabal file |
||||||
|
if !exists('s:uses_cabal') |
||||||
|
let s:uses_cabal = 0 |
||||||
|
if executable('stack') |
||||||
|
let output = neomake#compat#systemlist(['stack', '--verbosity', 'silent', 'path', '--project-root']) |
||||||
|
if !empty(output) |
||||||
|
let rootdir = output[0] |
||||||
|
if !empty(glob(rootdir . '/*.cabal')) |
||||||
|
let s:uses_cabal = 1 |
||||||
|
endif |
||||||
|
endif |
||||||
|
endif |
||||||
|
endif |
||||||
|
if s:uses_cabal |
||||||
|
let params['stackexecargs'] = ['--no-ghc-package-path'] |
||||||
|
endif |
||||||
|
return s:TryStack(params) |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#haskell#ghcmod() abort |
||||||
|
" This filters out newlines, which is what neovim gives us instead of the |
||||||
|
" null bytes that ghc-mod sometimes spits out. |
||||||
|
let mapexpr = 'substitute(v:val, "\n", "", "g")' |
||||||
|
return s:TryStack({ |
||||||
|
\ 'exe': 'ghc-mod', |
||||||
|
\ 'args': ['check'], |
||||||
|
\ 'mapexpr': mapexpr, |
||||||
|
\ 'errorformat': |
||||||
|
\ '%-G%\s%#,' . |
||||||
|
\ '%f:%l:%c:%trror: %m,' . |
||||||
|
\ '%f:%l:%c:%tarning: %m,'. |
||||||
|
\ '%f:%l:%c: %trror: %m,' . |
||||||
|
\ '%f:%l:%c: %tarning: %m,' . |
||||||
|
\ '%E%f:%l:%c:%m,' . |
||||||
|
\ '%E%f:%l:%c:,' . |
||||||
|
\ '%Z%m' |
||||||
|
\ }) |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#haskell#HlintEntryProcess(entry) abort |
||||||
|
" Postprocess hlint output to make it more readable as a single line |
||||||
|
let a:entry.text = substitute(a:entry.text, '\v(Found:)\s*\n', ' | \1', 'g') |
||||||
|
let a:entry.text = substitute(a:entry.text, '\v(Why not:)\s*\n', ' | \1', 'g') |
||||||
|
let a:entry.text = substitute(a:entry.text, '^No hints$', '', 'g') |
||||||
|
call neomake#postprocess#compress_whitespace(a:entry) |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#haskell#hlint() abort |
||||||
|
return s:TryStack({ |
||||||
|
\ 'exe': 'hlint', |
||||||
|
\ 'postprocess': function('neomake#makers#ft#haskell#HlintEntryProcess'), |
||||||
|
\ 'args': [], |
||||||
|
\ 'errorformat': |
||||||
|
\ '%E%f:%l:%v: Error: %m,' . |
||||||
|
\ '%W%f:%l:%v: Warning: %m,' . |
||||||
|
\ '%I%f:%l:%v: Suggestion: %m,' . |
||||||
|
\ '%C%m' |
||||||
|
\ }) |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#haskell#liquid() abort |
||||||
|
return s:TryStack({ |
||||||
|
\ 'exe': 'liquid', |
||||||
|
\ 'args': [], |
||||||
|
\ 'mapexpr': s:CleanUpSpaceAndBackticks(), |
||||||
|
\ 'errorformat': |
||||||
|
\ '%E %f:%l:%c-%.%#Error: %m,' . |
||||||
|
\ '%C%.%#|%.%#,' . |
||||||
|
\ '%C %#^%#,' . |
||||||
|
\ '%C%m,' |
||||||
|
\ }) |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:CheckStackMakerAsync(_job_id, data, _event) dict abort |
||||||
|
if a:data == 0 |
||||||
|
call add(s:makers, substitute(self.command, '-', '', 'g')) |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:TryStack(maker) abort |
||||||
|
if executable('stack') |
||||||
|
if !has_key(a:maker, 'stackexecargs') |
||||||
|
let a:maker['stackexecargs'] = [] |
||||||
|
endif |
||||||
|
let a:maker['args'] = |
||||||
|
\ ['--verbosity', 'silent', 'exec'] |
||||||
|
\ + a:maker['stackexecargs'] |
||||||
|
\ + ['--', a:maker['exe']] |
||||||
|
\ + a:maker['args'] |
||||||
|
let a:maker['exe'] = 'stack' |
||||||
|
endif |
||||||
|
return a:maker |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:CleanUpSpaceAndBackticks() abort |
||||||
|
return 'substitute(substitute(v:val, " \\{2,\\}", " ", "g"), "`", "''", "g")' |
||||||
|
endfunction |
||||||
|
" vim: ts=4 sw=4 et |
@ -0,0 +1,11 @@ |
|||||||
|
" vim: ts=4 sw=4 et |
||||||
|
|
||||||
|
function! neomake#makers#ft#haxe#EnabledMakers() abort |
||||||
|
return ['haxe'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#haxe#haxe() abort |
||||||
|
return { |
||||||
|
\ 'errorformat': '%E%f:%l: characters %c-%n : %m' |
||||||
|
\ } |
||||||
|
endfunction |
@ -0,0 +1,40 @@ |
|||||||
|
let s:makers = ['writegood'] |
||||||
|
|
||||||
|
let s:slash = neomake#utils#Slash() |
||||||
|
let s:vimhelplint_exe = '' |
||||||
|
if executable('vimhelplint') |
||||||
|
let s:vimhelplint_exe = 'vimhelplint' |
||||||
|
else |
||||||
|
let s:neomake_root = expand('<sfile>:p:h:h:h:h:h', 1) |
||||||
|
if !empty(glob(join([s:neomake_root, 'build', 'vimhelplint'], s:slash))) |
||||||
|
let s:vimhelplint_exe = join([s:neomake_root, 'contrib', 'vimhelplint'], s:slash) |
||||||
|
endif |
||||||
|
endif |
||||||
|
if !empty(s:vimhelplint_exe) |
||||||
|
let s:makers += ['vimhelplint'] |
||||||
|
endif |
||||||
|
|
||||||
|
function! neomake#makers#ft#help#EnabledMakers() abort |
||||||
|
return s:makers |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#help#vimhelplint() abort |
||||||
|
" NOTE: does not support/uses arg from wrapper script (i.e. no support for |
||||||
|
" tempfiles). It will use the arg only to expand/glob `*.txt` |
||||||
|
" (which does not include the hidden tempfile). |
||||||
|
return { |
||||||
|
\ 'exe': s:vimhelplint_exe, |
||||||
|
\ 'errorformat': '%f:%l:%c:%trror:%n:%m,%f:%l:%c:%tarning:%n:%m', |
||||||
|
\ 'postprocess': function('neomake#postprocess#generic_length'), |
||||||
|
\ 'output_stream': 'stdout', |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#help#proselint() abort |
||||||
|
return neomake#makers#ft#text#proselint() |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#help#writegood() abort |
||||||
|
return neomake#makers#ft#text#writegood() |
||||||
|
endfunction |
||||||
|
" vim: ts=4 sw=4 et |
@ -0,0 +1,20 @@ |
|||||||
|
function! neomake#makers#ft#html#tidy() abort |
||||||
|
" NOTE: could also have info items, but those are skipped with -e/-q, e.g. |
||||||
|
" 'line 7 column 1 - Info: value for attribute "id" missing quote marks'. |
||||||
|
return { |
||||||
|
\ 'args': ['-e', '-q', '--gnu-emacs', 'true'], |
||||||
|
\ 'errorformat': '%W%f:%l:%c: Warning: %m', |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#html#htmlhint() abort |
||||||
|
return { |
||||||
|
\ 'args': ['--format', 'unix', '--nocolor'], |
||||||
|
\ 'errorformat': '%f:%l:%c: %m,%-G,%-G%*\d problems', |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#html#EnabledMakers() abort |
||||||
|
return ['tidy', 'htmlhint'] |
||||||
|
endfunction |
||||||
|
" vim: ts=4 sw=4 et |
@ -0,0 +1,25 @@ |
|||||||
|
function! neomake#makers#ft#idris#EnabledMakers() abort |
||||||
|
return ['idris'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#idris#Postprocess(entry) abort |
||||||
|
call neomake#postprocess#compress_whitespace(a:entry) |
||||||
|
" Extract length from the beginning of the entry ('-4:When checking left hand side of xor:'). |
||||||
|
if a:entry.text =~# '\v^\d+:' |
||||||
|
let end = 0 + a:entry.text " cast to int |
||||||
|
let a:entry.length = end - a:entry.col |
||||||
|
let a:entry.text = substitute(a:entry.text, '\v^([^:]+:){2} ', '', '') |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#idris#idris() abort |
||||||
|
return { |
||||||
|
\ 'exe': 'idris', |
||||||
|
\ 'args': ['--check', '--warn', '--total', '--warnpartial', '--warnreach'], |
||||||
|
\ 'errorformat': |
||||||
|
\ '%E%f:%l:%c:%.%#,%-C %#%m,%-C%.%#,'. |
||||||
|
\ '%E%f:%l:%c-%m,%-C %#%m,%-C%.%#', |
||||||
|
\ 'postprocess': function('neomake#makers#ft#idris#Postprocess'), |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
" vim: ts=4 sw=4 et |
@ -0,0 +1,13 @@ |
|||||||
|
" vim: ts=4 sw=4 et |
||||||
|
|
||||||
|
function! neomake#makers#ft#jade#EnabledMakers() abort |
||||||
|
return ['jadelint'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#jade#jadelint() abort |
||||||
|
return { |
||||||
|
\ 'exe': 'jade-lint', |
||||||
|
\ 'args': ['--reporter', 'inline'], |
||||||
|
\ 'errorformat': '%f:%l:%c %m' |
||||||
|
\ } |
||||||
|
endfunction |
@ -0,0 +1,9 @@ |
|||||||
|
function! neomake#makers#ft#jasmine#SupersetOf() abort |
||||||
|
return 'javascript' |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#jasmine#EnabledMakers() abort |
||||||
|
return ['jshint', 'eslint', 'jscs'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
" vim: ts=4 sw=4 et |
@ -0,0 +1,396 @@ |
|||||||
|
"============================================================================ |
||||||
|
"File: java.vim |
||||||
|
"Description: Syntax checking plugin for neomake |
||||||
|
"Maintainer: Wang Shidong <wsdjeg at outlook dot com> |
||||||
|
"License: This program is free software. It comes without any warranty, |
||||||
|
" to the extent permitted by applicable law. You can redistribute |
||||||
|
" it and/or modify it under the terms of the Do What The Fuck You |
||||||
|
" Want To Public License, Version 2, as published by Sam Hocevar. |
||||||
|
" See http://sam.zoy.org/wtfpl/COPYING for more details. |
||||||
|
"============================================================================ |
||||||
|
|
||||||
|
let s:save_cpo = &cpoptions |
||||||
|
set cpoptions&vim |
||||||
|
|
||||||
|
if exists('g:loaded_neomake_java_javac_maker') |
||||||
|
finish |
||||||
|
endif |
||||||
|
let g:loaded_neomake_java_javac_maker = 1 |
||||||
|
|
||||||
|
let g:neomake_java_javac_maven_pom_tags = ['build', 'properties'] |
||||||
|
let g:neomake_java_javac_maven_pom_properties = {} |
||||||
|
let s:is_windows = has('win32') || has('win64') || has('win16') || has('dos32') || has('dos16') |
||||||
|
if s:is_windows |
||||||
|
let s:fsep = ';' |
||||||
|
let s:psep = '\' |
||||||
|
else |
||||||
|
let s:fsep = ':' |
||||||
|
let s:psep = '/' |
||||||
|
endif |
||||||
|
let g:neomake_java_checker_home = fnamemodify(expand('<sfile>'), ':p:h:gs?\\?/?') |
||||||
|
|
||||||
|
" custom options |
||||||
|
let g:neomake_java_javac_executable = |
||||||
|
\ get(g:, 'neomake_java_javac_executable', 'javac') |
||||||
|
|
||||||
|
let g:neomake_java_maven_executable = |
||||||
|
\ get(g:, 'neomake_java_maven_executable', 'mvn') |
||||||
|
|
||||||
|
let g:neomake_java_gradle_executable = |
||||||
|
\ get(g:, 'neomake_java_gradle_executable', s:is_windows? '.\gradlew.bat' : './gradlew') |
||||||
|
|
||||||
|
let g:neomake_java_ant_executable = |
||||||
|
\ get(g:, 'neomake_java_ant_executable', 'ant') |
||||||
|
|
||||||
|
let g:neomake_java_checkstyle_executable = |
||||||
|
\ get(g:, 'neomake_java_checkstyle_executable', 'checkstyle') |
||||||
|
|
||||||
|
let g:neomake_java_javac_options = |
||||||
|
\ get(g:, 'neomake_java_javac_options', ['-Xlint']) |
||||||
|
|
||||||
|
let g:neomake_java_maven_options = |
||||||
|
\ get(g:, 'neomake_java_maven_options', '') |
||||||
|
|
||||||
|
let g:neomake_java_javac_classpath = |
||||||
|
\ get(g:, 'neomake_java_javac_classpath', '') |
||||||
|
|
||||||
|
let g:neomake_java_javac_outputdir = |
||||||
|
\ get(g:, 'neomake_java_javac_outputdir', '') |
||||||
|
|
||||||
|
let g:neomake_java_checkstyle_xml = |
||||||
|
\ get(g:, 'neomake_java_checkstyle_xml', '/usr/share/checkstyle/google_checks.xml') |
||||||
|
|
||||||
|
let g:neomake_java_javac_delete_output = |
||||||
|
\ get(g:, 'neomake_java_javac_delete_output', 1) |
||||||
|
|
||||||
|
let g:neomake_java_javac_autoload_maven_classpath = |
||||||
|
\ get(g:, 'neomake_java_javac_autoload_maven_classpath', 1) |
||||||
|
|
||||||
|
let g:neomake_java_javac_autoload_gradle_classpath = |
||||||
|
\ get(g:, 'neomake_java_javac_autoload_gradle_classpath', 1) |
||||||
|
|
||||||
|
let g:neomake_java_javac_autoload_ant_classpath = |
||||||
|
\ get(g:, 'neomake_java_javac_autoload_ant_classpath', 1) |
||||||
|
|
||||||
|
let g:neomake_java_javac_autoload_eclipse_classpath = |
||||||
|
\ get(g:, 'neomake_java_javac_autoload_eclipse_classpath', 1) |
||||||
|
|
||||||
|
let g:neomake_java_javac_maven_pom_ftime = |
||||||
|
\ get(g:, 'neomake_java_javac_maven_pom_ftime', {}) |
||||||
|
|
||||||
|
let g:neomake_java_javac_maven_pom_classpath = |
||||||
|
\ get(g:, 'neomake_java_javac_maven_pom_classpath', {}) |
||||||
|
|
||||||
|
let g:neomake_java_javac_gradle_ftime = |
||||||
|
\ get(g:, 'neomake_java_javac_gradle_ftime', {}) |
||||||
|
|
||||||
|
let g:neomake_java_javac_gradle_classpath = |
||||||
|
\ get(g:, 'neomake_java_javac_gradle_classpath', {}) |
||||||
|
|
||||||
|
let g:neomake_java_javac_ant_ftime = |
||||||
|
\ get(g:, 'neomake_java_javac_ant_ftime', {}) |
||||||
|
|
||||||
|
let g:neomake_java_javac_ant_classpath = |
||||||
|
\ get(g:, 'neomake_java_javac_ant_classpath', {}) |
||||||
|
|
||||||
|
|
||||||
|
let s:has_maven = executable(expand(g:neomake_java_maven_executable, 1)) |
||||||
|
let s:has_gradle = executable(expand(g:neomake_java_gradle_executable, 1)) |
||||||
|
let s:has_ant = executable(expand(g:neomake_java_ant_executable, 1)) |
||||||
|
|
||||||
|
function! s:tmpdir() abort |
||||||
|
let tempdir = tempname() |
||||||
|
call mkdir(tempdir, 'p', 0700) |
||||||
|
return tempdir |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:ClassSep() abort |
||||||
|
return (s:is_windows || has('win32unix')) ? ';' : ':' |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:shescape(string) abort |
||||||
|
return neomake#utils#shellescape(a:string) |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:AddToClasspath(classpath, path) abort |
||||||
|
if a:path ==# '' |
||||||
|
return a:classpath |
||||||
|
endif |
||||||
|
return (a:classpath !=# '') ? a:classpath . s:ClassSep() . a:path : a:path |
||||||
|
endfunction |
||||||
|
|
||||||
|
" @vimlint(EVL103, 1, a:classpathFile) |
||||||
|
function! s:ReadClassPathFile(classpathFile) abort |
||||||
|
let cp = '' |
||||||
|
let file = g:neomake_java_checker_home. s:psep. 'java'. s:psep. 'classpath.py' |
||||||
|
if has('python3') |
||||||
|
execute 'py3file' file |
||||||
|
py3 import vim |
||||||
|
py3 vim.command("let cp = '%s'" % os.pathsep.join(ReadClasspathFile(vim.eval('a:classpathFile'))).replace('\\', '/')) |
||||||
|
elseif has('python') |
||||||
|
execute 'pyfile' file |
||||||
|
py import vim |
||||||
|
py vim.command("let cp = '%s'" % os.pathsep.join(ReadClasspathFile(vim.eval('a:classpathFile'))).replace('\\', '/')) |
||||||
|
endif |
||||||
|
return cp |
||||||
|
endfunction |
||||||
|
" @vimlint(EVL103, 0, a:classpathFile) |
||||||
|
|
||||||
|
function! neomake#makers#ft#java#EnabledMakers() abort |
||||||
|
let makers = [] |
||||||
|
if executable(expand(g:neomake_java_javac_executable, 1)) |
||||||
|
call add(makers, g:neomake_java_javac_executable) |
||||||
|
endif |
||||||
|
if executable(expand(g:neomake_java_checkstyle_executable, 1)) |
||||||
|
call add(makers, g:neomake_java_checkstyle_executable) |
||||||
|
endif |
||||||
|
return makers |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#java#javac() abort |
||||||
|
let javac_opts = extend([], g:neomake_java_javac_options) |
||||||
|
|
||||||
|
let output_dir = '' |
||||||
|
if g:neomake_java_javac_delete_output |
||||||
|
let output_dir = s:tmpdir() |
||||||
|
let javac_opts = extend(javac_opts, ['-d', s:shescape(output_dir)]) |
||||||
|
endif |
||||||
|
|
||||||
|
let javac_classpath = get(g:, 'neomake_java_javac_classpath', '') |
||||||
|
|
||||||
|
if s:has_maven && g:neomake_java_javac_autoload_maven_classpath && empty(javac_classpath) |
||||||
|
if !g:neomake_java_javac_delete_output |
||||||
|
let javac_opts = extend(javac_opts, ['-d', s:shescape(s:MavenOutputDirectory())]) |
||||||
|
endif |
||||||
|
let javac_classpath = s:AddToClasspath(javac_classpath, s:GetMavenClasspath()) |
||||||
|
endif |
||||||
|
|
||||||
|
if s:has_gradle && g:neomake_java_javac_autoload_gradle_classpath && empty(javac_classpath) |
||||||
|
if !g:neomake_java_javac_delete_output |
||||||
|
let javac_opts = extend(javac_opts, ['-d', s:shescape(s:GradleOutputDirectory())]) |
||||||
|
endif |
||||||
|
let javac_classpath = s:AddToClasspath(javac_classpath, s:GetGradleClasspath()) |
||||||
|
endif |
||||||
|
|
||||||
|
if s:has_ant && g:neomake_java_javac_autoload_ant_classpath && empty(javac_classpath) |
||||||
|
let javac_classpath = s:AddToClasspath(javac_classpath, s:GetAntClasspath()) |
||||||
|
endif |
||||||
|
|
||||||
|
if (has('python') || has('python3')) && empty(javac_classpath) |
||||||
|
let classpathFile = fnamemodify(findfile('.classpath', escape(expand('.'), '*[]?{}, ') . ';'), ':p') |
||||||
|
if !empty(classpathFile) && filereadable(classpathFile) |
||||||
|
let javac_classpath = s:ReadClassPathFile(classpathFile) |
||||||
|
endif |
||||||
|
endif |
||||||
|
|
||||||
|
if javac_classpath !=# '' |
||||||
|
let javac_opts = extend(javac_opts, ['-cp', javac_classpath]) |
||||||
|
endif |
||||||
|
|
||||||
|
return { |
||||||
|
\ 'args': javac_opts, |
||||||
|
\ 'exe': g:neomake_java_javac_executable, |
||||||
|
\ 'errorformat': |
||||||
|
\ '%E%f:%l: error: %m,'. |
||||||
|
\ '%W%f:%l: warning: %m,'. |
||||||
|
\ '%E%f:%l: %m,'. |
||||||
|
\ '%Z%p^,'. |
||||||
|
\ '%-G%.%#', |
||||||
|
\ 'version_arg': '-version' |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#java#checkstyle() abort |
||||||
|
return { |
||||||
|
\ 'args': ['-c', g:neomake_java_checkstyle_xml], |
||||||
|
\ 'exe': g:neomake_java_checkstyle_executable, |
||||||
|
\ 'errorformat': |
||||||
|
\ '%-GStarting audit...,'. |
||||||
|
\ '%-GAudit done.,'. |
||||||
|
\ '%-GPicked up _JAVA_OPTIONS:%.%#,'. |
||||||
|
\ '[%t%*[^]]] %f:%l:%c: %m [%s],'. |
||||||
|
\ '[%t%*[^]]] %f:%l: %m [%s]', |
||||||
|
\ 'version_arg': '-v' |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:findFileInParent(what, where) abort " {{{2 |
||||||
|
let old_suffixesadd = &suffixesadd |
||||||
|
let &suffixesadd = '' |
||||||
|
let file = findfile(a:what, escape(a:where, ' ') . ';') |
||||||
|
let &suffixesadd = old_suffixesadd |
||||||
|
return file |
||||||
|
endfunction " }}}2 |
||||||
|
|
||||||
|
function! s:GetMavenProperties() abort " {{{2 |
||||||
|
let mvn_properties = {} |
||||||
|
let pom = s:findFileInParent('pom.xml', expand('%:p:h', 1)) |
||||||
|
if s:has_maven && filereadable(pom) |
||||||
|
if !has_key(g:neomake_java_javac_maven_pom_properties, pom) |
||||||
|
let mvn_cmd = s:shescape(expand(g:neomake_java_maven_executable, 1)) . |
||||||
|
\ ' -f ' . s:shescape(pom) . |
||||||
|
\ ' ' . g:neomake_java_maven_options |
||||||
|
let mvn_is_managed_tag = 1 |
||||||
|
let mvn_settings_output = split(system(mvn_cmd . ' help:effective-pom'), "\n") |
||||||
|
let current_path = 'project' |
||||||
|
for line in mvn_settings_output |
||||||
|
let matches = matchlist(line, '\m^\s*<\([a-zA-Z0-9\-\.]\+\)>\s*$') |
||||||
|
if mvn_is_managed_tag && !empty(matches) |
||||||
|
let mvn_is_managed_tag = index(g:neomake_java_javac_maven_pom_tags, matches[1]) >= 0 |
||||||
|
let current_path .= '.' . matches[1] |
||||||
|
else |
||||||
|
let matches = matchlist(line, '\m^\s*</\([a-zA-Z0-9\-\.]\+\)>\s*$') |
||||||
|
if !empty(matches) |
||||||
|
let mvn_is_managed_tag = index(g:neomake_java_javac_maven_pom_tags, matches[1]) < 0 |
||||||
|
let current_path = substitute(current_path, '\m\.' . matches[1] . '$', '', '') |
||||||
|
else |
||||||
|
let matches = matchlist(line, '\m^\s*<\([a-zA-Z0-9\-\.]\+\)>\(.\+\)</[a-zA-Z0-9\-\.]\+>\s*$') |
||||||
|
if mvn_is_managed_tag && !empty(matches) |
||||||
|
let mvn_properties[current_path . '.' . matches[1]] = matches[2] |
||||||
|
endif |
||||||
|
endif |
||||||
|
endif |
||||||
|
endfor |
||||||
|
let g:neomake_java_javac_maven_pom_properties[pom] = mvn_properties |
||||||
|
endif |
||||||
|
return g:neomake_java_javac_maven_pom_properties[pom] |
||||||
|
endif |
||||||
|
return mvn_properties |
||||||
|
endfunction " }}}2 |
||||||
|
|
||||||
|
function! s:GetMavenClasspath() abort " {{{2 |
||||||
|
let pom = s:findFileInParent('pom.xml', expand('%:p:h', 1)) |
||||||
|
if s:has_maven && filereadable(pom) |
||||||
|
if !has_key(g:neomake_java_javac_maven_pom_ftime, pom) || g:neomake_java_javac_maven_pom_ftime[pom] != getftime(pom) |
||||||
|
let mvn_cmd = s:shescape(expand(g:neomake_java_maven_executable, 1)) . |
||||||
|
\ ' -f ' . s:shescape(pom) . |
||||||
|
\ ' ' . g:neomake_java_maven_options |
||||||
|
let mvn_classpath_output = split(system(mvn_cmd . ' dependency:build-classpath -DincludeScope=test'), "\n") |
||||||
|
let mvn_classpath = '' |
||||||
|
let class_path_next = 0 |
||||||
|
|
||||||
|
for line in mvn_classpath_output |
||||||
|
if class_path_next == 1 |
||||||
|
let mvn_classpath = substitute(line, "\r", '', 'g') |
||||||
|
break |
||||||
|
endif |
||||||
|
if stridx(line, 'Dependencies classpath:') >= 0 |
||||||
|
let class_path_next = 1 |
||||||
|
endif |
||||||
|
endfor |
||||||
|
|
||||||
|
let mvn_properties = s:GetMavenProperties() |
||||||
|
|
||||||
|
let output_dir = get(mvn_properties, 'project.build.outputDirectory', join(['target', 'classes'], s:psep)) |
||||||
|
let mvn_classpath = s:AddToClasspath(mvn_classpath, output_dir) |
||||||
|
|
||||||
|
let test_output_dir = get(mvn_properties, 'project.build.testOutputDirectory', join(['target', 'test-classes'], s:psep)) |
||||||
|
let mvn_classpath = s:AddToClasspath(mvn_classpath, test_output_dir) |
||||||
|
|
||||||
|
let g:neomake_java_javac_maven_pom_ftime[pom] = getftime(pom) |
||||||
|
let g:neomake_java_javac_maven_pom_classpath[pom] = mvn_classpath |
||||||
|
endif |
||||||
|
return g:neomake_java_javac_maven_pom_classpath[pom] |
||||||
|
endif |
||||||
|
return '' |
||||||
|
endfunction " }}}2 |
||||||
|
|
||||||
|
function! s:MavenOutputDirectory() abort " {{{2 |
||||||
|
let pom = s:findFileInParent('pom.xml', expand('%:p:h', 1)) |
||||||
|
if s:has_maven && filereadable(pom) |
||||||
|
let mvn_properties = s:GetMavenProperties() |
||||||
|
let output_dir = get(mvn_properties, 'project.properties.build.dir', getcwd()) |
||||||
|
|
||||||
|
let src_main_dir = get(mvn_properties, 'project.build.sourceDirectory', join(['src', 'main', 'java'], s:psep)) |
||||||
|
let src_test_dir = get(mvn_properties, 'project.build.testsourceDirectory', join(['src', 'test', 'java'], s:psep)) |
||||||
|
if stridx(expand('%:p:h', 1), src_main_dir) >= 0 |
||||||
|
let output_dir = get(mvn_properties, 'project.build.outputDirectory', join ([output_dir, 'target', 'classes'], s:psep)) |
||||||
|
endif |
||||||
|
if stridx(expand('%:p:h', 1), src_test_dir) >= 0 |
||||||
|
let output_dir = get(mvn_properties, 'project.build.testOutputDirectory', join([output_dir, 'target', 'test-classes'], s:psep)) |
||||||
|
endif |
||||||
|
|
||||||
|
if has('win32unix') |
||||||
|
let output_dir = substitute(system('cygpath -m ' . s:shescape(output_dir)), "\n", '', 'g') |
||||||
|
endif |
||||||
|
return output_dir |
||||||
|
endif |
||||||
|
return '.' |
||||||
|
endfunction " }}}2 |
||||||
|
|
||||||
|
function! s:GradleOutputDirectory() abort |
||||||
|
let gradle_build = s:findFileInParent('build.gradle', expand('%:p:h', 1)) |
||||||
|
let items = split(gradle_build, s:psep) |
||||||
|
if len(items)==1 |
||||||
|
return join(['build', 'intermediates', 'classes', 'debug'], s:psep) |
||||||
|
endif |
||||||
|
let outputdir = '' |
||||||
|
for i in items |
||||||
|
if i !=# 'build.gradle' |
||||||
|
let outputdir .= i . s:psep |
||||||
|
endif |
||||||
|
endfor |
||||||
|
return outputdir . join(['build', 'intermediates', 'classes', 'debug'], s:psep) |
||||||
|
endf |
||||||
|
|
||||||
|
function! s:GetGradleClasspath() abort |
||||||
|
let gradle = s:findFileInParent('build.gradle', expand('%:p:h', 1)) |
||||||
|
if s:has_gradle && filereadable(gradle) |
||||||
|
if !has_key(g:neomake_java_javac_gradle_ftime, gradle) || g:neomake_java_javac_gradle_ftime[gradle] != getftime(gradle) |
||||||
|
try |
||||||
|
let f = tempname() |
||||||
|
if s:is_windows |
||||||
|
let gradle_cmd = '.\gradlew.bat' |
||||||
|
else |
||||||
|
let gradle_cmd = './gradlew' |
||||||
|
endif |
||||||
|
call writefile(["allprojects{apply from: '" . g:neomake_java_checker_home . s:psep. 'java'. s:psep. "classpath.gradle'}"], f) |
||||||
|
let ret = system(gradle_cmd . ' -q -I ' . shellescape(f) . ' classpath' ) |
||||||
|
if v:shell_error == 0 |
||||||
|
let cp = filter(split(ret, "\n"), "v:val =~# '^CLASSPATH:'")[0][10:] |
||||||
|
if filereadable(getcwd() . s:psep . 'build.gradle') |
||||||
|
let out_putdir = neomake#compat#globpath_list(getcwd(), join( |
||||||
|
\ ['**', 'build', 'intermediates', 'classes', 'debug'], |
||||||
|
\ s:psep), 0) |
||||||
|
for classes in out_putdir |
||||||
|
let cp .= s:ClassSep() . classes |
||||||
|
endfor |
||||||
|
endif |
||||||
|
else |
||||||
|
let cp = '' |
||||||
|
endif |
||||||
|
catch |
||||||
|
finally |
||||||
|
call delete(f) |
||||||
|
endtry |
||||||
|
let g:neomake_java_javac_gradle_ftime[gradle] = getftime(gradle) |
||||||
|
let g:neomake_java_javac_gradle_classpath[gradle] = cp |
||||||
|
endif |
||||||
|
return g:neomake_java_javac_gradle_classpath[gradle] |
||||||
|
endif |
||||||
|
return '' |
||||||
|
endf |
||||||
|
|
||||||
|
function! s:GetAntClasspath() abort |
||||||
|
let ant = s:findFileInParent('build.xml', expand('%:p:h', 1)) |
||||||
|
if s:has_ant && filereadable(ant) |
||||||
|
if !has_key(g:neomake_java_javac_ant_ftime, ant) || g:neomake_java_javac_ant_ftime[ant] != getftime(ant) |
||||||
|
try |
||||||
|
let ant_cmd = 'ant classpath -f build.xml -S -q' |
||||||
|
let cp = system(ant_cmd) |
||||||
|
if v:shell_error != 0 |
||||||
|
let cp = '' |
||||||
|
endif |
||||||
|
catch |
||||||
|
endtry |
||||||
|
let g:neomake_java_javac_ant_ftime[ant] = getftime(ant) |
||||||
|
let g:neomake_java_javac_ant_classpath[ant] = cp |
||||||
|
endif |
||||||
|
return g:neomake_java_javac_ant_classpath[ant] |
||||||
|
endif |
||||||
|
return '' |
||||||
|
endf |
||||||
|
|
||||||
|
let &cpoptions = s:save_cpo |
||||||
|
unlet s:save_cpo |
||||||
|
" vim: ts=4 sw=4 et |
@ -0,0 +1,46 @@ |
|||||||
|
task classpath << { |
||||||
|
|
||||||
|
String finalFileContents = "" |
||||||
|
HashSet<String> classpathFiles = new HashSet<String>() |
||||||
|
for (proj in allprojects) { |
||||||
|
|
||||||
|
def exploded = proj.getBuildDir().absolutePath + File.separator + "intermediates" + File.separator + "exploded-aar" |
||||||
|
def listFiles = new File(exploded) |
||||||
|
if (listFiles.exists()) { |
||||||
|
listFiles.eachFileRecurse(){ file -> |
||||||
|
if (file.name.endsWith(".jar")){ |
||||||
|
classpathFiles += file |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
def rjava = proj.getBuildDir().absolutePath + File.separator + "intermediates" + File.separator + "classes" + File.separator + "debug" |
||||||
|
def rFiles = new File(rjava) |
||||||
|
if (rFiles.exists()) { |
||||||
|
classpathFiles += rFiles |
||||||
|
} |
||||||
|
|
||||||
|
for (conf in proj.configurations) { |
||||||
|
for (dependency in conf) { |
||||||
|
if (dependency.name.endsWith("aar")){ |
||||||
|
} else { |
||||||
|
classpathFiles += dependency |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
if (proj.hasProperty("android")){ |
||||||
|
classpathFiles += proj.android.bootClasspath |
||||||
|
} |
||||||
|
|
||||||
|
if (proj.hasProperty("sourceSets")) { |
||||||
|
|
||||||
|
for (srcSet in proj.sourceSets) { |
||||||
|
for (dir in srcSet.java.srcDirs) { |
||||||
|
classpathFiles += dir.absolutePath |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
def paths = classpathFiles.join(File.pathSeparator) |
||||||
|
println "CLASSPATH:" + paths |
||||||
|
} |
@ -0,0 +1,15 @@ |
|||||||
|
import os |
||||||
|
from xml.etree.ElementTree import * |
||||||
|
|
||||||
|
|
||||||
|
def ReadClasspathFile(fn): |
||||||
|
cp = [] |
||||||
|
for a in parse(fn).findall('classpathentry'): |
||||||
|
kind = a.get('kind') |
||||||
|
if kind == 'src' and 'output' in a.keys(): |
||||||
|
cp.append(os.path.abspath(a.get('output'))) |
||||||
|
elif kind == 'lib' and 'path' in a.keys(): |
||||||
|
cp.append(os.path.abspath(a.get('path'))) |
||||||
|
elif kind == 'output' and 'path' in a.keys(): |
||||||
|
cp.append(os.path.abspath(a.get('path'))) |
||||||
|
return cp |
@ -0,0 +1,119 @@ |
|||||||
|
" vim: ts=4 sw=4 et |
||||||
|
|
||||||
|
function! neomake#makers#ft#javascript#EnabledMakers() abort |
||||||
|
return ['jshint', 'jscs', |
||||||
|
\ executable('eslint_d') ? 'eslint_d' : 'eslint', |
||||||
|
\] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#javascript#tsc() abort |
||||||
|
return neomake#makers#ft#typescript#tsc() |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#javascript#gjslint() abort |
||||||
|
return { |
||||||
|
\ 'args': ['--nodebug_indentation', '--nosummary', '--unix_mode', '--nobeep'], |
||||||
|
\ 'errorformat': '%f:%l:(New Error -%\\?\%n) %m,' . |
||||||
|
\ '%f:%l:(-%\\?%n) %m,' . |
||||||
|
\ '%-G1 files checked,' . |
||||||
|
\ ' no errors found.,' . |
||||||
|
\ '%-G%.%#' |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#javascript#jshint() abort |
||||||
|
return { |
||||||
|
\ 'args': ['--verbose'], |
||||||
|
\ 'errorformat': '%A%f: line %l\, col %v\, %m \(%t%*\d\),%-G,%-G%\\d%\\+ errors', |
||||||
|
\ 'postprocess': function('neomake#postprocess#generic_length'), |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#javascript#jscs() abort |
||||||
|
return { |
||||||
|
\ 'args': ['--no-colors', '--reporter', 'inline'], |
||||||
|
\ 'errorformat': '%E%f: line %l\, col %c\, %m', |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#javascript#eslint() abort |
||||||
|
let maker = { |
||||||
|
\ 'args': ['--format=compact'], |
||||||
|
\ 'errorformat': '%E%f: line %l\, col %c\, Error - %m,' . |
||||||
|
\ '%W%f: line %l\, col %c\, Warning - %m,%-G,%-G%*\d problems%#', |
||||||
|
\ 'cwd': '%:p:h', |
||||||
|
\ 'output_stream': 'stdout', |
||||||
|
\ } |
||||||
|
|
||||||
|
function! maker.supports_stdin(_jobinfo) abort |
||||||
|
let self.args += ['--stdin', '--stdin-filename=%:p'] |
||||||
|
let self.tempfile_name = '' |
||||||
|
return 1 |
||||||
|
endfunction |
||||||
|
|
||||||
|
return maker |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#javascript#eslint_d() abort |
||||||
|
return neomake#makers#ft#javascript#eslint() |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#javascript#standard() abort |
||||||
|
return { |
||||||
|
\ 'args': ['-v'], |
||||||
|
\ 'errorformat': '%W %f:%l:%c: %m,%-Gstandard: %.%#' |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#javascript#semistandard() abort |
||||||
|
return { |
||||||
|
\ 'errorformat': '%W %f:%l:%c: %m' |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#javascript#rjsx() abort |
||||||
|
return { |
||||||
|
\ 'exe': 'emacs', |
||||||
|
\ 'args': ['%t','--quick','--batch','--eval=' |
||||||
|
\ .'(progn(setq package-load-list ''((js2-mode t)(rjsx-mode t)))(package-initialize)(require ''rjsx-mode)' |
||||||
|
\ .' (setq js2-include-node-externs t js2-include-rhino-externs t js2-include-browser-externs t js2-strict-missing-semi-warning nil)' |
||||||
|
\ .' (rjsx-mode)(js2-reparse)(js2-display-error-list)' |
||||||
|
\ .' (princ(replace-regexp-in-string "^" (concat buffer-file-name " ")' |
||||||
|
\ .' (with-current-buffer "*js-lint*" (buffer-substring-no-properties(point-min)(point-max)))))(terpri))'], |
||||||
|
\ 'errorformat': '%f line %l: %m,%-G%.%#', |
||||||
|
\ 'append_file': 0, |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#javascript#flow() abort |
||||||
|
return { |
||||||
|
\ 'args': ['--from=vim', '--show-all-errors'], |
||||||
|
\ 'errorformat': |
||||||
|
\ '%-GNo errors!,' |
||||||
|
\ .'%EFile "%f"\, line %l\, characters %c-%m,' |
||||||
|
\ .'%trror: File "%f"\, line %l\, characters %c-%m,' |
||||||
|
\ .'%C%m,%Z', |
||||||
|
\ 'postprocess': function('neomake#makers#ft#javascript#FlowProcess') |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#javascript#FlowProcess(entry) abort |
||||||
|
let lines = split(a:entry.text, '\n') |
||||||
|
if !empty(lines) |
||||||
|
let a:entry.text = join(lines[1:]) |
||||||
|
let a:entry.length = lines[0] - a:entry.col + 1 |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#javascript#xo() abort |
||||||
|
return { |
||||||
|
\ 'args': ['--compact'], |
||||||
|
\ 'errorformat': '%E%f: line %l\, col %c\, Error - %m,' . |
||||||
|
\ '%W%f: line %l\, col %c\, Warning - %m', |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#javascript#stylelint() abort |
||||||
|
return neomake#makers#ft#css#stylelint() |
||||||
|
endfunction |
||||||
|
|
@ -0,0 +1,38 @@ |
|||||||
|
function! neomake#makers#ft#json#EnabledMakers() abort |
||||||
|
return ['jsonlint'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#json#jsonlintpy() abort |
||||||
|
return { |
||||||
|
\ 'exe': 'jsonlint-py', |
||||||
|
\ 'args': ['--strict'], |
||||||
|
\ 'errorformat': |
||||||
|
\ '%f:%l:%c: %trror: %m,' . |
||||||
|
\ '%f:%l:%c: %tarning: %m,', |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#json#jsonlint() abort |
||||||
|
return { |
||||||
|
\ 'args': ['--compact'], |
||||||
|
\ 'errorformat': |
||||||
|
\ '%ELine %l:%c,'. |
||||||
|
\ '%Z\\s%#Reason: %m,'. |
||||||
|
\ '%C%.%#,'. |
||||||
|
\ '%f: line %l\, col %c\, %m,'. |
||||||
|
\ '%-G%.%#' |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#json#eslint() abort |
||||||
|
let maker = neomake#makers#ft#javascript#eslint() |
||||||
|
let maker.args += ['--plugin', 'json'] |
||||||
|
return maker |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#json#eslint_d() abort |
||||||
|
let maker = neomake#makers#ft#javascript#eslint_d() |
||||||
|
let maker.args += ['--plugin', 'json'] |
||||||
|
return maker |
||||||
|
endfunction |
||||||
|
" vim: ts=4 sw=4 et |
@ -0,0 +1,17 @@ |
|||||||
|
function! neomake#makers#ft#jsx#SupersetOf() abort |
||||||
|
return 'javascript' |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#jsx#EnabledMakers() abort |
||||||
|
return ['jshint', executable('eslint_d') ? 'eslint_d' : 'eslint'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#jsx#jsxhint() abort |
||||||
|
return neomake#makers#ft#javascript#jshint() |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#jsx#stylelint() abort |
||||||
|
return neomake#makers#ft#css#stylelint() |
||||||
|
endfunction |
||||||
|
|
||||||
|
" vim: ts=4 sw=4 et |
@ -0,0 +1,24 @@ |
|||||||
|
function! neomake#makers#ft#julia#EnabledMakers() abort |
||||||
|
return ['lint'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#julia#lint() abort |
||||||
|
return { |
||||||
|
\ 'errorformat': '%f:%l %t%*[^ ] %m', |
||||||
|
\ 'exe': 'julia', |
||||||
|
\ 'args': ['-e', ' |
||||||
|
\ try |
||||||
|
\ using Lint |
||||||
|
\ catch |
||||||
|
\ println("$(basename(ARGS[1])):1 E999 Install Lint.jl: Pkg.add(""Lint"")"); |
||||||
|
\ exit(1) |
||||||
|
\ end; |
||||||
|
\ r = lintfile(ARGS[1]); |
||||||
|
\ if !isempty(r) |
||||||
|
\ display(r); |
||||||
|
\ exit(1) |
||||||
|
\ end |
||||||
|
\ '] |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
" vim: ts=4 sw=4 et |
@ -0,0 +1,12 @@ |
|||||||
|
" vim: ts=4 sw=4 et |
||||||
|
|
||||||
|
function! neomake#makers#ft#kotlin#EnabledMakers() abort |
||||||
|
return ['ktlint'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#kotlin#ktlint() abort |
||||||
|
return { |
||||||
|
\ 'errorformat': '%E%f:%l:%c: %m', |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
@ -0,0 +1,19 @@ |
|||||||
|
" vim: ts=4 sw=4 et |
||||||
|
|
||||||
|
function! neomake#makers#ft#less#EnabledMakers() abort |
||||||
|
return executable('stylelint') ? ['stylelint'] : ['lessc'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#less#lessc() abort |
||||||
|
return { |
||||||
|
\ 'args': ['--lint', '--no-color'], |
||||||
|
\ 'errorformat': |
||||||
|
\ '%m in %f on line %l\, column %c:,' . |
||||||
|
\ '%m in %f:%l:%c,' . |
||||||
|
\ '%-G%.%#' |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#less#stylelint() abort |
||||||
|
return neomake#makers#ft#css#stylelint() |
||||||
|
endfunction |
@ -0,0 +1,11 @@ |
|||||||
|
" vim: ts=4 sw=4 et |
||||||
|
|
||||||
|
function! neomake#makers#ft#lex#EnabledMakers() abort |
||||||
|
return ['flex'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#lex#flex() abort |
||||||
|
return { |
||||||
|
\ 'errorformat': '%f:%l: %m' |
||||||
|
\ } |
||||||
|
endfunction |
@ -0,0 +1,34 @@ |
|||||||
|
function! neomake#makers#ft#lua#EnabledMakers() abort |
||||||
|
return executable('luacheck') ? ['luacheck'] : ['luac'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
" luacheck: postprocess: use pattern (%s) for end column. |
||||||
|
function! neomake#makers#ft#lua#PostprocessLuacheck(entry) abort |
||||||
|
if !(a:entry.type ==# 'W' && a:entry.nr ==# 631) |
||||||
|
" Add length, but not with W631 (line too long). |
||||||
|
let end_col = matchstr(a:entry.pattern, '\v\d+') |
||||||
|
if !empty(end_col) |
||||||
|
let a:entry.length = end_col - a:entry.col + 1 |
||||||
|
endif |
||||||
|
endif |
||||||
|
let a:entry.pattern = '' |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#lua#luacheck() abort |
||||||
|
" cwd: luacheck looks for .luacheckrc upwards from there. |
||||||
|
return { |
||||||
|
\ 'args': ['--no-color', '--formatter=plain', '--ranges', '--codes', '--filename', '%:p'], |
||||||
|
\ 'cwd': '%:p:h', |
||||||
|
\ 'errorformat': '%E%f:%l:%c-%s: \(%t%n\) %m', |
||||||
|
\ 'postprocess': function('neomake#makers#ft#lua#PostprocessLuacheck'), |
||||||
|
\ 'supports_stdin': 1, |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#lua#luac() abort |
||||||
|
return { |
||||||
|
\ 'args': ['-p'], |
||||||
|
\ 'errorformat': '%*\f: %#%f:%l: %m', |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
" vim: ts=4 sw=4 et |
@ -0,0 +1,8 @@ |
|||||||
|
function! neomake#makers#ft#mail#EnabledMakers() abort |
||||||
|
return ['proselint'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#mail#proselint() abort |
||||||
|
return neomake#makers#ft#text#proselint() |
||||||
|
endfunction |
||||||
|
" vim: ts=4 sw=4 et |
@ -0,0 +1,97 @@ |
|||||||
|
function! neomake#makers#ft#markdown#SupersetOf() abort |
||||||
|
return 'text' |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#markdown#EnabledMakers() abort |
||||||
|
let makers = executable('mdl') ? ['mdl'] : ['markdownlint'] |
||||||
|
if executable('vale') | let makers += ['vale'] | endif |
||||||
|
return makers + neomake#makers#ft#text#EnabledMakers() |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#markdown#mdl() abort |
||||||
|
let maker = { |
||||||
|
\ |
||||||
|
\ 'errorformat': |
||||||
|
\ '%W%f:%l: %m,%-G%.%#', |
||||||
|
\ 'output_stream': 'stdout', |
||||||
|
\ } |
||||||
|
function! maker.postprocess(entry) abort |
||||||
|
if a:entry.text[0:1] ==# 'MD' |
||||||
|
let [code, text] = split(a:entry.text, '\v^MD\d+\zs ') |
||||||
|
let a:entry.nr = str2nr(code[2:]) |
||||||
|
let a:entry.text = printf('%s (%s)', text, code) |
||||||
|
endif |
||||||
|
return a:entry |
||||||
|
endfunction |
||||||
|
return maker |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#markdown#markdownlint() abort |
||||||
|
return { |
||||||
|
\ 'errorformat': '%f: %l: %m' |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
let s:alex_supports_stdin = {} |
||||||
|
function! neomake#makers#ft#markdown#alex() abort |
||||||
|
let maker = { |
||||||
|
\ 'errorformat': |
||||||
|
\ '%P%f,' |
||||||
|
\ .'%-Q,' |
||||||
|
\ .'%*[ ]%l:%c-%*\d:%n%*[ ]%tarning%*[ ]%m,' |
||||||
|
\ .'%-G%.%#' |
||||||
|
\ } |
||||||
|
|
||||||
|
function! maker.supports_stdin(_jobinfo) abort |
||||||
|
let exe = exists('*exepath') ? exepath(self.exe) : self.exe |
||||||
|
let support = get(s:alex_supports_stdin, exe, -1) |
||||||
|
if support == -1 |
||||||
|
let ver = neomake#compat#systemlist(['alex', '--version']) |
||||||
|
let ver_split = split(ver[0], '\.') |
||||||
|
if len(ver_split) > 1 && (ver_split[0] > 0 || +ver_split[1] >= 6) |
||||||
|
let support = 1 |
||||||
|
else |
||||||
|
let support = 0 |
||||||
|
endif |
||||||
|
let s:alex_supports_stdin[exe] = support |
||||||
|
call neomake#log#debug('alex: stdin support: '.support.'.') |
||||||
|
endif |
||||||
|
if support |
||||||
|
let self.args += ['--stdin'] |
||||||
|
let self.tempfile_name = '' |
||||||
|
endif |
||||||
|
return support |
||||||
|
endfunction |
||||||
|
|
||||||
|
return maker |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#markdown#ProcessVale(context) abort |
||||||
|
let entries = [] |
||||||
|
for [filename, items] in items(a:context['json']) |
||||||
|
for data in items |
||||||
|
let entry = { |
||||||
|
\ 'maker_name': 'vale', |
||||||
|
\ 'filename': filename, |
||||||
|
\ 'text': data.Message, |
||||||
|
\ 'lnum': data.Line, |
||||||
|
\ 'col': data.Span[0], |
||||||
|
\ 'length': data.Span[1] - data.Span[0] + 1, |
||||||
|
\ 'type': toupper(data.Severity[0]) |
||||||
|
\ } |
||||||
|
call add(entries, entry) |
||||||
|
endfor |
||||||
|
endfor |
||||||
|
return entries |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#markdown#vale() abort |
||||||
|
return { |
||||||
|
\ 'args': [ |
||||||
|
\ '--no-wrap', |
||||||
|
\ '--output', 'JSON' |
||||||
|
\ ], |
||||||
|
\ 'process_json': function('neomake#makers#ft#markdown#ProcessVale') |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
" vim: ts=4 sw=4 et |
@ -0,0 +1,15 @@ |
|||||||
|
" vim: ts=4 sw=4 et |
||||||
|
|
||||||
|
function! neomake#makers#ft#matlab#EnabledMakers() abort |
||||||
|
return ['mlint'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#matlab#mlint() abort |
||||||
|
return { |
||||||
|
\ 'args': ['-id'], |
||||||
|
\ 'mapexpr': "neomake_bufname.':'.v:val", |
||||||
|
\ 'errorformat': |
||||||
|
\ '%f:L %l (C %c): %m,'. |
||||||
|
\ '%f:L %l (C %c-%*[0-9]): %m,', |
||||||
|
\ } |
||||||
|
endfunction |
@ -0,0 +1,15 @@ |
|||||||
|
function! neomake#makers#ft#moon#EnabledMakers() abort |
||||||
|
return ['moonc'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#moon#moonc() abort |
||||||
|
return { |
||||||
|
\ 'args': ['-l'], |
||||||
|
\ 'errorformat': |
||||||
|
\ '%-G,' . |
||||||
|
\ '%-G>%#,' . |
||||||
|
\ '%+P%f,'. |
||||||
|
\ 'line\ %l:\ %m' |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
" vim: ts=4 sw=4 et |
@ -0,0 +1,66 @@ |
|||||||
|
if !exists('g:neomake_test_messages') |
||||||
|
" Only use it during tests. |
||||||
|
finish |
||||||
|
endif |
||||||
|
|
||||||
|
function! neomake#makers#ft#neomake_tests#EnabledMakers() abort |
||||||
|
return get(b:, 'neomake_test_enabledmakers', |
||||||
|
\ get(g:, 'neomake_test_enabledmakers', |
||||||
|
\ ['maker_without_exe', 'nonexisting'])) |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#neomake_tests#maker_without_exe() abort |
||||||
|
return {} |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#neomake_tests#maker_with_nonstring_exe() abort |
||||||
|
return {'exe': function('tr')} |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#neomake_tests#echo_maker() abort |
||||||
|
return { |
||||||
|
\ 'exe': 'printf', |
||||||
|
\ 'args': 'neomake_tests_echo_maker', |
||||||
|
\ 'errorformat': '%m', |
||||||
|
\ 'append_file': 0, |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#neomake_tests#echo_args() abort |
||||||
|
return { |
||||||
|
\ 'exe': 'echo', |
||||||
|
\ 'errorformat': '%m', |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#neomake_tests#true() abort |
||||||
|
return {} |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#neomake_tests#error_maker() abort |
||||||
|
return { |
||||||
|
\ 'exe': 'printf', |
||||||
|
\ 'args': ['%s:1:error_msg_1'], |
||||||
|
\ 'errorformat': '%E%f:%l:%m', |
||||||
|
\ 'append_file': 1, |
||||||
|
\ 'short_name': 'errmkr', |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#neomake_tests#process_output_error() abort |
||||||
|
let maker = {'exe': 'echo', 'args': 'output', 'append_file': 0} |
||||||
|
|
||||||
|
function! maker.process_output(...) abort |
||||||
|
return [{'valid': 1, 'text': 'error', 'lnum': 1, 'bufnr': bufnr('%')}] |
||||||
|
endfunction |
||||||
|
return maker |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#neomake_tests#success_entry_maker() abort |
||||||
|
let maker = {} |
||||||
|
function! maker.get_list_entries(...) abort |
||||||
|
return [] |
||||||
|
endfunction |
||||||
|
return maker |
||||||
|
endfunction |
||||||
|
" vim: ts=4 sw=4 et |
@ -0,0 +1,16 @@ |
|||||||
|
function! neomake#makers#ft#nim#EnabledMakers() abort |
||||||
|
return ['nim'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#nim#nim() abort |
||||||
|
return { |
||||||
|
\ 'exe': 'nim', |
||||||
|
\ 'args': ['--listFullPaths', '--verbosity:0', '--colors:off', |
||||||
|
\ '-c', 'check'], |
||||||
|
\ 'errorformat': |
||||||
|
\ '%I%f(%l\, %c) Hint: %m,' . |
||||||
|
\ '%W%f(%l\, %c) Warning: %m,' . |
||||||
|
\ '%E%f(%l\, %c) Error: %m' |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
" vim: ts=4 sw=4 et |
@ -0,0 +1,14 @@ |
|||||||
|
" vim: ts=4 sw=4 et |
||||||
|
" |
||||||
|
function! neomake#makers#ft#nix#EnabledMakers() abort |
||||||
|
return ['nix_instantiate'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#nix#nix_instantiate() abort |
||||||
|
return { |
||||||
|
\ 'exe': 'nix-instantiate', |
||||||
|
\ 'args': ['--parse-only'], |
||||||
|
\ 'errorformat': 'error: %m at %f:%l:%c' |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
@ -0,0 +1,9 @@ |
|||||||
|
function! neomake#makers#ft#node#SupersetOf() abort |
||||||
|
return 'javascript' |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#node#EnabledMakers() abort |
||||||
|
return ['jshint', 'eslint', 'jscs'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
" vim: ts=4 sw=4 et |
@ -0,0 +1,55 @@ |
|||||||
|
" vim: ts=4 sw=4 et |
||||||
|
|
||||||
|
function! neomake#makers#ft#objc#EnabledMakers() abort |
||||||
|
let makers = ['clang', 'clangtidy', 'clangcheck'] |
||||||
|
return makers |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#objc#clang() abort |
||||||
|
" We will enable ARC and disable warnings about unused parameters because |
||||||
|
" it is quite common in Cocoa not to use every method parameter. |
||||||
|
return { |
||||||
|
\ 'args': ['-fsyntax-only', '-fobjc-arc', '-Wall', '-Wextra', '-Wno-unused-parameter'], |
||||||
|
\ 'errorformat': |
||||||
|
\ '%-G%f:%s:,' . |
||||||
|
\ '%f:%l:%c: %trror: %m,' . |
||||||
|
\ '%f:%l:%c: %tarning: %m,' . |
||||||
|
\ '%I%f:%l:%c: note: %m,' . |
||||||
|
\ '%f:%l:%c: %m,'. |
||||||
|
\ '%f:%l: %trror: %m,'. |
||||||
|
\ '%f:%l: %tarning: %m,'. |
||||||
|
\ '%I%f:%l: note: %m,'. |
||||||
|
\ '%f:%l: %m' |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
" The -p option followed by the path to the build directory should be set in |
||||||
|
" the maker's arguments. That directory should contain the compile command |
||||||
|
" database (compile_commands.json). |
||||||
|
function! neomake#makers#ft#objc#clangtidy() abort |
||||||
|
return { |
||||||
|
\ 'exe': 'clang-tidy', |
||||||
|
\ 'errorformat': |
||||||
|
\ '%E%f:%l:%c: fatal error: %m,' . |
||||||
|
\ '%E%f:%l:%c: error: %m,' . |
||||||
|
\ '%W%f:%l:%c: warning: %m,' . |
||||||
|
\ '%-G%\m%\%%(LLVM ERROR:%\|No compilation database found%\)%\@!%.%#,' . |
||||||
|
\ '%E%m', |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#objc#clangcheck() abort |
||||||
|
return { |
||||||
|
\ 'exe': 'clang-check', |
||||||
|
\ 'errorformat': |
||||||
|
\ '%-G%f:%s:,' . |
||||||
|
\ '%f:%l:%c: %trror: %m,' . |
||||||
|
\ '%f:%l:%c: %tarning: %m,' . |
||||||
|
\ '%I%f:%l:%c: note: %m,' . |
||||||
|
\ '%f:%l:%c: %m,'. |
||||||
|
\ '%f:%l: %trror: %m,'. |
||||||
|
\ '%f:%l: %tarning: %m,'. |
||||||
|
\ '%I%f:%l: note: %m,'. |
||||||
|
\ '%f:%l: %m', |
||||||
|
\ } |
||||||
|
endfunction |
@ -0,0 +1,8 @@ |
|||||||
|
function! neomake#makers#ft#pandoc#SupersetOf() abort |
||||||
|
return 'markdown' |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#pandoc#EnabledMakers() abort |
||||||
|
return neomake#makers#ft#markdown#EnabledMakers() |
||||||
|
endfunction |
||||||
|
" vim: ts=4 sw=4 et |
@ -0,0 +1,34 @@ |
|||||||
|
" vim: ts=4 sw=4 et |
||||||
|
function! neomake#makers#ft#perl#EnabledMakers() abort |
||||||
|
return ['perl', 'perlcritic'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#perl#perlcritic() abort |
||||||
|
return { |
||||||
|
\ 'args' : ['--quiet', '--nocolor', '--verbose', |
||||||
|
\ '\\%f:\\%l:\\%c:(\\%s) \\%m (\\%e)\\n'], |
||||||
|
\ 'errorformat': '%f:%l:%c:%m,' |
||||||
|
\} |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#perl#perl() abort |
||||||
|
return { |
||||||
|
\ 'args' : ['-c', '-X', '-Mwarnings'], |
||||||
|
\ 'errorformat': '%-G%.%#had too many errors.,' |
||||||
|
\ . '%-G%.%#had compilation errors.,' |
||||||
|
\ . '%-G%.%#syntax OK,' |
||||||
|
\ . '%m at %f line %l.,' |
||||||
|
\ . '%+E%.%# at %f line %l\,%.%#,' |
||||||
|
\ . '%+C%.%#', |
||||||
|
\ 'postprocess': function('neomake#makers#ft#perl#PerlEntryProcess'), |
||||||
|
\} |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#perl#PerlEntryProcess(entry) abort |
||||||
|
let extramsg = substitute(a:entry.pattern, '\^\\V', '', '') |
||||||
|
let extramsg = substitute(extramsg, '\\\$', '', '') |
||||||
|
|
||||||
|
if !empty(extramsg) |
||||||
|
let a:entry.text .= ' ' . extramsg |
||||||
|
endif |
||||||
|
endfunction |
@ -0,0 +1,72 @@ |
|||||||
|
" vim: ts=4 sw=4 et |
||||||
|
|
||||||
|
function! neomake#makers#ft#php#EnabledMakers() abort |
||||||
|
return ['php', 'phpmd', 'phpcs', 'phpstan'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#php#php() abort |
||||||
|
return { |
||||||
|
\ 'args': ['-l', '-d', 'display_errors=1', '-d', 'log_errors=0', |
||||||
|
\ '-d', 'xdebug.cli_color=0'], |
||||||
|
\ 'errorformat': |
||||||
|
\ '%-GNo syntax errors detected in%.%#,'. |
||||||
|
\ '%EParse error: %#syntax error\, %m in %f on line %l,'. |
||||||
|
\ '%EParse error: %m in %f on line %l,'. |
||||||
|
\ '%EFatal error: %m in %f on line %l,'. |
||||||
|
\ '%-G\s%#,'. |
||||||
|
\ '%-GErrors parsing %.%#', |
||||||
|
\ 'output_stream': 'stdout', |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#php#phpcs() abort |
||||||
|
let args = ['--report=csv', '-q'] |
||||||
|
|
||||||
|
"Add standard argument if one is set. |
||||||
|
if exists('g:neomake_php_phpcs_args_standard') |
||||||
|
call add(args, '--standard=' . expand(g:neomake_php_phpcs_args_standard)) |
||||||
|
endif |
||||||
|
|
||||||
|
return { |
||||||
|
\ 'args': args, |
||||||
|
\ 'errorformat': |
||||||
|
\ '%-GFile\,Line\,Column\,Type\,Message\,Source\,Severity%.%#,'. |
||||||
|
\ '"%f"\,%l\,%c\,%t%*[a-zA-Z]\,"%m"\,%*[a-zA-Z0-9_.-]\,%*[0-9]%.%#', |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#php#phpmd() abort |
||||||
|
return { |
||||||
|
\ 'args': ['%t', 'text', 'codesize,design,unusedcode,naming'], |
||||||
|
\ 'append_file': 0, |
||||||
|
\ 'errorformat': '%W%f:%l%\s%\s%#%m' |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#php#phpstan() abort |
||||||
|
" PHPStan normally considers 0 to be the default level, so that is used here as the default: |
||||||
|
let maker = { |
||||||
|
\ 'args': ['analyse', '--error-format', 'raw', '--no-progress', '--level', get(g:, 'neomake_phpstan_level', 0)], |
||||||
|
\ 'errorformat': '%E%f:%l:%m', |
||||||
|
\ } |
||||||
|
" Check for the existence of a default PHPStan project configuration file. |
||||||
|
" Technically PHPStan does not have a concept of a default filename for a |
||||||
|
" project configuration file, but phpstan.neon is the filename shown in the |
||||||
|
" example in the PHPStan documentation, so this is the default name expected |
||||||
|
" by Neomake. |
||||||
|
let phpStanConfigFilePath = neomake#utils#FindGlobFile('phpstan.neon') |
||||||
|
if !empty(phpStanConfigFilePath) |
||||||
|
call extend(maker.args, ['-c', phpStanConfigFilePath]) |
||||||
|
endif |
||||||
|
return maker |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#php#psalm() abort |
||||||
|
let maker = { |
||||||
|
\ 'args': [ |
||||||
|
\ '--output-format=pylint' |
||||||
|
\ ], |
||||||
|
\ 'errorformat': '%A%f:%l:%\s[%t%n]%\s%m', |
||||||
|
\ } |
||||||
|
return maker |
||||||
|
endfunction |
@ -0,0 +1,12 @@ |
|||||||
|
function! neomake#makers#ft#proto#EnabledMakers() abort |
||||||
|
return ['prototool'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#proto#prototool() abort |
||||||
|
return { |
||||||
|
\ 'exe': 'prototool', |
||||||
|
\ 'args': ['lint'], |
||||||
|
\ 'errorformat': '%f:%l:%c:%m', |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
" vim: ts=4 sw=4 et |
@ -0,0 +1,13 @@ |
|||||||
|
" vim: ts=4 sw=4 et |
||||||
|
|
||||||
|
function! neomake#makers#ft#pug#EnabledMakers() abort |
||||||
|
return ['puglint'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#pug#puglint() abort |
||||||
|
return { |
||||||
|
\ 'exe': 'pug-lint', |
||||||
|
\ 'args': ['--reporter', 'inline'], |
||||||
|
\ 'errorformat': '%f:%l:%c %m' |
||||||
|
\ } |
||||||
|
endfunction |
@ -0,0 +1,29 @@ |
|||||||
|
function! neomake#makers#ft#puppet#EnabledMakers() abort |
||||||
|
return ['puppet', 'puppetlint'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#puppet#puppetlint() abort |
||||||
|
return { |
||||||
|
\ 'exe': 'puppet-lint', |
||||||
|
\ 'args': ['--log-format', '%%{path}:%%{line}:%%{column}:%%{kind}:[%%{check}] %%{message}'], |
||||||
|
\ 'errorformat': '%f:%l:%c:%t%*[a-zA-Z]:%m', |
||||||
|
\ 'short_name': 'pupl', |
||||||
|
\ 'output_stream': 'stdout', |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#puppet#puppet() abort |
||||||
|
return { |
||||||
|
\ 'args': ['parser', 'validate', '--color=false'], |
||||||
|
\ 'errorformat': |
||||||
|
\ '%-Gerr: Try ''puppet help parser validate'' for usage,' . |
||||||
|
\ '%-GError: Try ''puppet help parser validate'' for usage,' . |
||||||
|
\ '%t%*[a-zA-Z]: %m at %f:%l:%c,' . |
||||||
|
\ '%t%*[a-zA-Z]: %m at %f:%l,'. |
||||||
|
\ '%t%*[a-zA-Z]: Could not parse for environment production: %m (file: %f\, line: %l\, column: %c),' . |
||||||
|
\ '%t%*[a-zA-Z]: Could not parse for environment production: %m (file: %f)', |
||||||
|
\ 'short_name': 'pupp', |
||||||
|
\ 'output_stream': 'stderr', |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
" vim: ts=4 sw=4 et |
@ -0,0 +1,63 @@ |
|||||||
|
" vim: ts=4 sw=4 et |
||||||
|
|
||||||
|
function! neomake#makers#ft#purescript#EnabledMakers() abort |
||||||
|
return ['pulp'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#purescript#pulp() abort |
||||||
|
" command is `pulp build --no-psa -- --json-errors` |
||||||
|
" as indicated in https://github.com/nwolverson/atom-ide-purescript/issues/136 |
||||||
|
let maker = { |
||||||
|
\ 'args': ['build', '--no-psa', '--', '--json-errors'], |
||||||
|
\ 'append_file': 0, |
||||||
|
\ 'process_output': function('neomake#makers#ft#purescript#PSProcessOutput'), |
||||||
|
\ } |
||||||
|
|
||||||
|
" Find project root, since files are reported relative to it. |
||||||
|
let bower_file = neomake#utils#FindGlobFile('bower.json') |
||||||
|
if !empty(bower_file) |
||||||
|
let maker.cwd = fnamemodify(bower_file, ':h') |
||||||
|
endif |
||||||
|
|
||||||
|
return maker |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#purescript#PSProcessOutput(context) abort |
||||||
|
let errors = [] |
||||||
|
for line in a:context.output |
||||||
|
if line[0] !=# '{' |
||||||
|
continue |
||||||
|
endif |
||||||
|
let decoded = neomake#compat#json_decode(line) |
||||||
|
for [key, values] in items(decoded) |
||||||
|
let code = key ==# 'warnings' ? 'W' : 'E' |
||||||
|
for item in values |
||||||
|
let compiler_error = item['errorCode'] |
||||||
|
let message = item['message'] |
||||||
|
let position = item['position'] |
||||||
|
let filename = item['filename'] |
||||||
|
if position is g:neomake#compat#json_null |
||||||
|
let row = 1 |
||||||
|
let col = 1 |
||||||
|
let end_col = 1 |
||||||
|
let length = 1 |
||||||
|
else |
||||||
|
let row = position['startLine'] |
||||||
|
let col = position['startColumn'] |
||||||
|
let end_col = position['endColumn'] |
||||||
|
let length = end_col - col |
||||||
|
endif |
||||||
|
|
||||||
|
call add(errors, { |
||||||
|
\ 'text': compiler_error . ' : ' . message, |
||||||
|
\ 'type': code, |
||||||
|
\ 'lnum': row, |
||||||
|
\ 'col': col, |
||||||
|
\ 'length': length, |
||||||
|
\ 'filename': filename, |
||||||
|
\ }) |
||||||
|
endfor |
||||||
|
endfor |
||||||
|
endfor |
||||||
|
return errors |
||||||
|
endfunction |
@ -0,0 +1,458 @@ |
|||||||
|
" vim: ts=4 sw=4 et |
||||||
|
|
||||||
|
if !exists('s:compile_script') |
||||||
|
let s:slash = neomake#utils#Slash() |
||||||
|
let s:compile_script = expand('<sfile>:p:h', 1).s:slash.'python'.s:slash.'compile.py' |
||||||
|
endif |
||||||
|
|
||||||
|
function! neomake#makers#ft#python#EnabledMakers() abort |
||||||
|
let makers = ['python', 'frosted'] |
||||||
|
if executable('pylama') |
||||||
|
call add(makers, 'pylama') |
||||||
|
else |
||||||
|
if executable('flake8') |
||||||
|
call add(makers, 'flake8') |
||||||
|
else |
||||||
|
call extend(makers, ['pyflakes', 'pycodestyle', 'pydocstyle']) |
||||||
|
endif |
||||||
|
call add(makers, 'pylint') " Last because it is the slowest |
||||||
|
endif |
||||||
|
return makers |
||||||
|
endfunction |
||||||
|
|
||||||
|
let neomake#makers#ft#python#project_root_files = ['setup.cfg', 'tox.ini'] |
||||||
|
|
||||||
|
function! neomake#makers#ft#python#DetectPythonVersion() abort |
||||||
|
let output = neomake#compat#systemlist('python -V 2>&1') |
||||||
|
if v:shell_error |
||||||
|
call neomake#log#error(printf( |
||||||
|
\ 'Failed to detect Python version: %s.', |
||||||
|
\ join(output))) |
||||||
|
let s:python_version = [-1, -1, -1] |
||||||
|
else |
||||||
|
let s:python_version = split(split(output[0])[1], '\.') |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
|
||||||
|
let s:ignore_python_warnings = [ |
||||||
|
\ '\v[\/]inspect.py:\d+: Warning:', |
||||||
|
\ '\v^.{-}:\d+: FutureWarning:', |
||||||
|
\ ] |
||||||
|
|
||||||
|
" Filter Python warnings (the warning and the following line). |
||||||
|
" To be used as a funcref with filter(). |
||||||
|
function! s:filter_py_warning(v) abort |
||||||
|
if s:filter_next_py_warning |
||||||
|
let s:filter_next_py_warning = 0 |
||||||
|
" Only keep (expected) lines starting with two spaces. |
||||||
|
return a:v[0:1] !=# ' ' |
||||||
|
endif |
||||||
|
for pattern in s:ignore_python_warnings |
||||||
|
if a:v =~# pattern |
||||||
|
let s:filter_next_py_warning = 1 |
||||||
|
return 0 |
||||||
|
endif |
||||||
|
endfor |
||||||
|
return 1 |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#python#FilterPythonWarnings(lines, context) abort |
||||||
|
if a:context.source ==# 'stderr' |
||||||
|
let s:filter_next_py_warning = 0 |
||||||
|
call filter(a:lines, 's:filter_py_warning(v:val)') |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#python#pylint() abort |
||||||
|
let maker = { |
||||||
|
\ 'args': [ |
||||||
|
\ '--output-format=text', |
||||||
|
\ '--msg-template="{path}:{line}:{column}:{C}: [{symbol}] {msg} [{msg_id}]"', |
||||||
|
\ '--reports=no' |
||||||
|
\ ], |
||||||
|
\ 'errorformat': |
||||||
|
\ '%A%f:%l:%c:%t: %m,' . |
||||||
|
\ '%A%f:%l: %m,' . |
||||||
|
\ '%A%f:(%l): %m,' . |
||||||
|
\ '%-Z%p^%.%#,' . |
||||||
|
\ '%-G%.%#', |
||||||
|
\ 'output_stream': 'stdout', |
||||||
|
\ 'postprocess': [ |
||||||
|
\ function('neomake#postprocess#generic_length'), |
||||||
|
\ function('neomake#makers#ft#python#PylintEntryProcess'), |
||||||
|
\ ]} |
||||||
|
function! maker.filter_output(lines, context) abort |
||||||
|
if a:context.source ==# 'stderr' |
||||||
|
call filter(a:lines, "v:val !=# 'No config file found, using default configuration' && v:val !~# '^Using config file '") |
||||||
|
endif |
||||||
|
call neomake#makers#ft#python#FilterPythonWarnings(a:lines, a:context) |
||||||
|
endfunction |
||||||
|
return maker |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#python#PylintEntryProcess(entry) abort |
||||||
|
if a:entry.type ==# 'F' " Fatal error which prevented further processing |
||||||
|
let type = 'E' |
||||||
|
elseif a:entry.type ==# 'E' " Error for important programming issues |
||||||
|
let type = 'E' |
||||||
|
elseif a:entry.type ==# 'W' " Warning for stylistic or minor programming issues |
||||||
|
let type = 'W' |
||||||
|
elseif a:entry.type ==# 'R' " Refactor suggestion |
||||||
|
let type = 'W' |
||||||
|
elseif a:entry.type ==# 'C' " Convention violation |
||||||
|
let type = 'W' |
||||||
|
elseif a:entry.type ==# 'I' " Informations |
||||||
|
let type = 'I' |
||||||
|
else |
||||||
|
let type = '' |
||||||
|
endif |
||||||
|
let a:entry.type = type |
||||||
|
" Pylint uses 0-indexed columns, vim uses 1-indexed columns |
||||||
|
let a:entry.col += 1 |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#python#flake8() abort |
||||||
|
let maker = { |
||||||
|
\ 'args': ['--format=default'], |
||||||
|
\ 'errorformat': |
||||||
|
\ '%E%f:%l: could not compile,%-Z%p^,' . |
||||||
|
\ '%A%f:%l:%c: %t%n %m,' . |
||||||
|
\ '%A%f:%l: %t%n %m,' . |
||||||
|
\ '%-G%.%#', |
||||||
|
\ 'postprocess': function('neomake#makers#ft#python#Flake8EntryProcess'), |
||||||
|
\ 'short_name': 'fl8', |
||||||
|
\ 'output_stream': 'stdout', |
||||||
|
\ 'filter_output': function('neomake#makers#ft#python#FilterPythonWarnings'), |
||||||
|
\ } |
||||||
|
|
||||||
|
function! maker.supports_stdin(jobinfo) abort |
||||||
|
let self.args += ['--stdin-display-name', '%:p'] |
||||||
|
|
||||||
|
let bufpath = bufname(a:jobinfo.bufnr) |
||||||
|
if !empty(bufpath) |
||||||
|
let bufdir = fnamemodify(bufpath, ':p:h') |
||||||
|
if stridx(bufdir, getcwd()) != 0 |
||||||
|
" The buffer is not below the current dir, so let's cd for lookup |
||||||
|
" of config files etc. |
||||||
|
" This avoids running into issues with flake8's per-file-ignores, |
||||||
|
" which is handled not relative to the config file currently |
||||||
|
" (https://gitlab.com/pycqa/flake8/issues/517). |
||||||
|
call a:jobinfo.cd(bufdir) |
||||||
|
endif |
||||||
|
endif |
||||||
|
return 1 |
||||||
|
endfunction |
||||||
|
return maker |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#python#Flake8EntryProcess(entry) abort |
||||||
|
if a:entry.type ==# 'F' " pyflakes |
||||||
|
" Ref: http://flake8.pycqa.org/en/latest/user/error-codes.html |
||||||
|
if a:entry.nr > 400 && a:entry.nr < 500 |
||||||
|
if a:entry.nr == 407 |
||||||
|
let type = 'E' " 'an undefined __future__ feature name was imported' |
||||||
|
else |
||||||
|
let type = 'W' |
||||||
|
endif |
||||||
|
elseif a:entry.nr == 841 |
||||||
|
let type = 'W' |
||||||
|
else |
||||||
|
let type = 'E' |
||||||
|
endif |
||||||
|
elseif a:entry.type ==# 'E' && a:entry.nr >= 900 " PEP8 runtime errors (E901, E902) |
||||||
|
let type = 'E' |
||||||
|
elseif a:entry.type ==# 'E' || a:entry.type ==# 'W' " PEP8 errors & warnings |
||||||
|
let type = 'W' |
||||||
|
elseif a:entry.type ==# 'N' || a:entry.type ==# 'D' " Naming (PEP8) & docstring (PEP257) conventions |
||||||
|
let type = 'W' |
||||||
|
elseif a:entry.type ==# 'C' || a:entry.type ==# 'T' " McCabe complexity & todo notes |
||||||
|
let type = 'I' |
||||||
|
elseif a:entry.type ==# 'I' " keep at least 'I' from isort (I1), could get style subtype?! |
||||||
|
let type = a:entry.type |
||||||
|
else |
||||||
|
let type = '' |
||||||
|
endif |
||||||
|
|
||||||
|
let token_pattern = '\v''\zs[^'']+\ze' |
||||||
|
if a:entry.type ==# 'F' && (a:entry.nr == 401 || a:entry.nr == 811) |
||||||
|
" Special handling for F401 (``module`` imported but unused) and |
||||||
|
" F811 (redefinition of unused ``name`` from line ``N``). |
||||||
|
" The unused column is incorrect for import errors and redefinition |
||||||
|
" errors. |
||||||
|
let token = matchstr(a:entry.text, token_pattern) |
||||||
|
if !empty(token) |
||||||
|
let view = winsaveview() |
||||||
|
call cursor(a:entry.lnum, a:entry.col) |
||||||
|
" The number of lines to give up searching afterwards |
||||||
|
let search_lines = 5 |
||||||
|
|
||||||
|
if searchpos('\<from\>', 'cnW', a:entry.lnum)[1] == a:entry.col |
||||||
|
" for 'from xxx.yyy import zzz' the token looks like |
||||||
|
" xxx.yyy.zzz, but only the zzz part should be highlighted. So |
||||||
|
" this discards the module part |
||||||
|
let token = split(token, '\.')[-1] |
||||||
|
|
||||||
|
" Also the search should be started at the import keyword. |
||||||
|
" Otherwise for 'from os import os' the first os will be |
||||||
|
" found. This moves the cursor there. |
||||||
|
call search('\<import\>', 'cW', a:entry.lnum + search_lines) |
||||||
|
endif |
||||||
|
|
||||||
|
" Search for the first occurrence of the token and highlight in |
||||||
|
" the next couple of lines and change the lnum and col to that |
||||||
|
" position. |
||||||
|
" Don't match entries surrounded by dots, even though |
||||||
|
" it ends a word, we want to find a full identifier. It also |
||||||
|
" matches all seperators such as spaces and newlines with |
||||||
|
" backslashes until it knows for sure the previous real character |
||||||
|
" was not a dot. |
||||||
|
let ident_pos = searchpos('\(\.\(\_s\|\\\)*\)\@<!\<' . |
||||||
|
\ token . '\>\(\(\_s\|\\\)*\.\)\@!', |
||||||
|
\ 'cnW', |
||||||
|
\ a:entry.lnum + search_lines) |
||||||
|
if ident_pos[1] > 0 |
||||||
|
let a:entry.lnum = ident_pos[0] |
||||||
|
let a:entry.col = ident_pos[1] |
||||||
|
endif |
||||||
|
|
||||||
|
call winrestview(view) |
||||||
|
|
||||||
|
let a:entry.length = strlen(token) |
||||||
|
endif |
||||||
|
else |
||||||
|
call neomake#postprocess#generic_length_with_pattern(a:entry, token_pattern) |
||||||
|
|
||||||
|
" Special processing for F821 (undefined name) in f-strings. |
||||||
|
if !has_key(a:entry, 'length') && a:entry.type ==# 'F' && a:entry.nr == 821 |
||||||
|
let token = matchstr(a:entry.text, token_pattern) |
||||||
|
if !empty(token) |
||||||
|
" Search for '{token}' in reported and following lines. |
||||||
|
" It seems like for the first line it is correct already (i.e. |
||||||
|
" flake8 reports the column therein), but we still test there |
||||||
|
" to be sure. |
||||||
|
" https://gitlab.com/pycqa/flake8/issues/407 |
||||||
|
let line = get(getbufline(a:entry.bufnr, a:entry.lnum), 0, '') |
||||||
|
" NOTE: uses byte offset, starting at col means to start after |
||||||
|
" the opening quote. |
||||||
|
let pattern = '\V\C{\.\{-}\zs'.escape(token, '\').'\>' |
||||||
|
let pos = match(line, pattern, a:entry.col) |
||||||
|
if pos == -1 |
||||||
|
let line_offset = 0 |
||||||
|
while line_offset < 10 |
||||||
|
let line_offset += 1 |
||||||
|
let line = get(getbufline(a:entry.bufnr, a:entry.lnum + line_offset), 0, '') |
||||||
|
let pos = match(line, pattern) |
||||||
|
if pos != -1 |
||||||
|
let a:entry.lnum = a:entry.lnum + line_offset |
||||||
|
break |
||||||
|
endif |
||||||
|
endwhile |
||||||
|
endif |
||||||
|
if pos > 0 |
||||||
|
let a:entry.col = pos + 1 |
||||||
|
let a:entry.length = strlen(token) |
||||||
|
endif |
||||||
|
endif |
||||||
|
endif |
||||||
|
endif |
||||||
|
|
||||||
|
let a:entry.text = a:entry.type . a:entry.nr . ' ' . a:entry.text |
||||||
|
let a:entry.type = type |
||||||
|
" Reset "nr" to Avoid redundancy with neomake#GetCurrentErrorMsg. |
||||||
|
" TODO: This is rather bad, since "nr" itself can be useful. |
||||||
|
" This should rather use the entry via Neomake's list, and then a |
||||||
|
" new property like "current_error_text" could be used. |
||||||
|
" Or with the maker being available a callback could be used. |
||||||
|
let a:entry.nr = -1 |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#python#pyflakes() abort |
||||||
|
return { |
||||||
|
\ 'errorformat': |
||||||
|
\ '%E%f:%l: could not compile,' . |
||||||
|
\ '%-Z%p^,'. |
||||||
|
\ '%E%f:%l:%c: %m,' . |
||||||
|
\ '%E%f:%l: %m,' . |
||||||
|
\ '%-G%.%#', |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#python#pycodestyle() abort |
||||||
|
if !exists('s:_pycodestyle_exe') |
||||||
|
" Use the preferred exe to avoid deprecation warnings. |
||||||
|
let s:_pycodestyle_exe = executable('pycodestyle') ? 'pycodestyle' : 'pep8' |
||||||
|
endif |
||||||
|
return { |
||||||
|
\ 'exe': s:_pycodestyle_exe, |
||||||
|
\ 'errorformat': '%f:%l:%c: %m', |
||||||
|
\ 'postprocess': function('neomake#makers#ft#python#Pep8EntryProcess') |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
" Note: pep8 has been renamed to pycodestyle, but is kept also as alias. |
||||||
|
function! neomake#makers#ft#python#pep8() abort |
||||||
|
return neomake#makers#ft#python#pycodestyle() |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#python#Pep8EntryProcess(entry) abort |
||||||
|
if a:entry.text =~# '^E9' " PEP8 runtime errors (E901, E902) |
||||||
|
let a:entry.type = 'E' |
||||||
|
elseif a:entry.text =~# '^E113' " unexpected indentation (IndentationError) |
||||||
|
let a:entry.type = 'E' |
||||||
|
else " Everything else is a warning |
||||||
|
let a:entry.type = 'W' |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#python#pydocstyle() abort |
||||||
|
if !exists('s:_pydocstyle_exe') |
||||||
|
" Use the preferred exe to avoid deprecation warnings. |
||||||
|
let s:_pydocstyle_exe = executable('pydocstyle') ? 'pydocstyle' : 'pep257' |
||||||
|
endif |
||||||
|
return { |
||||||
|
\ 'exe': s:_pydocstyle_exe, |
||||||
|
\ 'errorformat': |
||||||
|
\ '%W%f:%l %.%#:,' . |
||||||
|
\ '%+C %m', |
||||||
|
\ 'postprocess': function('neomake#postprocess#compress_whitespace'), |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
" Note: pep257 has been renamed to pydocstyle, but is kept also as alias. |
||||||
|
function! neomake#makers#ft#python#pep257() abort |
||||||
|
return neomake#makers#ft#python#pydocstyle() |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#python#PylamaEntryProcess(entry) abort |
||||||
|
if a:entry.nr == -1 |
||||||
|
" Get number from the beginning of text. |
||||||
|
let nr = matchstr(a:entry.text, '\v^\u\zs\d+') |
||||||
|
if !empty(nr) |
||||||
|
let a:entry.nr = nr + 0 |
||||||
|
endif |
||||||
|
endif |
||||||
|
if a:entry.type ==# 'C' && a:entry.text =~# '\v\[%(pycodestyle|pep8)\]$' |
||||||
|
call neomake#makers#ft#python#Pep8EntryProcess(a:entry) |
||||||
|
elseif a:entry.type ==# 'D' " pydocstyle/pep257 |
||||||
|
let a:entry.type = 'W' |
||||||
|
elseif a:entry.type ==# 'C' && a:entry.nr == 901 " mccabe |
||||||
|
let a:entry.type = 'I' |
||||||
|
elseif a:entry.type ==# 'R' " Radon |
||||||
|
let a:entry.type = 'W' |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#python#pylama() abort |
||||||
|
let maker = { |
||||||
|
\ 'args': ['--format', 'parsable'], |
||||||
|
\ 'errorformat': '%f:%l:%c: [%t] %m', |
||||||
|
\ 'postprocess': function('neomake#makers#ft#python#PylamaEntryProcess'), |
||||||
|
\ 'output_stream': 'stdout', |
||||||
|
\ } |
||||||
|
" Pylama looks for the config only in the current directory. |
||||||
|
" Therefore we change to where the config likely is. |
||||||
|
" --options could be used to pass a config file, but we cannot be sure |
||||||
|
" which one really gets used. |
||||||
|
let ini_file = neomake#utils#FindGlobFile('{pylama.ini,setup.cfg,tox.ini,pytest.ini}') |
||||||
|
if !empty(ini_file) |
||||||
|
let maker.cwd = fnamemodify(ini_file, ':h') |
||||||
|
endif |
||||||
|
return maker |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#python#python() abort |
||||||
|
return { |
||||||
|
\ 'args': [s:compile_script], |
||||||
|
\ 'errorformat': '%E%f:%l:%c: %m', |
||||||
|
\ 'serialize': 1, |
||||||
|
\ 'serialize_abort_on_error': 1, |
||||||
|
\ 'output_stream': 'stdout', |
||||||
|
\ 'short_name': 'py', |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#python#frosted() abort |
||||||
|
return { |
||||||
|
\ 'args': [ |
||||||
|
\ '-vb' |
||||||
|
\ ], |
||||||
|
\ 'errorformat': |
||||||
|
\ '%f:%l:%c:%m,' . |
||||||
|
\ '%E%f:%l: %m,' . |
||||||
|
\ '%-Z%p^,' . |
||||||
|
\ '%-G%.%#' |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#python#vulture() abort |
||||||
|
return { |
||||||
|
\ 'errorformat': '%f:%l: %m', |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#python#mypy() abort |
||||||
|
" NOTE: uses defaults suitable for using it without any config. |
||||||
|
" ignore_missing_imports cannot be disabled in a config then though |
||||||
|
let args = [ |
||||||
|
\ '--show-column-numbers', |
||||||
|
\ '--check-untyped-defs', |
||||||
|
\ '--ignore-missing-imports', |
||||||
|
\ ] |
||||||
|
|
||||||
|
" Append '--py2' to args with Python 2 for Python 2 mode. |
||||||
|
if !exists('s:python_version') |
||||||
|
call neomake#makers#ft#python#DetectPythonVersion() |
||||||
|
endif |
||||||
|
if s:python_version[0] ==# '2' |
||||||
|
call add(args, '--py2') |
||||||
|
endif |
||||||
|
|
||||||
|
let maker = { |
||||||
|
\ 'args': args, |
||||||
|
\ 'output_stream': 'stdout', |
||||||
|
\ 'errorformat': |
||||||
|
\ '%E%f:%l:%c: error: %m,' . |
||||||
|
\ '%W%f:%l:%c: warning: %m,' . |
||||||
|
\ '%I%f:%l:%c: note: %m,' . |
||||||
|
\ '%E%f:%l: error: %m,' . |
||||||
|
\ '%W%f:%l: warning: %m,' . |
||||||
|
\ '%I%f:%l: note: %m', |
||||||
|
\ } |
||||||
|
function! maker.InitForJob(jobinfo) abort |
||||||
|
let maker = deepcopy(self) |
||||||
|
let file_mode = a:jobinfo.file_mode |
||||||
|
if file_mode |
||||||
|
" Follow imports, but do not emit errors/issues for it, which |
||||||
|
" would result in errors for other buffers etc. |
||||||
|
" XXX: dmypy requires "skip" or "error" |
||||||
|
call insert(maker.args, '--follow-imports=silent') |
||||||
|
else |
||||||
|
let project_root = neomake#utils#get_project_root(a:jobinfo.bufnr) |
||||||
|
if empty(project_root) |
||||||
|
call add(maker.args, '.') |
||||||
|
else |
||||||
|
call add(maker.args, project_root) |
||||||
|
endif |
||||||
|
endif |
||||||
|
return maker |
||||||
|
endfunction |
||||||
|
function! maker.supports_stdin(jobinfo) abort |
||||||
|
if !has_key(self, 'tempfile_name') |
||||||
|
let self.tempfile_name = self._get_default_tempfilename(a:jobinfo) |
||||||
|
endif |
||||||
|
let self.args += ['--shadow-file', '%', self.tempfile_name] |
||||||
|
return 0 |
||||||
|
endfunction |
||||||
|
function! maker.postprocess(entry) abort |
||||||
|
if a:entry.text =~# '\v^Need type (annotation|comment) for' |
||||||
|
let a:entry.type = 'I' |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
return maker |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#python#py3kwarn() abort |
||||||
|
return { |
||||||
|
\ 'errorformat': '%W%f:%l:%c: %m', |
||||||
|
\ } |
||||||
|
endfunction |
@ -0,0 +1,14 @@ |
|||||||
|
#!/usr/bin/env python |
||||||
|
|
||||||
|
from __future__ import print_function |
||||||
|
from sys import argv, exit |
||||||
|
|
||||||
|
|
||||||
|
if len(argv) != 2: |
||||||
|
exit(64) |
||||||
|
|
||||||
|
try: |
||||||
|
compile(open(argv[1]).read(), argv[1], 'exec', 0, 1) |
||||||
|
except SyntaxError as err: |
||||||
|
print('%s:%s:%s: %s' % (err.filename, err.lineno, err.offset, err.msg)) |
||||||
|
exit(1) |
@ -0,0 +1,17 @@ |
|||||||
|
" vim: ts=4 sw=4 et |
||||||
|
|
||||||
|
function! neomake#makers#ft#r#EnabledMakers() abort |
||||||
|
return ['lintr'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#r#lintr() abort |
||||||
|
return { |
||||||
|
\ 'exe': 'R', |
||||||
|
\ 'args': ['--slave', '--no-restore', '--no-save', '-e lintr::lint("%t")'], |
||||||
|
\ 'append_file': 0, |
||||||
|
\ 'errorformat': |
||||||
|
\ '%W%f:%l:%c: style: %m,' . |
||||||
|
\ '%W%f:%l:%c: warning: %m,' . |
||||||
|
\ '%E%f:%l:%c: error: %m,' |
||||||
|
\ } |
||||||
|
endfunction |
@ -0,0 +1,32 @@ |
|||||||
|
" vim: ts=4 sw=4 et |
||||||
|
|
||||||
|
function! neomake#makers#ft#racket#EnabledMakers() abort |
||||||
|
return ['raco'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
" This is the same form of syntax-checking used by DrRacket as well. The |
||||||
|
" downside is that it will only catch the first error, but none of the |
||||||
|
" subsequent ones. This is due to how evaluation in Racket works. |
||||||
|
" |
||||||
|
" About the error format: raco will print the first line as |
||||||
|
" <file>:<line>:<column> <message> |
||||||
|
" Every successive line will be indented by two spaces: |
||||||
|
" in: <keyword> |
||||||
|
" context...: |
||||||
|
" <file>:<line>:<column>: <keyword> |
||||||
|
" The last pattern will be repeated as often as necessary. Example: |
||||||
|
" foo.rkt:4:1: dfine: unbound identifier in modulemessage |
||||||
|
" in: dfine |
||||||
|
" context...: |
||||||
|
" /usr/local/Cellar/racket/6.5/share/racket/pkgs/compiler-lib/compiler/commands/expand.rkt:34:15: loop |
||||||
|
" /usr/local/Cellar/racket/6.5/share/racket/pkgs/compiler-lib/compiler/commands/expand.rkt:10:2: show-program |
||||||
|
" /usr/local/Cellar/racket/6.5/share/racket/pkgs/compiler-lib/compiler/commands/expand.rkt: [running body] |
||||||
|
" /usr/local/Cellar/minimal-racket/6.6/share/racket/collects/raco/raco.rkt: [running body] |
||||||
|
" /usr/local/Cellar/minimal-racket/6.6/share/racket/collects/raco/main.rkt: [running body] |
||||||
|
function! neomake#makers#ft#racket#raco() abort |
||||||
|
return { |
||||||
|
\ 'exe': 'raco', |
||||||
|
\ 'args': ['expand'], |
||||||
|
\ 'errorformat': '%-G %.%#,%E%f:%l:%c: %m' |
||||||
|
\ } |
||||||
|
endfunction |
@ -0,0 +1,89 @@ |
|||||||
|
" vim: ts=4 sw=4 et |
||||||
|
|
||||||
|
function! neomake#makers#ft#rst#SupersetOf() abort |
||||||
|
return 'text' |
||||||
|
endfunction |
||||||
|
|
||||||
|
" Get Sphinx source dir for the current buffer (determined by looking for |
||||||
|
" conf.py, typically in docs/ or doc/). |
||||||
|
" Caches the value in a buffer-local setting. |
||||||
|
function! s:get_sphinx_srcdir() abort |
||||||
|
let srcdir = neomake#config#get('sphinx.source_dir') |
||||||
|
if srcdir isnot# g:neomake#config#undefined |
||||||
|
return srcdir |
||||||
|
endif |
||||||
|
|
||||||
|
let r = '' |
||||||
|
let project_root = neomake#utils#get_project_root() |
||||||
|
let bufname = bufname('%') |
||||||
|
if empty(bufname) |
||||||
|
call neomake#log#debug('sphinx: skipping setting of source_dir for empty bufname.', {'bufnr': bufnr('%')}) |
||||||
|
return '' |
||||||
|
endif |
||||||
|
let f = findfile('conf.py', printf('%s;%s', fnamemodify(bufname, ':p:h'), project_root)) |
||||||
|
if !empty(f) |
||||||
|
let r = fnamemodify(f, ':p:h') |
||||||
|
endif |
||||||
|
call neomake#log#debug(printf('sphinx: setting b:neomake.sphinx.source_dir=%s.', string(r)), {'bufnr': bufnr('%')}) |
||||||
|
call neomake#config#set('b:sphinx.source_dir', r) |
||||||
|
return r |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#rst#EnabledMakers() abort |
||||||
|
if executable('sphinx-build') && !empty(s:get_sphinx_srcdir()) |
||||||
|
return ['sphinx'] |
||||||
|
endif |
||||||
|
return ['rstlint', 'rstcheck'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#rst#rstlint() abort |
||||||
|
return { |
||||||
|
\ 'exe': 'rst-lint', |
||||||
|
\ 'errorformat': |
||||||
|
\ '%ESEVERE %f:%l %m,'. |
||||||
|
\ '%EERROR %f:%l %m,'. |
||||||
|
\ '%WWARNING %f:%l %m,'. |
||||||
|
\ '%IINFO %f:%l %m,'. |
||||||
|
\ '%C%m', |
||||||
|
\ 'postprocess': function('neomake#postprocess#compress_whitespace'), |
||||||
|
\ 'output_stream': 'stdout', |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#rst#rstcheck() abort |
||||||
|
return { |
||||||
|
\ 'errorformat': |
||||||
|
\ '%I%f:%l: (INFO/1) %m,'. |
||||||
|
\ '%W%f:%l: (WARNING/2) %m,'. |
||||||
|
\ '%E%f:%l: (ERROR/3) %m,'. |
||||||
|
\ '%E%f:%l: (SEVERE/4) %m', |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#rst#sphinx() abort |
||||||
|
" TODO: |
||||||
|
" - project mode (after cleanup branch) |
||||||
|
let srcdir = s:get_sphinx_srcdir() |
||||||
|
if empty(srcdir) |
||||||
|
throw 'Neomake: sphinx: could not find conf.py (you can configure sphinx.source_dir)' |
||||||
|
endif |
||||||
|
if !exists('s:sphinx_cache') |
||||||
|
let s:sphinx_cache = tempname() |
||||||
|
endif |
||||||
|
" NOTE: uses '%Z%m,%-G%.%#' instead of '%C%m,%-G' to include next line in |
||||||
|
" multiline errors (fixed in 7.4.203). |
||||||
|
return { |
||||||
|
\ 'exe': 'sphinx-build', |
||||||
|
\ 'args': ['-n', '-E', '-q', '-N', '-b', 'dummy', srcdir, s:sphinx_cache], |
||||||
|
\ 'append_file': 0, |
||||||
|
\ 'errorformat': |
||||||
|
\ '%f:%l: %tARNING: %m,' . |
||||||
|
\ '%EWARNING: %f:%l: (SEVER%t/4) %m,' . |
||||||
|
\ '%EWARNING: %f:%l: (%tRROR/3) %m,' . |
||||||
|
\ '%EWARNING: %f:%l: (%tARNING/2) %m,' . |
||||||
|
\ '%Z%m,' . |
||||||
|
\ '%-G%.%#', |
||||||
|
\ 'output_stream': 'stderr', |
||||||
|
\ 'postprocess': function('neomake#postprocess#compress_whitespace'), |
||||||
|
\ } |
||||||
|
endfunction |
@ -0,0 +1,98 @@ |
|||||||
|
" vim: ts=4 sw=4 et |
||||||
|
|
||||||
|
function! neomake#makers#ft#ruby#EnabledMakers() abort |
||||||
|
return ['flog', 'mri', 'rubocop', 'reek', 'rubylint'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#ruby#rubocop() abort |
||||||
|
let maker = { |
||||||
|
\ 'args': ['--format', 'emacs', '--force-exclusion', '--display-cop-names'], |
||||||
|
\ 'errorformat': '%f:%l:%c: %t: %m,%E%f:%l: %m', |
||||||
|
\ 'postprocess': function('neomake#makers#ft#ruby#RubocopEntryProcess'), |
||||||
|
\ 'output_stream': 'stdout', |
||||||
|
\ } |
||||||
|
|
||||||
|
function! maker.supports_stdin(_jobinfo) abort |
||||||
|
let self.args += ['--stdin', '%'] |
||||||
|
let self.tempfile_name = '' |
||||||
|
return 1 |
||||||
|
endfunction |
||||||
|
|
||||||
|
return maker |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#ruby#RubocopEntryProcess(entry) abort |
||||||
|
if a:entry.type ==# 'F' " Fatal error which prevented further processing |
||||||
|
let a:entry.type = 'E' |
||||||
|
elseif a:entry.type ==# 'E' " Error for important programming issues |
||||||
|
let a:entry.type = 'E' |
||||||
|
elseif a:entry.type ==# 'W' " Warning for stylistic or minor programming issues |
||||||
|
let a:entry.type = 'W' |
||||||
|
elseif a:entry.type ==# 'R' " Refactor suggestion |
||||||
|
let a:entry.type = 'W' |
||||||
|
elseif a:entry.type ==# 'C' " Convention violation |
||||||
|
let a:entry.type = 'I' |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#ruby#rubylint() abort |
||||||
|
return { |
||||||
|
\ 'exe': 'ruby-lint', |
||||||
|
\ 'args': ['--presenter', 'syntastic'], |
||||||
|
\ 'errorformat': '%f:%t:%l:%c: %m', |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#ruby#mri() abort |
||||||
|
let errorformat = '%-G%\m%.%#warning: %\%%(possibly %\)%\?useless use of == in void context,' |
||||||
|
let errorformat .= '%-G%\%.%\%.%\%.%.%#,' |
||||||
|
let errorformat .= |
||||||
|
\ '%-GSyntax OK,'. |
||||||
|
\ '%E%f:%l: syntax error\, %m,'. |
||||||
|
\ '%Z%p^,'. |
||||||
|
\ '%W%f:%l: warning: %m,'. |
||||||
|
\ '%Z%p^,'. |
||||||
|
\ '%W%f:%l: %m,'. |
||||||
|
\ '%-C%.%#' |
||||||
|
|
||||||
|
return { |
||||||
|
\ 'exe': 'ruby', |
||||||
|
\ 'args': ['-c', '-T1', '-w'], |
||||||
|
\ 'errorformat': errorformat, |
||||||
|
\ 'output_stream': 'both', |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#ruby#jruby() abort |
||||||
|
let errorformat = |
||||||
|
\ '%-GSyntax OK for %f,'. |
||||||
|
\ '%ESyntaxError in %f:%l: syntax error\, %m,'. |
||||||
|
\ '%Z%p^,'. |
||||||
|
\ '%W%f:%l: warning: %m,'. |
||||||
|
\ '%Z%p^,'. |
||||||
|
\ '%W%f:%l: %m,'. |
||||||
|
\ '%-C%.%#' |
||||||
|
|
||||||
|
return { |
||||||
|
\ 'exe': 'jruby', |
||||||
|
\ 'args': ['-c', '-T1', '-w'], |
||||||
|
\ 'errorformat': errorformat |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#ruby#reek() abort |
||||||
|
return { |
||||||
|
\ 'args': ['--format', 'text', '--single-line'], |
||||||
|
\ 'errorformat': '%W%f:%l: %m', |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#ruby#flog() abort |
||||||
|
return { |
||||||
|
\ 'errorformat': |
||||||
|
\ '%W%m %f:%l-%c,' . |
||||||
|
\ '%-G\s%#,' . |
||||||
|
\ '%-G%.%#: flog total,' . |
||||||
|
\ '%-G%.%#: flog/method average,' |
||||||
|
\ } |
||||||
|
endfunction |
@ -0,0 +1,238 @@ |
|||||||
|
function! neomake#makers#ft#rust#EnabledMakers() abort |
||||||
|
return ['cargo'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#rust#rustc() abort |
||||||
|
return { |
||||||
|
\ 'errorformat': |
||||||
|
\ '%-Gerror: aborting due to previous error,'. |
||||||
|
\ '%-Gerror: aborting due to %\\d%\\+ previous errors,'. |
||||||
|
\ '%-Gerror: Could not compile `%s`.,'. |
||||||
|
\ '%Eerror[E%n]: %m,'. |
||||||
|
\ '%Eerror: %m,'. |
||||||
|
\ '%Wwarning: %m,'. |
||||||
|
\ '%Inote: %m,'. |
||||||
|
\ '%-Z\ %#-->\ %f:%l:%c,'. |
||||||
|
\ '%G\ %#\= %*[^:]: %m,'. |
||||||
|
\ '%G\ %#|\ %#%\\^%\\+ %m,'. |
||||||
|
\ '%I%>help:\ %#%m,'. |
||||||
|
\ '%Z\ %#%m,'. |
||||||
|
\ '%-G%.%#', |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:get_cargo_workspace_root() abort |
||||||
|
if !exists('b:_neomake_cargo_workspace') |
||||||
|
let cmd = 'cargo metadata --no-deps --format-version 1' |
||||||
|
let [cd_error, cd_back_cmd] = neomake#utils#temp_cd(expand('%:h')) |
||||||
|
if !empty(cd_error) |
||||||
|
call neomake#log#debug(printf( |
||||||
|
\ 's:get_cargo_workspace_root: failed to cd to buffer directory: %s.', |
||||||
|
\ cd_error)) |
||||||
|
endif |
||||||
|
let output = system(cmd) |
||||||
|
if !empty(cd_back_cmd) |
||||||
|
exe cd_back_cmd |
||||||
|
endif |
||||||
|
if v:shell_error |
||||||
|
call neomake#log#debug(printf( |
||||||
|
\ 'Failed to get cargo metadata for workspace using %s.', |
||||||
|
\ string(cmd))) |
||||||
|
let b:_neomake_cargo_workspace = '' |
||||||
|
else |
||||||
|
let json = neomake#compat#json_decode(output) |
||||||
|
let b:_neomake_cargo_workspace = json['workspace_root'] |
||||||
|
endif |
||||||
|
endif |
||||||
|
return b:_neomake_cargo_workspace |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:get_cargo_maker_cwd(default) abort |
||||||
|
let cargo_workspace_root = s:get_cargo_workspace_root() |
||||||
|
if !empty(cargo_workspace_root) |
||||||
|
return cargo_workspace_root |
||||||
|
endif |
||||||
|
|
||||||
|
let cargo_toml = neomake#utils#FindGlobFile('Cargo.toml') |
||||||
|
if !empty(cargo_toml) |
||||||
|
return fnamemodify(cargo_toml, ':h') |
||||||
|
endif |
||||||
|
|
||||||
|
return a:default |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#rust#cargotest() abort |
||||||
|
" NOTE: duplicates are removed due to https://github.com/rust-lang/cargo/issues/5128. |
||||||
|
let maker = { |
||||||
|
\ 'exe': 'cargo', |
||||||
|
\ 'args': ['test', '%:t:r', '--quiet'], |
||||||
|
\ 'append_file': 0, |
||||||
|
\ 'uses_filename': 0, |
||||||
|
\ 'postprocess': copy(g:neomake#postprocess#remove_duplicates), |
||||||
|
\ 'errorformat': |
||||||
|
\ '%-G,' . |
||||||
|
\ '%-Gtest %s,' . |
||||||
|
\ '%-Grunning %\\d%# test%s,' . |
||||||
|
\ '%-Gfailures:%s,' . |
||||||
|
\ '%-G----%s,' . |
||||||
|
\ '%-G%.%#--verbose%s,' . |
||||||
|
\ '%-G%.%#--explain%s,' . |
||||||
|
\ '%-Gerror: aborting due to previous error,' . |
||||||
|
\ '%-G%\ %#error: aborting due to %\\d%#%\ %#previous errors,' . |
||||||
|
\ '%E%\ %#error[E%n]:\ %m,' . |
||||||
|
\ '%E%\ %#error:\ %m,' . |
||||||
|
\ '%I%\ %#note:\ %m,'. |
||||||
|
\ '%W%\ %#warning:\ %m,' . |
||||||
|
\ '%-Z%\ %#-->\ %f:%l:%c,' . |
||||||
|
\ '%-G%\\d%# %#|\ %s,' . |
||||||
|
\ '%-G%\\d%# %#|,' . |
||||||
|
\ '%-G\ %#\= %*[^:]:\ %m,'. |
||||||
|
\ '%E%\ %#%m,' . |
||||||
|
\ '%G%\ %#%s%\\,,' . |
||||||
|
\ '%Z%\ %#%s%\\,%\\s%f:%l:%c' |
||||||
|
\ } |
||||||
|
|
||||||
|
function! maker.InitForJob(_jobinfo) abort |
||||||
|
if !has_key(self, 'cwd') |
||||||
|
let self.cwd = s:get_cargo_maker_cwd('%:p:h') |
||||||
|
return self |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
return maker |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#rust#cargo() abort |
||||||
|
let maker_command = get(b:, 'neomake_rust_cargo_command', |
||||||
|
\ get(g:, 'neomake_rust_cargo_command', ['check'])) |
||||||
|
let maker = { |
||||||
|
\ 'args': maker_command + ['--message-format=json', '--quiet'], |
||||||
|
\ 'append_file': 0, |
||||||
|
\ 'tempfile_enabled': 0, |
||||||
|
\ 'process_output': function('neomake#makers#ft#rust#CargoProcessOutput'), |
||||||
|
\ } |
||||||
|
|
||||||
|
function! maker.InitForJob(_jobinfo) abort |
||||||
|
if !has_key(self, 'cwd') |
||||||
|
let self.cwd = s:get_cargo_maker_cwd('%:p:h') |
||||||
|
return self |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
return maker |
||||||
|
endfunction |
||||||
|
|
||||||
|
" NOTE: does not use process_json, since cargo outputs multiple JSON root |
||||||
|
" elements per line. |
||||||
|
function! neomake#makers#ft#rust#CargoProcessOutput(context) abort |
||||||
|
let errors = [] |
||||||
|
for line in a:context['output'] |
||||||
|
if line[0] !=# '{' |
||||||
|
continue |
||||||
|
endif |
||||||
|
|
||||||
|
let decoded = neomake#compat#json_decode(line) |
||||||
|
let data = get(decoded, 'message', -1) |
||||||
|
if type(data) != type({}) || empty(get(data, 'spans', [])) |
||||||
|
" call neomake#log#debug(printf('cargo: ignoring input: %s.', line)) |
||||||
|
continue |
||||||
|
endif |
||||||
|
|
||||||
|
let error = {'maker_name': 'cargo'} |
||||||
|
|
||||||
|
let code_dict = get(data, 'code', -1) |
||||||
|
if code_dict is g:neomake#compat#json_null |
||||||
|
\ || index(['E', 'W'], code_dict['code'][0]) == -1 |
||||||
|
let level = get(data, 'level', -1) |
||||||
|
if level != -1 |
||||||
|
let error.type = toupper(level[0]) |
||||||
|
else |
||||||
|
let error.type = 'W' |
||||||
|
endif |
||||||
|
else |
||||||
|
let error.type = code_dict['code'][0] |
||||||
|
let error.nr = str2nr(code_dict['code'][1:]) |
||||||
|
endif |
||||||
|
|
||||||
|
let span = data.spans[0] |
||||||
|
for candidate_span in data.spans |
||||||
|
if candidate_span.is_primary |
||||||
|
let span = candidate_span |
||||||
|
break |
||||||
|
endif |
||||||
|
endfor |
||||||
|
|
||||||
|
let expanded = 0 |
||||||
|
let has_expansion = type(span.expansion) == type({}) |
||||||
|
\ && type(span.expansion.span) == type({}) |
||||||
|
\ && type(span.expansion.def_site_span) == type({}) |
||||||
|
|
||||||
|
if span.file_name =~# '^<.*>$' && has_expansion |
||||||
|
let expanded = 1 |
||||||
|
call neomake#makers#ft#rust#FillErrorFromSpan(error, |
||||||
|
\ span.expansion.span) |
||||||
|
else |
||||||
|
call neomake#makers#ft#rust#FillErrorFromSpan(error, span) |
||||||
|
endif |
||||||
|
|
||||||
|
let error.text = data.message |
||||||
|
let detail = span.label |
||||||
|
let children = data.children |
||||||
|
if type(detail) == type('') && !empty(detail) |
||||||
|
let error.text = error.text . ': ' . detail |
||||||
|
elseif !empty(children) && has_key(children[0], 'message') |
||||||
|
let error.text = error.text . '. ' . children[0].message |
||||||
|
endif |
||||||
|
|
||||||
|
call add(errors, error) |
||||||
|
|
||||||
|
if has_expansion && !expanded |
||||||
|
let error = copy(error) |
||||||
|
call neomake#makers#ft#rust#FillErrorFromSpan(error, |
||||||
|
\ span.expansion.span) |
||||||
|
call add(errors, error) |
||||||
|
endif |
||||||
|
|
||||||
|
for child in children[1:] |
||||||
|
if !has_key(child, 'message') |
||||||
|
continue |
||||||
|
endif |
||||||
|
|
||||||
|
let info = deepcopy(error) |
||||||
|
let info.type = 'I' |
||||||
|
let info.text = child.message |
||||||
|
call neomake#postprocess#compress_whitespace(info) |
||||||
|
if has_key(child, 'rendered') |
||||||
|
\ && !(child.rendered is g:neomake#compat#json_null) |
||||||
|
let info.text = info.text . ': ' . child.rendered |
||||||
|
endif |
||||||
|
|
||||||
|
if len(child.spans) |
||||||
|
let span = child.spans[0] |
||||||
|
if span.file_name =~# '^<.*>$' |
||||||
|
\ && type(span.expansion) == type({}) |
||||||
|
\ && type(span.expansion.span) == type({}) |
||||||
|
\ && type(span.expansion.def_site_span) == type({}) |
||||||
|
call neomake#makers#ft#rust#FillErrorFromSpan(info, |
||||||
|
\ span.expansion.span) |
||||||
|
else |
||||||
|
call neomake#makers#ft#rust#FillErrorFromSpan(info, span) |
||||||
|
endif |
||||||
|
let detail = span.label |
||||||
|
if type(detail) == type('') && len(detail) |
||||||
|
let info.text = info.text . ': ' . detail |
||||||
|
endif |
||||||
|
endif |
||||||
|
|
||||||
|
call add(errors, info) |
||||||
|
endfor |
||||||
|
endfor |
||||||
|
return errors |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#rust#FillErrorFromSpan(error, span) abort |
||||||
|
let a:error.filename = a:span.file_name |
||||||
|
let a:error.col = a:span.column_start |
||||||
|
let a:error.lnum = a:span.line_start |
||||||
|
let a:error.length = a:span.byte_end - a:span.byte_start |
||||||
|
endfunction |
||||||
|
|
||||||
|
" vim: ts=4 sw=4 et |
@ -0,0 +1,40 @@ |
|||||||
|
" vim: ts=4 sw=4 et |
||||||
|
function! neomake#makers#ft#scala#EnabledMakers() abort |
||||||
|
" use let g:neomake_scala_enabled_makers = ['fsc','scalastyle'] for fsc |
||||||
|
let makers = ['scalac', 'scalastyle'] |
||||||
|
return makers |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#scala#fsc() abort |
||||||
|
return { |
||||||
|
\ 'args': [ |
||||||
|
\ '-Ystop-after:parser' |
||||||
|
\ ], |
||||||
|
\ 'errorformat': |
||||||
|
\ '%E%f:%l: %trror: %m,' . |
||||||
|
\ '%Z%p^,' . |
||||||
|
\ '%-G%.%#' |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#scala#scalac() abort |
||||||
|
return { |
||||||
|
\ 'args': [ |
||||||
|
\ '-Ystop-after:parser' |
||||||
|
\ ], |
||||||
|
\ 'errorformat': |
||||||
|
\ '%E%f:%l: %trror: %m,' . |
||||||
|
\ '%Z%p^,' . |
||||||
|
\ '%-G%.%#' |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#scala#scalastyle() abort |
||||||
|
return { |
||||||
|
\ 'errorformat': |
||||||
|
\ '%trror file=%f message=%m line=%l column=%c,' . |
||||||
|
\ '%trror file=%f message=%m line=%l,' . |
||||||
|
\ '%tarning file=%f message=%m line=%l column=%c,' . |
||||||
|
\ '%tarning file=%f message=%m line=%l' |
||||||
|
\ } |
||||||
|
endfunction |
@ -0,0 +1,25 @@ |
|||||||
|
" vim: ts=4 sw=4 et |
||||||
|
|
||||||
|
function! neomake#makers#ft#scss#EnabledMakers() abort |
||||||
|
return executable('stylelint') ? ['stylelint'] : executable('sass-lint') ? ['sasslint'] : ['scsslint'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#scss#sasslint() abort |
||||||
|
return { |
||||||
|
\ 'exe': 'sass-lint', |
||||||
|
\ 'args': ['--no-exit', '--verbose', '--format', 'compact'], |
||||||
|
\ 'errorformat': neomake#makers#ft#javascript#eslint()['errorformat'] |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#scss#scsslint() abort |
||||||
|
return { |
||||||
|
\ 'exe': 'scss-lint', |
||||||
|
\ 'errorformat': '%A%f:%l:%v [%t] %m,' . |
||||||
|
\ '%A%f:%l [%t] %m' |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#scss#stylelint() abort |
||||||
|
return neomake#makers#ft#css#stylelint() |
||||||
|
endfunction |
@ -0,0 +1,13 @@ |
|||||||
|
function! neomake#makers#ft#serpent#EnabledMakers() abort |
||||||
|
return ['serplint'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#serpent#serplint() abort |
||||||
|
return { |
||||||
|
\ 'exe': 'serplint', |
||||||
|
\ 'args': [], |
||||||
|
\ 'errorformat': |
||||||
|
\ '%f:%l:%c %t%n %m', |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
" vim: ts=4 sw=4 et |
@ -0,0 +1,86 @@ |
|||||||
|
" vim: ts=4 sw=4 et |
||||||
|
|
||||||
|
function! neomake#makers#ft#sh#EnabledMakers() abort |
||||||
|
return ['sh', 'shellcheck'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
let s:shellcheck = { |
||||||
|
\ 'args': ['-fgcc', '-x'], |
||||||
|
\ 'errorformat': |
||||||
|
\ '%f:%l:%c: %trror: %m [SC%n],' . |
||||||
|
\ '%f:%l:%c: %tarning: %m [SC%n],' . |
||||||
|
\ '%I%f:%l:%c: Note: %m [SC%n]', |
||||||
|
\ 'output_stream': 'stdout', |
||||||
|
\ 'short_name': 'SC', |
||||||
|
\ 'cwd': '%:h', |
||||||
|
\ } |
||||||
|
|
||||||
|
function! neomake#makers#ft#sh#shellcheck() abort |
||||||
|
let maker = deepcopy(s:shellcheck) |
||||||
|
|
||||||
|
let line1 = getline(1) |
||||||
|
if match(line1, '\v^#!.*<%(sh|dash|bash|ksh)') < 0 |
||||||
|
\ && match(line1, '\v^#\s*shellcheck\s+shell\=') < 0 |
||||||
|
" shellcheck does not read the shebang by itself. |
||||||
|
let ext = expand('%:e') |
||||||
|
if ext ==# 'ksh' |
||||||
|
let maker.args += ['-s', 'ksh'] |
||||||
|
elseif ext ==# 'sh' |
||||||
|
if exists('g:is_sh') |
||||||
|
let maker.args += ['-s', 'sh'] |
||||||
|
elseif exists('g:is_posix') || exists('g:is_kornshell') |
||||||
|
let maker.args += ['-s', 'ksh'] |
||||||
|
else |
||||||
|
let maker.args += ['-s', 'bash'] |
||||||
|
endif |
||||||
|
else |
||||||
|
let maker.args += ['-s', 'bash'] |
||||||
|
endif |
||||||
|
endif |
||||||
|
return maker |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#sh#checkbashisms() abort |
||||||
|
return { |
||||||
|
\ 'args': ['-fx'], |
||||||
|
\ 'errorformat': |
||||||
|
\ '%-Gscript %f is already a bash script; skipping,' . |
||||||
|
\ '%Eerror: %f: %m\, opened in line %l,' . |
||||||
|
\ '%Eerror: %f: %m,' . |
||||||
|
\ '%Ecannot open script %f for reading: %m,' . |
||||||
|
\ '%Wscript %f %m,%C%.# lines,' . |
||||||
|
\ '%Wpossible bashism in %f line %l (%m):,%C%.%#,%Z.%#,' . |
||||||
|
\ '%-G%.%#', |
||||||
|
\ 'output_stream': 'stderr', |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#sh#sh() abort |
||||||
|
let shebang = matchstr(getline(1), '^#!\s*\zs.*$') |
||||||
|
if !empty(shebang) |
||||||
|
let l = split(shebang) |
||||||
|
let exe = l[0] |
||||||
|
let args = l[1:] + ['-n'] |
||||||
|
else |
||||||
|
let exe = '/usr/bin/env' |
||||||
|
let args = ['sh', '-n'] |
||||||
|
endif |
||||||
|
|
||||||
|
" NOTE: the format without "line" is used by dash. |
||||||
|
return { |
||||||
|
\ 'exe': exe, |
||||||
|
\ 'args': args, |
||||||
|
\ 'errorformat': |
||||||
|
\ '%E%f: line %l: %m,' . |
||||||
|
\ '%E%f: %l: %m', |
||||||
|
\ 'output_stream': 'stderr', |
||||||
|
\} |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#sh#dash() abort |
||||||
|
return { |
||||||
|
\ 'args': ['-n'], |
||||||
|
\ 'errorformat': '%E%f: %l: %m', |
||||||
|
\ 'output_stream': 'stderr', |
||||||
|
\} |
||||||
|
endfunction |
@ -0,0 +1,13 @@ |
|||||||
|
" vim: ts=4 sw=4 et |
||||||
|
|
||||||
|
function! neomake#makers#ft#slim#EnabledMakers() abort |
||||||
|
return ['slimlint'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#slim#slimlint() abort |
||||||
|
return { |
||||||
|
\ 'exe': 'slim-lint', |
||||||
|
\ 'args': ['--no-color'], |
||||||
|
\ 'errorformat': '%f:%l [%t] %m' |
||||||
|
\ } |
||||||
|
endfunction |
@ -0,0 +1,19 @@ |
|||||||
|
" vim: ts=4 sw=4 et |
||||||
|
|
||||||
|
function! neomake#makers#ft#sml#EnabledMakers() abort |
||||||
|
return ['smlnj'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
" This comes straight out of syntastic. |
||||||
|
function! neomake#makers#ft#sml#smlnj() abort |
||||||
|
return { |
||||||
|
\ 'exe': 'sml', |
||||||
|
\ 'errorformat': |
||||||
|
\ '%E%f:%l%\%.%c %trror: %m,' . |
||||||
|
\ '%E%f:%l%\%.%c-%\d%\+%\%.%\d%\+ %trror: %m,' . |
||||||
|
\ '%W%f:%l%\%.%c %tarning: %m,' . |
||||||
|
\ '%W%f:%l%\%.%c-%\d%\+%\%.%\d%\+ %tarning: %m,' . |
||||||
|
\ '%C%\s%\+%m,' . |
||||||
|
\ '%-G%.%#' |
||||||
|
\ } |
||||||
|
endfunction |
@ -0,0 +1,16 @@ |
|||||||
|
function! neomake#makers#ft#solidity#EnabledMakers() abort |
||||||
|
return ['solium', 'solhint'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#solidity#solium() abort |
||||||
|
return { |
||||||
|
\ 'args': ['--reporter', 'gcc', '--file'], |
||||||
|
\ 'errorformat': |
||||||
|
\ '%f:%l:%c: %t%s: %m', |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#solidity#solhint() abort |
||||||
|
return neomake#makers#ft#javascript#eslint() |
||||||
|
endfunction |
||||||
|
" vim: ts=4 sw=4 et |
@ -0,0 +1,13 @@ |
|||||||
|
function! neomake#makers#ft#spar#EnabledMakers() abort |
||||||
|
return ['spar'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#spar#spar() abort |
||||||
|
return { |
||||||
|
\ 'args': ['-g', '-c'], |
||||||
|
\ 'errorformat': |
||||||
|
\ '%f:%l:%c: %m', |
||||||
|
\ 'nvim_job_opts': {'pty': 1} |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
" vim: ts=4 sw=4 et |
@ -0,0 +1,16 @@ |
|||||||
|
function! neomake#makers#ft#spec#EnabledMakers() abort |
||||||
|
return ['rpmlint'] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! neomake#makers#ft#spec#rpmlint() abort |
||||||
|
return { |
||||||
|
\ 'errorformat': |
||||||
|
\ '%E%f:%l: E: %m,' . |
||||||
|
\ '%E%f: E: %m,' . |
||||||
|
\ '%W%f:%l: W: %m,' . |
||||||
|
\ '%W%f: W: %m,' . |
||||||
|
\ '%-G%.%#' |
||||||
|
\ } |
||||||
|
endfunction |
||||||
|
|
||||||
|
" vim: ts=4 sw=4 et |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue