phpstan filename mappings not respected when running via docker
Information
VIM version
NVIM v0.9.0-dev-377+gc9adbcafa
Build type: RelWithDebInfo
Operating System: Ubuntu 20.04.5 LTS
What went wrong
I have configured ale to run phpstan via my docker container with the following vim config:
let b:ale_php_phpstan_executable = '/home/adam/code/docker-phpstan.sh'
let b:ale_php_phpstan_use_global = 1
let b:ale_filename_mappings = {
\ 'phpstan': [
\ ['/home/adam/code/my-project', '/var/www'],
\ ],
\}
and this shell script:
#!/usr/bin/zsh
exec docker exec -i my_container vendor/bin/phpstan "$@"
When I put a simple error in a file, the ALEInfo output (see below) shows that phpstan is running and the error is being detected. However, when ale tries to read the output I get this error:
Error detected while processing function <SNR>216_NeoVimCallback[35]..function <SNR>216_NeoVimCallback[29]..
53[1]..<SNR>213_ExitCallback[28]..<SNR>143_HandleExit[24]..ale_linters#php#phpstan#Handle:
line 8:
E716: Key not present in Dictionary: "/home/adam/code/my-project/modules/SomeModule/Jobs/SomeJob.php"
The issue seems to be that the phpstan output has the file keyed at /var/www:
{"totals":{"errors":0,"file_errors":1},"files":{"/var/www/modules/SomeModule/Jobs/SomeJob.php":{"errors":1,"messages":[{"message":"If condition is always false.","line":47,"ignorable":true}]}},"errors":[]}
but the ale linter is expecting it to be at home/adam/code/my-project. I'm guessing somewhere inside https://github.com/dense-analysis/ale/blob/master/ale_linters/php/phpstan.vim#L54 needs to account for the filename mappings and it currently isn't, but my VimL knowledge is basic at best.
Reproducing the bug
- You'll need a PHP project running inside a docker container, with phpstan installed
- Set the vim configs as I have laid out above
- Cause an error in a file, and you should see the same error and ALEInfo output
:ALEInfo
Expand
Current Filetype: php Available Linters: ['cspell', 'intelephense', 'langserver', 'phan', 'php', 'phpactor', 'phpcs', 'phpmd', 'phpstan', 'psalm', 'tlint'] Enabled Linters: ['cspell', 'intelephense', 'langserver', 'phan', 'php', 'phpactor', 'phpcs', 'phpmd', 'phpstan', 'psalm', 'tlint'] Ignored Linters: ['intelephense', 'langserver', 'phpactor', 'psalm'] Suggested Fixers: 'php_cs_fixer' - Fix PHP files with php-cs-fixer. 'phpcbf' - Fix PHP files with phpcbf. 'pint' - Fix PHP files with Laravel Pint. 'remove_trailing_lines' - Remove all blank lines at the end of a file. 'trim_whitespace' - Remove all trailing whitespace characters at the end of every line. Linter Variables:
let g:ale_php_intelephense_config = {} let g:ale_php_intelephense_executable = 'intelephense' let g:ale_php_intelephense_use_global = 1 let g:ale_php_langserver_executable = 'php-language-server.php' let g:ale_php_langserver_use_global = 0 let g:ale_php_phan_executable = 'phan' let g:ale_php_phan_minimum_severity = 0 let g:ale_php_phan_use_client = 0 let g:ale_php_php_executable = 'php' let g:ale_php_phpcs_executable = 'phpcs' let g:ale_php_phpcs_options = '' let g:ale_php_phpcs_standard = 'PSR12' let g:ale_php_phpcs_use_global = 0 let g:ale_php_phpmd_executable = 'phpmd' let g:ale_php_phpmd_ruleset = 'cleancode,codesize,controversial,design,naming,unusedcode' let g:ale_php_phpstan_autoload = '' let g:ale_php_phpstan_configuration = '' let g:ale_php_phpstan_executable = 'phpstan' let b:ale_php_phpstan_executable = '/home/adam/code/docker-phpstan.sh' let g:ale_php_phpstan_level = 5 let g:ale_php_phpstan_memory_limit = '' let g:ale_php_phpstan_use_global = 0 let b:ale_php_phpstan_use_global = 1 let g:ale_php_psalm_executable = 'psalm' let g:ale_php_psalm_options = '' let g:ale_php_psalm_use_global = 0 let g:ale_php_tlint_executable = 'tlint' let g:ale_php_tlint_options = '' let g:ale_php_tlint_use_global = 0 Global Variables:
let g:ale_cache_executable_check_failures = v:null let g:ale_change_sign_column_color = 0 let g:ale_command_wrapper = '' let g:ale_completion_delay = v:null let g:ale_completion_enabled = 0 let g:ale_completion_max_suggestions = v:null let g:ale_disable_lsp = 1 let g:ale_echo_cursor = 1 let g:ale_echo_msg_error_str = 'Error' let g:ale_echo_msg_format = '[%linter%] %s' let g:ale_echo_msg_info_str = 'Info' let g:ale_echo_msg_warning_str = 'Warning' let g:ale_enabled = 1 let g:ale_fix_on_save = 0 let g:ale_fixers = {} let g:ale_history_enabled = 1 let g:ale_history_log_output = 1 let g:ale_keep_list_window_open = 0 let g:ale_lint_delay = 1000 let g:ale_lint_on_enter = 1 let g:ale_lint_on_filetype_changed = 1 let g:ale_lint_on_insert_leave = 1 let g:ale_lint_on_save = 1 let g:ale_lint_on_text_changed = 'normal' let g:ale_linter_aliases = {} let g:ale_linters = {} let g:ale_linters_explicit = 0 let g:ale_linters_ignore = {} let g:ale_list_vertical = 0 let g:ale_list_window_size = 10 let g:ale_loclist_msg_format = '[%linter%] %s' let g:ale_max_buffer_history_size = 20 let g:ale_max_signs = -1 let g:ale_maximum_file_size = v:null let g:ale_open_list = 0 let g:ale_pattern_options = v:null let g:ale_pattern_options_enabled = v:null let g:ale_root = {} let g:ale_set_balloons = 0 let g:ale_set_highlights = 1 let g:ale_set_loclist = 1 let g:ale_set_quickfix = 0 let g:ale_set_signs = 1 let g:ale_sign_column_always = 0 let g:ale_sign_error = '🙅' let g:ale_sign_info = '🤨' let g:ale_sign_offset = 1000000 let g:ale_sign_style_error = '🙅' let g:ale_sign_style_warning = '🤨' let g:ale_sign_warning = '🤨' let g:ale_sign_highlight_linenrs = 0 let g:ale_statusline_format = v:null let g:ale_type_map = {} let g:ale_use_global_executables = v:null let g:ale_virtualtext_cursor = 0 let g:ale_warn_about_trailing_blank_lines = 1 let g:ale_warn_about_trailing_whitespace = 1 Command History:
(finished - exit code 2) ['/usr/bin/zsh', '-c', 'cd ''/home/adam/code/my-project/modules/SomeModule/Jobs'' && ''/home/adam/code/my-project/vendor/bin/phpcs'' -s --report=emacs --stdin-path=''/home/adam/code/my-project/modules/SomeModule/Jobs/SomeJob.php'' --standard=''PSR12'' < ''/tmp/nvim.adam/WGND6e/9/SomeJob.php''']
<<<OUTPUT STARTS>>> /home/adam/code/my-project/modules/SomeModule/Jobs/SomeJob.php:25:5: warning - Visibility must be declared on all constants if your project supports PHP 7.1 or later (PSR12.Properties.ConstantVisibility.NotFound) /home/adam/my-project/modules/SomeModule/Jobs/SomeJob.php:45:14: error - Line indented incorrectly; expected 12 spaces, found 13 (Generic.WhiteSpace.ScopeIndent.IncorrectExact) /home/adam/code/my-project/modules/SomeModule/Jobs/SomeJob.php:45:14: error - Closing brace indented incorrectly; expected 12 spaces, found 13 (Squiz.WhiteSpace.ScopeClosingBrace.Indent) <<<OUTPUT ENDS>>>
(executable check - failure) phpmd (executable check - success) /home/adam/code/my-project-docker-phpstan.sh (finished - exit code 0) ['/usr/bin/zsh', '-c', '''/home/adam/code/my-project-docker-phpstan.sh'' --version']
<<<OUTPUT STARTS>>> PHPStan - PHP Static Analysis Tool 1.9.2 <<<OUTPUT ENDS>>>
(executable check - failure) tlint (started) ['/usr/bin/zsh', '-c', '''/home/adam/code/my-project-docker-phpstan.sh'' analyze --no-progress --error-format json -l ''5'' ''/var/www/modules/SomeModule/Jobs/SomeJob.php'' < ''/tmp/nvim.adam/WGND6e/12/SomeJob.php'''] (executable check - failure) cspell (executable check - failure) phan (finished - exit code 0) ['/usr/bin/zsh', '-c', '''php'' -l -d error_reporting=E_ALL -d display_errors=1 -d log_errors=0 -- < ''/tmp/nvim.adam/WGND6e/17/SomeJob.php''']
<<<OUTPUT STARTS>>> No syntax errors detected in Standard input code <<<OUTPUT ENDS>>>
(finished - exit code 2) ['/usr/bin/zsh', '-c', 'cd ''/home/adam/code/my-project/modules/SomeModule/Jobs'' && ''/home/adam/code/my-project/vendor/bin/phpcs'' -s --report=emacs --stdin-path=''/home/adam/code/my-project/modules/SomeModule/Jobs/SomeJob.php'' --standard=''PSR12'' < ''/tmp/nvim.adam/WGND6e/18/SomeJob.php''']
<<<OUTPUT STARTS>>> /home/adam/code/my-project/modules/SomeModule/Jobs/SomeJob.php:25:5: warning - Visibility must be declared on all constants if your project supports PHP 7.1 or later (PSR12.Properties.ConstantVisibility.NotFound) /home/adam/code/my-project/modules/SomeModule/Jobs/SomeJob.php:45:14: error - Line indented incorrectly; expected 12 spaces, found 13 (Generic.WhiteSpace.ScopeIndent.IncorrectExact) /home/adam/code/my-project/modules/SomeModule/Jobs/SomeJob.php:45:14: error - Closing brace indented incorrectly; expected 12 spaces, found 13 (Squiz.WhiteSpace.ScopeClosingBrace.Indent) <<<OUTPUT ENDS>>>
(executable check - failure) phpmd (started) ['/usr/bin/zsh', '-c', '''/home/adam/code/my-project-docker-phpstan.sh'' analyze --no-progress --error-format json -l ''5'' ''/var/www/modules/SomeModule/Jobs/SomeJob.php'' < ''/tmp/nvim.adam/WGND6e/19/SomeJob.php'''] (executable check - failure) tlint (executable check - failure) cspell (executable check - failure) phan (finished - exit code 0) ['/usr/bin/zsh', '-c', '''php'' -l -d error_reporting=E_ALL -d display_errors=1 -d log_errors=0 -- < ''/tmp/nvim.adam/WGND6e/20/SomeJob.php''']
<<<OUTPUT STARTS>>> No syntax errors detected in Standard input code <<<OUTPUT ENDS>>>
(finished - exit code 2) ['/usr/bin/zsh', '-c', 'cd ''/home/adam/code/my-project/modules/SomeModule/Jobs'' && ''/home/adam/code/my-project/vendor/bin/phpcs'' -s --report=emacs --stdin-path=''/home/adam/code/my-project/modules/SomeModule/Jobs/SomeJob.php'' --standard=''PSR12'' < ''/tmp/nvim.adam/WGND6e/21/SomeJob.php''']
<<<OUTPUT STARTS>>> /home/adam/code/my-project/modules/SomeModule/Jobs/SomeJob.php:25:5: warning - Visibility must be declared on all constants if your project supports PHP 7.1 or later (PSR12.Properties.ConstantVisibility.NotFound) /home/adam/code/my-project/modules/SomeModule/Jobs/SomeJob.php:45:14: error - Line indented incorrectly; expected 12 spaces, found 13 (Generic.WhiteSpace.ScopeIndent.IncorrectExact) /home/adam/code/my-project/modules/SomeModule/Jobs/SomeJob.php:45:14: error - Closing brace indented incorrectly; expected 12 spaces, found 13 (Squiz.WhiteSpace.ScopeClosingBrace.Indent) <<<OUTPUT ENDS>>>
(executable check - failure) phpmd (finished - exit code 1) ['/usr/bin/zsh', '-c', '''/home/adam/code/my-project-docker-phpstan.sh'' analyze --no-progress --error-format json -l ''5'' ''/var/www/modules/SomeModule/Jobs/SomeJob.php'' < ''/tmp/nvim.adam/WGND6e/22/SomeJob.php''']
<<<OUTPUT STARTS>>> {"totals":{"errors":0,"file_errors":1},"files":{"/var/www/modules/SomeModule/Jobs/SomeJob.php":{"errors":1,"messages":[{"message":"If condition is always false.","line":47,"ignorable":true}]}},"errors":[]} <<<OUTPUT ENDS>>>
(executable check - failure) tlint
For a week the PHPStan linter did not work and i could not find my error. The error was the same as reported in the OP.
I am just starting to use vim, so vim script is also new to me. After a lot of reading the issues and commits about file mapping, i understood that the problem was not my error, but that the file mapping had not been implemented yet in phpstan.vim
Today i used the commits, to find out what changed have been made for file mapping and search for pieces that i could use.
The result it that i now have a working PHPStan linter. What did i do? In phpstan.vim line 60 i replaced
for l:err in l:res.files[expand('#' . a:buffer .':p')].messages
with
let l:file_mappings = ale#GetFilenameMappings(a:buffer, 'phpstan')
for l:err in l:res.files[
\ ale_linters#php#phpstan#Mapping(a:buffer, l:file_mappings)
\].messages
The first line loads the mapping. The second line calls the new function (see below) that applies the mapping the current expand buffer.
function! ale_linters#php#phpstan#Mapping(buffer, file_mappings) abort
if empty(a:file_mappings)
let l:result = expand('#' . a:buffer .':p')
else
let l:result = ale#filename_mapping#Map(
\ expand('#' . a:buffer .':p'),
\ a:file_mappings
\)
endif
return l:result
endfunction
To create a pull request i need to write a test, but that is a bridge to far. Also i do not know the code style rules.
On request a can create a pull request for the above
Regards Edwin