ale icon indicating copy to clipboard operation
ale copied to clipboard

phpcbf empties my file on save

Open CaptainQuirk opened this issue 6 years ago • 12 comments
trafficstars

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

  1. Open the file
  2. 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:

CaptainQuirk avatar Apr 10 '19 12:04 CaptainQuirk

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.

w0rp avatar Apr 10 '19 14:04 w0rp

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

CaptainQuirk avatar Apr 10 '19 15:04 CaptainQuirk

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

mikedfunk avatar Jun 05 '19 22:06 mikedfunk

The same trick can be done in ALE's codebase by using the process_with option for the fixer.

w0rp avatar Jun 08 '19 23:06 w0rp

I ran into this today and @mikedfunk's fix worked for me

dustinleblanc avatar Aug 22 '19 14:08 dustinleblanc

@mikedfunk 's fix worked for me.

danshumaker avatar Dec 05 '19 01:12 danshumaker

Just started experiencing this. Weird. @mikedfunk 's fix worked here too.

ediblemanager avatar Jan 09 '20 20:01 ediblemanager

@mikedfunk it didn't work in my machine, this is what I found:

Running the script directly didn't work:

image

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

image

Install phpcbf globally with:

composer global require squizlabs/php_codesniffer

it now works:

image

eduardoarandah avatar Feb 12 '20 18:02 eduardoarandah

I have the same issue and is very annoying. Maybe it is possible to fix it in ALE itself?

Mte90 avatar Jul 27 '20 16:07 Mte90

it is time for another ping because I got the same error also with that script configured and I am investigating why.

Mte90 avatar Jan 05 '21 12:01 Mte90

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!

gnuget avatar Jul 13 '22 00:07 gnuget

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 .module file like vim 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 :ALEFix and 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?

rodrigoaguilera avatar Sep 09 '22 12:09 rodrigoaguilera

The same trick can be done in ALE's codebase by using the process_with option 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']

skylite21 avatar Dec 25 '22 19:12 skylite21

after some digging I figured that my issue is related to #4236 .

skylite21 avatar Dec 25 '22 21:12 skylite21

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


nPaul avatar Jun 05 '23 07:06 nPaul