From 5458a1b29167b1fefde5fb6545e371a9d77ca36e Mon Sep 17 00:00:00 2001 From: Horacio Sanson Date: Sun, 22 Nov 2020 05:49:31 +0900 Subject: [PATCH] Fix 3103 - add shellcheck shell directive detection. (#3216) * Fix 3103 - add shellcheck shell directive detection. Searches for shellcheck shell directive to detect dialects for scripts that do not have shebang. * Change order of detection of shellcheck dialect In a situation where the filetype can be wrong (example: something.sh which is written in bash dialect) and has no hash-bang (since it is meant to be sourced) then the override specified within the script will be ignored. It probably is the most right thing to do if the script author has added a specific directive; it should trump everything else. Co-authored-by: Horacio Sanson Co-authored-by: Dino Korah --- autoload/ale/handlers/shellcheck.vim | 26 ++++++++++++++- test/test_shell_detection.vader | 48 ++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/autoload/ale/handlers/shellcheck.vim b/autoload/ale/handlers/shellcheck.vim index 351d6d3f..701c43b2 100644 --- a/autoload/ale/handlers/shellcheck.vim +++ b/autoload/ale/handlers/shellcheck.vim @@ -1,8 +1,32 @@ " Author: w0rp " Description: This file adds support for using the shellcheck linter +" Shellcheck supports shell directives to define the shell dialect for scripts +" that do not have a shebang for some reason. +" https://github.com/koalaman/shellcheck/wiki/Directive#shell +function! ale#handlers#shellcheck#GetShellcheckDialectDirective(buffer) abort + let l:linenr = 0 + let l:pattern = '\s\{-}#\s\{-}shellcheck\s\{-}shell=\(.*\)' + let l:possible_shell = ['bash', 'dash', 'ash', 'tcsh', 'csh', 'zsh', 'ksh', 'sh'] + + while l:linenr < min([50, line('$')]) + let l:linenr += 1 + let l:match = matchlist(getline(l:linenr), l:pattern) + + if len(l:match) > 1 && index(l:possible_shell, l:match[1]) >= 0 + return l:match[1] + endif + endwhile + + return '' +endfunction + function! ale#handlers#shellcheck#GetDialectArgument(buffer) abort - let l:shell_type = ale#handlers#sh#GetShellType(a:buffer) + let l:shell_type = ale#handlers#shellcheck#GetShellcheckDialectDirective(a:buffer) + + if empty(l:shell_type) + let l:shell_type = ale#handlers#sh#GetShellType(a:buffer) + endif if !empty(l:shell_type) " Use the dash dialect for /bin/ash, etc. diff --git a/test/test_shell_detection.vader b/test/test_shell_detection.vader index 697054d0..11d801c3 100644 --- a/test/test_shell_detection.vader +++ b/test/test_shell_detection.vader @@ -127,3 +127,51 @@ Execute(The dash dialect should be used for the shell and the base function): Execute(dash should be used for shellcheck): AssertEqual 'dash', ale#handlers#shellcheck#GetDialectArgument(bufnr('')) + +Given(A file with a Bash shellcheck shell directive): + # shellcheck shell=bash + +Execute(bash dialect should be detected appropriately): + AssertEqual 'bash', ale#handlers#shellcheck#GetDialectArgument(bufnr('')) + +Given(A file with a sh shellcheck shell directive): + #shellcheck shell=sh + +Execute(sh dialect should be detected appropriately): + AssertEqual 'sh', ale#handlers#shellcheck#GetDialectArgument(bufnr('')) + +Given(A file with a tcsh shellcheck shell directive): + # shellcheck shell=tcsh + +Execute(tcsh dialect should be detected appropriately): + AssertEqual 'tcsh', ale#handlers#shellcheck#GetDialectArgument(bufnr('')) + +Given(A file with a zsh shellcheck shell directive): + # shellcheck shell=zsh + +Execute(zsh dialect should be detected appropriately): + AssertEqual 'zsh', ale#handlers#shellcheck#GetDialectArgument(bufnr('')) + +Given(A file with a csh shellcheck shell directive): + # shellcheck shell=csh + +Execute(zsh dialect should be detected appropriately): + AssertEqual 'csh', ale#handlers#shellcheck#GetDialectArgument(bufnr('')) + +Given(A file with a ksh shellcheck shell directive): + # shellcheck shell=ksh + +Execute(ksh dialect should be detected appropriately): + AssertEqual 'ksh', ale#handlers#shellcheck#GetDialectArgument(bufnr('')) + +Given(A file with a dash shellcheck shell directive): + # shellcheck shell=dash + +Execute(dash dialect should be detected appropriately): + AssertEqual 'dash', ale#handlers#shellcheck#GetDialectArgument(bufnr('')) + +Given(A file with a ash shellcheck shell directive): + # shellcheck shell=ash + +Execute(dash dialect should be detected for ash that shellcheck does not support): + AssertEqual 'dash', ale#handlers#shellcheck#GetDialectArgument(bufnr(''))