ale
ale copied to clipboard
phpcbf empties my file on save
Hi,
I'm having a weird phenomenon when saving a specific file
Ale version : abcefe7a
Information
VIM version
VIM - Vi IMproved 8.1 (2018 May 18, compiled Mar 27 2019 09:51:18) Included patches: 1-1057
Operating System: Linux Mint 18.2 Sonya
What went wrong
Like in #1408, the phpcbf output replaces my whole file.
Other php file in the same project aren't affected
The content of the file is the following and is called SettingsReader.php :
<?php
namespace Drupal\factory_management\Service;
class SettingsReader {
/**
* @param string $siteId
* @return string
*/
public function password($siteId) {
$config = $this->database($siteId);
return $config['password'];
}
/**
* @param string $siteId
* @return array
*/
public function database($siteId) {
$app_root = DRUPAL_ROOT;
$site_path = 'sites' . DIRECTORY_SEPARATOR . $siteId;
if (!file_exists($site_path . '/settings.php')) {
throw new \RuntimeException("No settings file found in « {$site_path} . '/settings.php' »");
}
require DRUPAL_ROOT . DIRECTORY_SEPARATOR . 'sites' . DIRECTORY_SEPARATOR . $siteId . '/settings.php';
if (empty($databases['default']['default'])) {
throw new \RuntimeException("No \$databases[default][default] configuration found in « $site_path » ");
}
return $databases['default']['default'];
}
}
Reproducing the bug
- Open the file
- Save it
The result is this :
No fixable errors were found
Time: 44ms; Memory: 6MB
:ALEInfo
Current Filetype: php
Available Linters: ['langserver', 'phan', 'php', 'phpcs', 'phpmd', 'phpstan', 'psalm']
Enabled Linters: ['phpcs', 'phpstan']
Suggested Fixers:
'php_cs_fixer' - Fix PHP files with php-cs-fixer.
'phpcbf' - Fix PHP files with phpcbf.
'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_phpcs_executable = 'phpcs'
let g:ale_php_phpcs_options = ''
let g:ale_php_phpcs_standard = ''
let g:ale_php_phpcs_use_global = 0
let g:ale_php_phpstan_configuration = 'phpstan.neon'
let g:ale_php_phpstan_executable = 'vendor/bin/phpstan'
let g:ale_php_phpstan_level = 7
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 = 100
let g:ale_completion_enabled = 1
let g:ale_completion_max_suggestions = 50
let g:ale_echo_cursor = 1
let g:ale_echo_msg_error_str = 'Error'
let g:ale_echo_msg_format = '%code: %%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 = 1
let g:ale_fixers = {'php': ['phpcbf']}
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 = 200
let g:ale_lint_on_enter = 1
let g:ale_lint_on_filetype_changed = 1
let g:ale_lint_on_insert_leave = 0
let g:ale_lint_on_save = 1
let g:ale_lint_on_text_changed = 'always'
let g:ale_linter_aliases = {}
let g:ale_linters = {'php': ['phpcs', 'phpstan']}
let g:ale_linters_explicit = 0
let g:ale_list_vertical = 0
let g:ale_list_window_size = 10
let g:ale_loclist_msg_format = '%code: %%s'
let g:ale_lsp_root = {}
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_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 = 1
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_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:
The fixer will be returning the text you're seeing. Someone will need to edit the fixer so it doesn't replace the buffer with that content.
The same text is returned for many other files when I execute the fixer in the console. But this file is the only file that gets emptied
I fix that with this script. Save to ~/.support/php-cbf-helper.sh for instance:
#!/bin/bash
# https://stackoverflow.com/questions/31224368/how-do-i-escape-a-series-of-backslashes-in-a-bash-printf
# printf avoids legit backslashes turning into escape chars :/
out=$(printf "%s" "$(phpcbf -q $@)")
# if there are no errors, don't show me any text! Used by vim-ale. If this
# isn't used, when the "No fixable errors found" output shows up, vim will
# replace the contents of the file with that output!
if [[ "$( echo \"$out\" | grep 'No fixable' )" ]]; then
exit
fi
if [[ "$( echo \"$out\" | grep 'Warning: ' )" ]]; then
exit
fi
# printf avoids legit backslashes turning into escape chars :/
printf "%s" "$out"
and chmod +x ~/.support/php-cbf-helper.sh. Then add this ale config to your ~/.vimrc:
" If I don't do this, phpcbf fails on any file in the exclude-pattern :/
let g:ale_php_phpcbf_executable = $HOME.'/.support/phpcbf-helper.sh'
" in order to get the alternate executable working you have to declare it as
" use global, even though it's not 'global' :/
let g:ale_php_phpcbf_use_global = 1
Edited to use bash instead of sh
Note: this requires phpcbf to be in your PATH
The same trick can be done in ALE's codebase by using the process_with option for the fixer.
I ran into this today and @mikedfunk's fix worked for me
@mikedfunk 's fix worked for me.
Just started experiencing this. Weird. @mikedfunk 's fix worked here too.
@mikedfunk it didn't work in my machine, this is what I found:
Running the script directly didn't work:

After changing /bin/bash in first line it works but can't find executable:

Install phpcbf globally with:
composer global require squizlabs/php_codesniffer
it now works:

I have the same issue and is very annoying. Maybe it is possible to fix it in ALE itself?
it is time for another ping because I got the same error also with that script configured and I am investigating why.
Not so sure if my /bin/sh version was too outdated or what but I had to changed it for /usr/bin/zsh or /usr/bin/bash in order to make @mikedfunk 's fix to work.
So this is what is working for me right now:
#!/usr/bin/bash
# https://stackoverflow.com/questions/31224368/how-do-i-escape-a-series-of-backslashes-in-a-bash-printf
# printf avoids legit backslashes turning into escape chars :/
out=$(printf "%s" "$(phpcbf -q $@)")
# # if there are no errors, don't show me any text! Used by vim-ale. If this
# # isn't used, when the "No fixable errors found" output shows up, vim will
# # replace the contents of the file with that output!
if [[ "$( echo \"$out\" | grep 'No fixable' )" ]]; then
exit
fi
if [[ "$( echo \"$out\" | grep 'Warning: ' )" ]]; then
exit
fi
# printf avoids legit backslashes turning into escape chars :/
printf "%s" "$out"
Thanks!
I am able to reproduce the bug and for me it depends on whether a phpcs.xml.dist exist in the current directory or above.
- Clone the Drupal repo: https://git.drupalcode.org/project/drupal.git
- Edit a
.modulefile likevim core/modules/field/field.module(phpcs won't detect anything because the file has no errors but the Drupal code standars are detected and reported by ale) - Run
:ALEFixand see the buffer replaced - Make some code modification that are fixable like a function brace in its own line and run
:ALEFix - The buffer is replaced and
Not happening for the same file with this steps:
cd core(where the phpcs.xml.dist file lives)vim modules/field/field.module- Run
:ALEFixand the buffer is preserved even making code error and fix it with ALEFix works.
Copying the phpcs.xml.dist to the root of the repo also fixes the issue.
I hope this helps to catch the bug.
Is it possible that phpcs and phpcbf have different logic to detect the standard?
Why is no info about phpcbf being launched at :ALEInfo?
The same trick can be done in ALE's codebase by using the
process_withoption for the fixer.
I'm trying to do just that but I have no idea how the process_with callback works. This is what I have so far in my init.vim:
function! s:ale_fix_php(bufnr, output)
let output = filter(copy(a:output), 'v:val !~# "No fixable errors were found"')
return output
endfunction
let g:ale_fixers_process_with = {'php': function('s:ale_fix_php')}
autocmd FileType php let b:ale_fixers = ['phpcbf']
after some digging I figured that my issue is related to #4236 .
i have same problem phpcbf
on save any file with filename is start with dot (example .test.php) content replaced at:
No fixable errors were found
Time: 34ms; Memory: 6MB