Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Missing "shellcheck shell={dialect}" detection #3103

Closed
lloeki opened this issue Apr 13, 2020 · 2 comments · Fixed by #3216
Closed

Missing "shellcheck shell={dialect}" detection #3103

lloeki opened this issue Apr 13, 2020 · 2 comments · Fixed by #3216
Labels

Comments

@lloeki
Copy link
Contributor

lloeki commented Apr 13, 2020

Information

VIM version

VIM - Vi IMproved 8.2 (2019 Dec 12, compiled Mar 11 2020 13:48:59)
macOS version
Included patches: 1-343

Operating System: macOS 10.15

What went wrong

Opening a shell file with shellcheck shell=bash lints with shellcheck -s sh.

Reproducing the bug

$ cat > foo <<EOF
# vim: ft=sh
# shellcheck shell=bash
function foo(){
  true
}
EOF
$ vim foo  # shows SC2112

=> ALE orders spellcheck to lint as sh

Seems like in ale_linters#sh#shellcheck#GetDialectArgument(buffer) there's a vim-level workaround possible by writing my own autocmd to set some buffer variables, but my vimscript-fu is terrible:

    " If there's no hashbang, try using Vim's buffer variables.
    if getbufvar(a:buffer, 'is_bash', 0)
        return 'bash'
    elseif getbufvar(a:buffer, 'is_sh', 0)
        return 'sh'
    elseif getbufvar(a:buffer, 'is_kornshell', 0)
        return 'ksh'
    endif

But from a cursory look I suppose ale#handlers#sh#GetShellType(buffer) ought to be modified to look for shellcheck shell={dialect} in the first few lines (again my vimscript-fu is appalling, otherwise I'd have made a PR 😅).

:ALEInfo

Current Filetype: sh
Available Linters: ['language_server', 'shell', 'shellcheck']
  Enabled Linters: ['language_server', 'shell', 'shellcheck']
 Suggested Fixers: 
  'remove_trailing_lines' - Remove all blank lines at the end of a file.
  'shfmt' - Fix sh files with shfmt.
  'trim_whitespace' - Remove all trailing whitespace characters at the end of every line.
 Linter Variables:

let g:ale_sh_language_server_executable = 'bash-language-server'
let g:ale_sh_language_server_use_global = 0
let g:ale_sh_shell_default_shell = 'zsh'
let g:ale_sh_shellcheck_change_directory = 1
let g:ale_sh_shellcheck_dialect = 'auto'
let g:ale_sh_shellcheck_exclusions = ''
let g:ale_sh_shellcheck_executable = 'shellcheck'
let g:ale_sh_shellcheck_options = ''
 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_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 = 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 = 200
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_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 = 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:

(executable check - success) zsh
(finished - exit code 0) ['/bin/zsh', '-c', 'zsh -n ''/var/folders/hx/6nb5k_jn6mn8v6ch4xh6937c0000gp/T/vC3jppQ/2/foo''']

<<<NO OUTPUT RETURNED>>>

(executable check - success) shellcheck
(finished - exit code 0) ['/bin/zsh', '-c', '''shellcheck'' --version']

<<<OUTPUT STARTS>>>
ShellCheck - shell script analysis tool
version: 0.7.0
license: GNU General Public License, version 3
website: https://www.shellcheck.net
<<<OUTPUT ENDS>>>

(finished - exit code 1) ['/bin/zsh', '-c', 'cd ''/Users/lloeki'' && ''shellcheck'' -s sh -x -f gcc - < ''/var/folders/hx/6nb5k_jn6mn8v6ch4xh6937c0000gp/T/vC3jppQ/3/foo''']

<<<OUTPUT STARTS>>>
-:3:1: warning: 'function' keyword is non-standard. Delete it. [SC2112]
<<<OUTPUT ENDS>>>
@lloeki lloeki added the bug label Apr 13, 2020
@lloeki
Copy link
Contributor Author

lloeki commented Apr 13, 2020

Actually came up with this limited workaround:

function! ShellcheckDetect(buffer)
  for l:line_num in [1, 2, 3]
    let l:line = get(getbufline(a:buffer, l:line_num), 0, '')

    if l:line[:11] is# '# shellcheck'
      let l:command = l:line
      for l:possible_shell in ['bash', 'dash', 'ash', 'tcsh', 'csh', 'zsh', 'ksh', 'sh']
        if l:command =~# l:possible_shell . '\s*$'
          return l:possible_shell
        endif
      endfor
    endif
  endfor

  return ''
endfunction

function! ShellcheckSet(buffer)
  let l:shell = ShellcheckDetect(a:buffer)
  if l:shell == 'bash'
    call setbufvar(a:buffer, 'is_bash', 1)
  else
    call setbufvar(a:buffer, 'is_bash', 0)
  endif
endfunction

autocmd FileType sh call ShellcheckSet(bufnr("%"))

@hsanson
Copy link
Contributor

hsanson commented Jun 24, 2020

@lloeki I have create a PR that adds support to shellcheck shell directives for dialect detection.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants