mirror of
1
0
Fork 0

Updated plugins

This commit is contained in:
Amir Salihefendic 2018-06-14 12:31:12 +02:00
parent 7288aee801
commit 3e3297af67
273 changed files with 11821 additions and 5377 deletions

View File

@ -1,37 +0,0 @@
" Author: w0rp <devw0rp@gmail.com>
" Description: Follow-up checks for the plugin: warn about conflicting plugins.
" A flag for ensuring that this is not run more than one time.
if exists('g:loaded_ale_after')
finish
endif
" Set the flag so this file is not run more than one time.
let g:loaded_ale_after = 1
" Check if the flag is available and set to 0 to disable checking for and
" emitting conflicting plugin warnings.
if exists('g:ale_emit_conflict_warnings') && !g:ale_emit_conflict_warnings
finish
endif
" Conflicting Plugins Checks
function! s:GetConflictingPluginWarning(plugin_name) abort
return 'ALE conflicts with ' . a:plugin_name
\ . '. Uninstall it, or disable this warning with '
\ . '`let g:ale_emit_conflict_warnings = 0` in your vimrc file, '
\ . '*before* plugins are loaded.'
endfunction
if exists('g:loaded_syntastic_plugin')
throw s:GetConflictingPluginWarning('Syntastic')
endif
if exists('g:loaded_neomake')
throw s:GetConflictingPluginWarning('Neomake')
endif
if exists('g:loaded_validator_plugin')
throw s:GetConflictingPluginWarning('Validator')
endif

View File

@ -0,0 +1,34 @@
" Author: Ben Falconer <ben@falconers.me.uk>
" Description: A language server for C++
call ale#Set('cpp_cquery_executable', 'cquery')
call ale#Set('cpp_cquery_cache_directory', expand('~/.cache/cquery'))
function! ale_linters#cpp#cquery#GetProjectRoot(buffer) abort
let l:project_root = ale#path#FindNearestFile(a:buffer, 'compile_commands.json')
return !empty(l:project_root) ? fnamemodify(l:project_root, ':h') : ''
endfunction
function! ale_linters#cpp#cquery#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'cpp_cquery_executable')
endfunction
function! ale_linters#cpp#cquery#GetCommand(buffer) abort
let l:executable = ale_linters#cpp#cquery#GetExecutable(a:buffer)
return ale#Escape(l:executable)
endfunction
function! ale_linters#cpp#cquery#GetInitializationOptions(buffer) abort
return {'cacheDirectory': ale#Var(a:buffer, 'cpp_cquery_cache_directory')}
endfunction
call ale#linter#Define('cpp', {
\ 'name': 'cquery',
\ 'lsp': 'stdio',
\ 'executable_callback': 'ale_linters#cpp#cquery#GetExecutable',
\ 'command_callback': 'ale_linters#cpp#cquery#GetCommand',
\ 'project_root_callback': 'ale_linters#cpp#cquery#GetProjectRoot',
\ 'initialization_options_callback': 'ale_linters#cpp#cquery#GetInitializationOptions',
\ 'language': 'cpp',
\})

View File

@ -4,6 +4,7 @@
call ale#Set('cpp_flawfinder_executable', 'flawfinder') call ale#Set('cpp_flawfinder_executable', 'flawfinder')
call ale#Set('cpp_flawfinder_options', '') call ale#Set('cpp_flawfinder_options', '')
call ale#Set('cpp_flawfinder_minlevel', 1) call ale#Set('cpp_flawfinder_minlevel', 1)
call ale#Set('c_flawfinder_error_severity', 6)
function! ale_linters#cpp#flawfinder#GetExecutable(buffer) abort function! ale_linters#cpp#flawfinder#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'cpp_flawfinder_executable') return ale#Var(a:buffer, 'cpp_flawfinder_executable')

View File

@ -21,7 +21,8 @@ function! ale_linters#cpp#gcc#GetCommand(buffer, output) abort
endfunction endfunction
call ale#linter#Define('cpp', { call ale#linter#Define('cpp', {
\ 'name': 'g++', \ 'name': 'gcc',
\ 'aliases': ['g++'],
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'executable_callback': 'ale_linters#cpp#gcc#GetExecutable', \ 'executable_callback': 'ale_linters#cpp#gcc#GetExecutable',
\ 'command_chain': [ \ 'command_chain': [

View File

@ -2,7 +2,7 @@
call ale#Set('css_stylelint_executable', 'stylelint') call ale#Set('css_stylelint_executable', 'stylelint')
call ale#Set('css_stylelint_options', '') call ale#Set('css_stylelint_options', '')
call ale#Set('css_stylelint_use_global', 0) call ale#Set('css_stylelint_use_global', get(g:, 'ale_use_global_executables', 0))
function! ale_linters#css#stylelint#GetExecutable(buffer) abort function! ale_linters#css#stylelint#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'css_stylelint', [ return ale#node#FindExecutable(a:buffer, 'css_stylelint', [

View File

@ -0,0 +1,45 @@
" Author: Eddie Lebow https://github.com/elebow
" Description: Cucumber, a BDD test tool
function! ale_linters#cucumber#cucumber#GetCommand(buffer) abort
let l:features_dir = ale#path#FindNearestDirectory(a:buffer, 'features')
if !empty(l:features_dir)
let l:features_arg = '-r ' . ale#Escape(l:features_dir)
else
let l:features_arg = ''
endif
return 'cucumber --dry-run --quiet --strict --format=json '
\ . l:features_arg . ' %t'
endfunction
function! ale_linters#cucumber#cucumber#Handle(buffer, lines) abort
try
let l:json = ale#util#FuzzyJSONDecode(a:lines, {})[0]
catch
return []
endtry
let l:output = []
for l:element in get(l:json, 'elements', [])
for l:step in l:element['steps']
if l:step['result']['status'] is# 'undefined'
call add(l:output, {
\ 'lnum': l:step['line'],
\ 'code': 'E',
\ 'text': 'Undefined step'
\})
endif
endfor
endfor
return l:output
endfunction
call ale#linter#Define('cucumber', {
\ 'name': 'cucumber',
\ 'executable': 'cucumber',
\ 'command_callback': 'ale_linters#cucumber#cucumber#GetCommand',
\ 'callback': 'ale_linters#cucumber#cucumber#Handle'
\})

View File

@ -46,7 +46,7 @@ function! ale_linters#d#dmd#DMDCommand(buffer, dub_output) abort
endif endif
endfor endfor
return 'dmd '. join(l:import_list) . ' -o- -vcolumns -c %t' return 'dmd '. join(l:import_list) . ' -o- -wi -vcolumns -c %t'
endfunction endfunction
function! ale_linters#d#dmd#Handle(buffer, lines) abort function! ale_linters#d#dmd#Handle(buffer, lines) abort

View File

@ -7,10 +7,6 @@ function! ale_linters#dart#language_server#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'dart_language_server_executable') return ale#Var(a:buffer, 'dart_language_server_executable')
endfunction endfunction
function! ale_linters#dart#language_server#GetLanguage(buffer) abort
return 'dart'
endfunction
function! ale_linters#dart#language_server#GetProjectRoot(buffer) abort function! ale_linters#dart#language_server#GetProjectRoot(buffer) abort
" Note: pub only looks for pubspec.yaml, there's no point in adding " Note: pub only looks for pubspec.yaml, there's no point in adding
" support for pubspec.yml " support for pubspec.yml
@ -24,7 +20,6 @@ call ale#linter#Define('dart', {
\ 'lsp': 'stdio', \ 'lsp': 'stdio',
\ 'executable_callback': 'ale_linters#dart#language_server#GetExecutable', \ 'executable_callback': 'ale_linters#dart#language_server#GetExecutable',
\ 'command_callback': 'ale_linters#dart#language_server#GetExecutable', \ 'command_callback': 'ale_linters#dart#language_server#GetExecutable',
\ 'language_callback': 'ale_linters#dart#language_server#GetLanguage', \ 'language': 'dart',
\ 'project_root_callback': 'ale_linters#dart#language_server#GetProjectRoot', \ 'project_root_callback': 'ale_linters#dart#language_server#GetProjectRoot',
\}) \})

View File

@ -1,45 +1,26 @@
" Author: buffalocoder - https://github.com/buffalocoder, soywod - https://github.com/soywod " Author: buffalocoder - https://github.com/buffalocoder, soywod - https://github.com/soywod, hecrj - https://github.com/hecrj
" Description: Elm linting in Ale. Closely follows the Syntastic checker in https://github.com/ElmCast/elm-vim. " Description: Elm linting in Ale. Closely follows the Syntastic checker in https://github.com/ElmCast/elm-vim.
call ale#Set('elm_make_executable', 'elm-make') call ale#Set('elm_make_executable', 'elm')
call ale#Set('elm_make_use_global', 0) call ale#Set('elm_make_use_global', get(g:, 'ale_use_global_executables', 0))
function! ale_linters#elm#make#GetExecutable(buffer) abort function! ale_linters#elm#make#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'elm_make', [ return ale#node#FindExecutable(a:buffer, 'elm_make', [
\ 'node_modules/.bin/elm-make', \ 'node_modules/.bin/elm',
\]) \])
endfunction endfunction
function! ale_linters#elm#make#Handle(buffer, lines) abort function! ale_linters#elm#make#Handle(buffer, lines) abort
let l:output = [] let l:output = []
let l:is_windows = has('win32')
let l:temp_dir = l:is_windows ? $TMP : $TMPDIR
let l:unparsed_lines = [] let l:unparsed_lines = []
for l:line in a:lines for l:line in a:lines
if l:line[0] is# '[' if l:line[0] is# '{'
let l:errors = json_decode(l:line) " Elm 0.19
call ale_linters#elm#make#HandleElm019Line(l:line, l:output)
for l:error in l:errors elseif l:line[0] is# '['
" Check if file is from the temp directory. " Elm 0.18
" Filters out any errors not related to the buffer. call ale_linters#elm#make#HandleElm018Line(l:line, l:output)
if l:is_windows
let l:file_is_buffer = l:error.file[0:len(l:temp_dir) - 1] is? l:temp_dir
else
let l:file_is_buffer = l:error.file[0:len(l:temp_dir) - 1] is# l:temp_dir
endif
if l:file_is_buffer
call add(l:output, {
\ 'lnum': l:error.region.start.line,
\ 'col': l:error.region.start.column,
\ 'end_lnum': l:error.region.end.line,
\ 'end_col': l:error.region.end.column,
\ 'type': (l:error.type is? 'error') ? 'E' : 'W',
\ 'text': l:error.overview,
\ 'detail': l:error.overview . "\n\n" . l:error.details
\})
endif
endfor
elseif l:line isnot# 'Successfully generated /dev/null' elseif l:line isnot# 'Successfully generated /dev/null'
call add(l:unparsed_lines, l:line) call add(l:unparsed_lines, l:line)
endif endif
@ -57,23 +38,142 @@ function! ale_linters#elm#make#Handle(buffer, lines) abort
return l:output return l:output
endfunction endfunction
function! ale_linters#elm#make#HandleElm019Line(line, output) abort
let l:report = json_decode(a:line)
if l:report.type is? 'error'
" General problem
let l:details = ale_linters#elm#make#ParseMessage(l:report.message)
if empty(l:report.path)
let l:report.path = 'Elm'
endif
if ale_linters#elm#make#FileIsBuffer(l:report.path)
call add(a:output, {
\ 'lnum': 1,
\ 'type': 'E',
\ 'text': l:details,
\})
else
call add(a:output, {
\ 'lnum': 1,
\ 'type': 'E',
\ 'text': l:report.path .' - '. l:details,
\ 'detail': l:report.path ." ----------\n\n". l:details,
\})
endif
else
" Compilation errors
for l:error in l:report.errors
let l:file_is_buffer = ale_linters#elm#make#FileIsBuffer(l:error.path)
for l:problem in l:error.problems
let l:details = ale_linters#elm#make#ParseMessage(l:problem.message)
if l:file_is_buffer
" Buffer module has problems
call add(a:output, {
\ 'lnum': l:problem.region.start.line,
\ 'col': l:problem.region.start.column,
\ 'end_lnum': l:problem.region.end.line,
\ 'end_col': l:problem.region.end.column,
\ 'type': 'E',
\ 'text': l:details,
\})
else
" Imported module has problems
let l:location = l:error.path .':'. l:problem.region.start.line
call add(a:output, {
\ 'lnum': 1,
\ 'type': 'E',
\ 'text': l:location .' - '. l:details,
\ 'detail': l:location ." ----------\n\n". l:details,
\})
endif
endfor
endfor
endif
endfunction
function! ale_linters#elm#make#HandleElm018Line(line, output) abort
let l:errors = json_decode(a:line)
for l:error in l:errors
let l:file_is_buffer = ale_linters#elm#make#FileIsBuffer(l:error.file)
if l:file_is_buffer
" Current buffer has problems
call add(a:output, {
\ 'lnum': l:error.region.start.line,
\ 'col': l:error.region.start.column,
\ 'end_lnum': l:error.region.end.line,
\ 'end_col': l:error.region.end.column,
\ 'type': (l:error.type is? 'error') ? 'E' : 'W',
\ 'text': l:error.overview,
\ 'detail': l:error.overview . "\n\n" . l:error.details
\})
elseif l:error.type is? 'error'
" Imported module has errors
let l:location = l:error.file .':'. l:error.region.start.line
call add(a:output, {
\ 'lnum': 1,
\ 'type': 'E',
\ 'text': l:location .' - '. l:error.overview,
\ 'detail': l:location ." ----------\n\n". l:error.overview . "\n\n" . l:error.details
\})
endif
endfor
endfunction
function! ale_linters#elm#make#FileIsBuffer(path) abort
let l:is_windows = has('win32')
let l:temp_dir = l:is_windows ? $TMP : $TMPDIR
if has('win32')
return a:path[0:len(l:temp_dir) - 1] is? l:temp_dir
else
return a:path[0:len(l:temp_dir) - 1] is# l:temp_dir
endif
endfunction
function! ale_linters#elm#make#ParseMessage(message) abort
return join(map(copy(a:message), 'ale_linters#elm#make#ParseMessageItem(v:val)'), '')
endfunction
function! ale_linters#elm#make#ParseMessageItem(item) abort
if type(a:item) == type('')
return a:item
else
return a:item.string
endif
endfunction
" Return the command to execute the linter in the projects directory. " Return the command to execute the linter in the projects directory.
" If it doesn't, then this will fail when imports are needed. " If it doesn't, then this will fail when imports are needed.
function! ale_linters#elm#make#GetCommand(buffer) abort function! ale_linters#elm#make#GetCommand(buffer) abort
let l:elm_package = ale#path#FindNearestFile(a:buffer, 'elm-package.json') let l:elm_json = ale#path#FindNearestFile(a:buffer, 'elm.json')
let l:elm_exe = ale_linters#elm#make#GetExecutable(a:buffer) let l:elm_exe = ale_linters#elm#make#GetExecutable(a:buffer)
if empty(l:elm_package)
if empty(l:elm_json)
" Fallback to Elm 0.18
let l:elm_json = ale#path#FindNearestFile(a:buffer, 'elm-package.json')
endif
if empty(l:elm_json)
let l:dir_set_cmd = '' let l:dir_set_cmd = ''
else else
let l:root_dir = fnamemodify(l:elm_package, ':p:h') let l:root_dir = fnamemodify(l:elm_json, ':p:h')
let l:dir_set_cmd = 'cd ' . ale#Escape(l:root_dir) . ' && ' let l:dir_set_cmd = 'cd ' . ale#Escape(l:root_dir) . ' && '
endif endif
" The elm-make compiler, at the time of this writing, uses '/dev/null' as " The elm compiler, at the time of this writing, uses '/dev/null' as
" a sort of flag to tell the compiler not to generate an output file, " a sort of flag to tell the compiler not to generate an output file,
" which is why this is hard coded here. It does not use NUL on Windows. " which is why this is hard coded here.
" Source: https://github.com/elm-lang/elm-make/blob/master/src/Flags.hs " Source: https://github.com/elm-lang/elm-compiler/blob/19d5a769b30ec0b2fc4475985abb4cd94cd1d6c3/builder/src/Generate/Output.hs#L253
let l:elm_cmd = ale#Escape(l:elm_exe) let l:elm_cmd = ale#Escape(l:elm_exe)
\ . ' make'
\ . ' --report=json' \ . ' --report=json'
\ . ' --output=/dev/null' \ . ' --output=/dev/null'

View File

@ -4,7 +4,7 @@
let g:ale_gitcommit_gitlint_executable = let g:ale_gitcommit_gitlint_executable =
\ get(g:, 'ale_gitcommit_gitlint_executable', 'gitlint') \ get(g:, 'ale_gitcommit_gitlint_executable', 'gitlint')
let g:ale_gitcommit_gitlint_options = get(g:, 'ale_gitcommit_gitlint_options', '') let g:ale_gitcommit_gitlint_options = get(g:, 'ale_gitcommit_gitlint_options', '')
let g:ale_gitcommit_gitlint_use_global = get(g:, 'ale_gitcommit_gitlint_use_global', 0) let g:ale_gitcommit_gitlint_use_global = get(g:, 'ale_gitcommit_gitlint_use_global', get(g:, 'ale_use_global_executables', 0))
function! ale_linters#gitcommit#gitlint#GetExecutable(buffer) abort function! ale_linters#gitcommit#gitlint#GetExecutable(buffer) abort
@ -28,6 +28,10 @@ function! ale_linters#gitcommit#gitlint#Handle(buffer, lines) abort
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:match in ale#util#GetMatches(a:lines, l:pattern)
let l:code = l:match[2] let l:code = l:match[2]
if l:code is# 'T2' && !ale#Var(a:buffer, 'warn_about_trailing_whitespace')
continue
endif
let l:item = { let l:item = {
\ 'lnum': l:match[1] + 0, \ 'lnum': l:match[1] + 0,
\ 'text': l:match[3], \ 'text': l:match[3],

View File

@ -18,10 +18,6 @@ function! ale_linters#glsl#glslls#GetCommand(buffer) abort
return ale#Escape(l:executable) . l:logfile_args . ' --stdin' return ale#Escape(l:executable) . l:logfile_args . ' --stdin'
endfunction endfunction
function! ale_linters#glsl#glslls#GetLanguage(buffer) abort
return 'glsl'
endfunction
function! ale_linters#glsl#glslls#GetProjectRoot(buffer) abort function! ale_linters#glsl#glslls#GetProjectRoot(buffer) abort
let l:project_root = ale#c#FindProjectRoot(a:buffer) let l:project_root = ale#c#FindProjectRoot(a:buffer)
@ -33,6 +29,6 @@ call ale#linter#Define('glsl', {
\ 'lsp': 'stdio', \ 'lsp': 'stdio',
\ 'executable_callback': 'ale_linters#glsl#glslls#GetExecutable', \ 'executable_callback': 'ale_linters#glsl#glslls#GetExecutable',
\ 'command_callback': 'ale_linters#glsl#glslls#GetCommand', \ 'command_callback': 'ale_linters#glsl#glslls#GetCommand',
\ 'language_callback': 'ale_linters#glsl#glslls#GetLanguage', \ 'language': 'glsl',
\ 'project_root_callback': 'ale_linters#glsl#glslls#GetProjectRoot', \ 'project_root_callback': 'ale_linters#glsl#glslls#GetProjectRoot',
\}) \})

View File

@ -2,7 +2,7 @@
" Description: Ember-template-lint for checking Handlebars files " Description: Ember-template-lint for checking Handlebars files
call ale#Set('handlebars_embertemplatelint_executable', 'ember-template-lint') call ale#Set('handlebars_embertemplatelint_executable', 'ember-template-lint')
call ale#Set('handlebars_embertemplatelint_use_global', 0) call ale#Set('handlebars_embertemplatelint_use_global', get(g:, 'ale_use_global_executables', 0))
function! ale_linters#handlebars#embertemplatelint#GetExecutable(buffer) abort function! ale_linters#handlebars#embertemplatelint#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'handlebars_embertemplatelint', [ return ale#node#FindExecutable(a:buffer, 'handlebars_embertemplatelint', [

View File

@ -2,7 +2,7 @@
" Description: hdevtools for Haskell files " Description: hdevtools for Haskell files
call ale#Set('haskell_hdevtools_executable', 'hdevtools') call ale#Set('haskell_hdevtools_executable', 'hdevtools')
call ale#Set('haskell_hdevtools_options', '-g -Wall') call ale#Set('haskell_hdevtools_options', get(g:, 'hdevtools_options', '-g -Wall'))
function! ale_linters#haskell#hdevtools#GetExecutable(buffer) abort function! ale_linters#haskell#hdevtools#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'haskell_hdevtools_executable') return ale#Var(a:buffer, 'haskell_hdevtools_executable')

View File

@ -3,7 +3,7 @@
call ale#Set('html_htmlhint_options', '') call ale#Set('html_htmlhint_options', '')
call ale#Set('html_htmlhint_executable', 'htmlhint') call ale#Set('html_htmlhint_executable', 'htmlhint')
call ale#Set('html_htmlhint_use_global', 0) call ale#Set('html_htmlhint_use_global', get(g:, 'ale_use_global_executables', 0))
function! ale_linters#html#htmlhint#GetExecutable(buffer) abort function! ale_linters#html#htmlhint#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'html_htmlhint', [ return ale#node#FindExecutable(a:buffer, 'html_htmlhint', [

View File

@ -3,11 +3,19 @@
" CLI options " CLI options
let g:ale_html_tidy_executable = get(g:, 'ale_html_tidy_executable', 'tidy') let g:ale_html_tidy_executable = get(g:, 'ale_html_tidy_executable', 'tidy')
" remove in 2.0
" Look for the old _args variable first. " Look for the old _args variable first.
let s:deprecation_warning_echoed = 0
let s:default_options = get(g:, 'ale_html_tidy_args', '-q -e -language en') let s:default_options = get(g:, 'ale_html_tidy_args', '-q -e -language en')
let g:ale_html_tidy_options = get(g:, 'ale_html_tidy_options', s:default_options) let g:ale_html_tidy_options = get(g:, 'ale_html_tidy_options', s:default_options)
function! ale_linters#html#tidy#GetCommand(buffer) abort function! ale_linters#html#tidy#GetCommand(buffer) abort
" remove in 2.0
if exists('g:ale_html_tidy_args') && !s:deprecation_warning_echoed
execute 'echom ''Rename your g:ale_html_tidy_args setting to g:ale_html_tidy_options instead. Support for this will removed in ALE 2.0.'''
let s:deprecation_warning_echoed = 1
endif
" Specify file encoding in options " Specify file encoding in options
" (Idea taken from https://github.com/scrooloose/syntastic/blob/master/syntax_checkers/html/tidy.vim) " (Idea taken from https://github.com/scrooloose/syntastic/blob/master/syntax_checkers/html/tidy.vim)
let l:file_encoding = get({ let l:file_encoding = get({

View File

@ -3,8 +3,9 @@
let s:classpath_sep = has('unix') ? ':' : ';' let s:classpath_sep = has('unix') ? ':' : ';'
let g:ale_java_javac_options = get(g:, 'ale_java_javac_options', '') call ale#Set('java_javac_executable', 'javac')
let g:ale_java_javac_classpath = get(g:, 'ale_java_javac_classpath', '') call ale#Set('java_javac_options', '')
call ale#Set('java_javac_classpath', '')
function! ale_linters#java#javac#GetImportPaths(buffer) abort function! ale_linters#java#javac#GetImportPaths(buffer) abort
let l:pom_path = ale#path#FindNearestFile(a:buffer, 'pom.xml') let l:pom_path = ale#path#FindNearestFile(a:buffer, 'pom.xml')
@ -35,6 +36,10 @@ function! s:BuildClassPathOption(buffer, import_paths) abort
\ : '' \ : ''
endfunction endfunction
function! ale_linters#java#javac#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'java_javac_executable')
endfunction
function! ale_linters#java#javac#GetCommand(buffer, import_paths) abort function! ale_linters#java#javac#GetCommand(buffer, import_paths) abort
let l:cp_option = s:BuildClassPathOption(a:buffer, a:import_paths) let l:cp_option = s:BuildClassPathOption(a:buffer, a:import_paths)
let l:sp_option = '' let l:sp_option = ''
@ -72,11 +77,13 @@ function! ale_linters#java#javac#GetCommand(buffer, import_paths) abort
" Create .class files in a temporary directory, which we will delete later. " Create .class files in a temporary directory, which we will delete later.
let l:class_file_directory = ale#engine#CreateDirectory(a:buffer) let l:class_file_directory = ale#engine#CreateDirectory(a:buffer)
let l:executable = ale_linters#java#javac#GetExecutable(a:buffer)
" Always run javac from the directory the file is in, so we can resolve " Always run javac from the directory the file is in, so we can resolve
" relative paths correctly. " relative paths correctly.
return ale#path#BufferCdString(a:buffer) return ale#path#BufferCdString(a:buffer)
\ . 'javac -Xlint' \ . ale#Escape(l:executable)
\ . ' -Xlint'
\ . ' ' . l:cp_option \ . ' ' . l:cp_option
\ . ' ' . l:sp_option \ . ' ' . l:sp_option
\ . ' -d ' . ale#Escape(l:class_file_directory) \ . ' -d ' . ale#Escape(l:class_file_directory)
@ -119,7 +126,7 @@ endfunction
call ale#linter#Define('java', { call ale#linter#Define('java', {
\ 'name': 'javac', \ 'name': 'javac',
\ 'executable': 'javac', \ 'executable_callback': 'ale_linters#java#javac#GetExecutable',
\ 'command_chain': [ \ 'command_chain': [
\ {'callback': 'ale_linters#java#javac#GetImportPaths', 'output_stream': 'stdout'}, \ {'callback': 'ale_linters#java#javac#GetImportPaths', 'output_stream': 'stdout'},
\ {'callback': 'ale_linters#java#javac#GetCommand', 'output_stream': 'stderr'}, \ {'callback': 'ale_linters#java#javac#GetCommand', 'output_stream': 'stderr'},

View File

@ -0,0 +1,36 @@
" Author: Johannes Wienke <languitar@semipol.de>
" Description: PMD for Java files
function! ale_linters#java#pmd#Handle(buffer, lines) abort
let l:pattern = '"\(\d\+\)",".\+","\(.\+\)","\(\d\+\)","\(\d\+\)","\(.\+\)","\(.\+\)","\(.\+\)"$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, {
\ 'type': 'W',
\ 'lnum': l:match[4] + 0,
\ 'text': l:match[5],
\ 'code': l:match[6] . ' - ' . l:match[7],
\})
endfor
return l:output
endfunction
function! ale_linters#java#pmd#GetCommand(buffer) abort
return 'pmd '
\ . ale#Var(a:buffer, 'java_pmd_options')
\ . ' -f csv'
\ . ' -d %t'
endfunction
if !exists('g:ale_java_pmd_options')
let g:ale_java_pmd_options = '-R category/java/bestpractices.xml'
endif
call ale#linter#Define('java', {
\ 'name': 'pmd',
\ 'executable': 'pmd',
\ 'command_callback': 'ale_linters#java#pmd#GetCommand',
\ 'callback': 'ale_linters#java#pmd#Handle',
\})

View File

@ -4,7 +4,8 @@
call ale#Set('javascript_flow_executable', 'flow') call ale#Set('javascript_flow_executable', 'flow')
call ale#Set('javascript_flow_use_home_config', 0) call ale#Set('javascript_flow_use_home_config', 0)
call ale#Set('javascript_flow_use_global', 0) call ale#Set('javascript_flow_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('javascript_flow_use_respect_pragma', 1)
function! ale_linters#javascript#flow#GetExecutable(buffer) abort function! ale_linters#javascript#flow#GetExecutable(buffer) abort
let l:flow_config = ale#path#FindNearestFile(a:buffer, '.flowconfig') let l:flow_config = ale#path#FindNearestFile(a:buffer, '.flowconfig')
@ -47,8 +48,8 @@ function! ale_linters#javascript#flow#GetCommand(buffer, version_lines) abort
" If we can parse the version number, then only use --respect-pragma " If we can parse the version number, then only use --respect-pragma
" if the version is >= 0.36.0, which added the argument. " if the version is >= 0.36.0, which added the argument.
let l:use_respect_pragma = empty(l:version) let l:use_respect_pragma = ale#Var(a:buffer, 'javascript_flow_use_respect_pragma')
\ || ale#semver#GTE(l:version, [0, 36]) \ && (empty(l:version) || ale#semver#GTE(l:version, [0, 36]))
return ale#Escape(l:executable) return ale#Escape(l:executable)
\ . ' check-contents' \ . ' check-contents'

View File

@ -2,7 +2,7 @@
" Description: jscs for JavaScript files " Description: jscs for JavaScript files
call ale#Set('javascript_jscs_executable', 'jscs') call ale#Set('javascript_jscs_executable', 'jscs')
call ale#Set('javascript_jscs_use_global', 0) call ale#Set('javascript_jscs_use_global', get(g:, 'ale_use_global_executables', 0))
function! ale_linters#javascript#jscs#GetExecutable(buffer) abort function! ale_linters#javascript#jscs#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'javascript_jscs', [ return ale#node#FindExecutable(a:buffer, 'javascript_jscs', [

View File

@ -2,7 +2,7 @@
" Description: JSHint for Javascript files " Description: JSHint for Javascript files
call ale#Set('javascript_jshint_executable', 'jshint') call ale#Set('javascript_jshint_executable', 'jshint')
call ale#Set('javascript_jshint_use_global', 0) call ale#Set('javascript_jshint_use_global', get(g:, 'ale_use_global_executables', 0))
function! ale_linters#javascript#jshint#GetExecutable(buffer) abort function! ale_linters#javascript#jshint#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'javascript_jshint', [ return ale#node#FindExecutable(a:buffer, 'javascript_jshint', [

View File

@ -2,7 +2,7 @@
" Description: standardjs for JavaScript files " Description: standardjs for JavaScript files
call ale#Set('javascript_standard_executable', 'standard') call ale#Set('javascript_standard_executable', 'standard')
call ale#Set('javascript_standard_use_global', 0) call ale#Set('javascript_standard_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('javascript_standard_options', '') call ale#Set('javascript_standard_options', '')
function! ale_linters#javascript#standard#GetExecutable(buffer) abort function! ale_linters#javascript#standard#GetExecutable(buffer) abort

View File

@ -2,7 +2,7 @@
" Description: xo for JavaScript files " Description: xo for JavaScript files
call ale#Set('javascript_xo_executable', 'xo') call ale#Set('javascript_xo_executable', 'xo')
call ale#Set('javascript_xo_use_global', 0) call ale#Set('javascript_xo_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('javascript_xo_options', '') call ale#Set('javascript_xo_options', '')
function! ale_linters#javascript#xo#GetExecutable(buffer) abort function! ale_linters#javascript#xo#GetExecutable(buffer) abort

View File

@ -3,7 +3,7 @@
call ale#Set('less_lessc_executable', 'lessc') call ale#Set('less_lessc_executable', 'lessc')
call ale#Set('less_lessc_options', '') call ale#Set('less_lessc_options', '')
call ale#Set('less_lessc_use_global', 0) call ale#Set('less_lessc_use_global', get(g:, 'ale_use_global_executables', 0))
function! ale_linters#less#lessc#GetExecutable(buffer) abort function! ale_linters#less#lessc#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'less_lessc', [ return ale#node#FindExecutable(a:buffer, 'less_lessc', [

View File

@ -2,7 +2,7 @@
call ale#Set('less_stylelint_executable', 'stylelint') call ale#Set('less_stylelint_executable', 'stylelint')
call ale#Set('less_stylelint_options', '') call ale#Set('less_stylelint_options', '')
call ale#Set('less_stylelint_use_global', 0) call ale#Set('less_stylelint_use_global', get(g:, 'ale_use_global_executables', 0))
function! ale_linters#less#stylelint#GetExecutable(buffer) abort function! ale_linters#less#stylelint#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'less_stylelint', [ return ale#node#FindExecutable(a:buffer, 'less_stylelint', [

View File

@ -10,9 +10,13 @@ endfunction
function! ale_linters#markdown#mdl#GetCommand(buffer) abort function! ale_linters#markdown#mdl#GetCommand(buffer) abort
let l:executable = ale_linters#markdown#mdl#GetExecutable(a:buffer) let l:executable = ale_linters#markdown#mdl#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'bundle$'
\ ? ' exec mdl'
\ : ''
let l:options = ale#Var(a:buffer, 'markdown_mdl_options') let l:options = ale#Var(a:buffer, 'markdown_mdl_options')
return ale#Escape(l:executable) return ale#Escape(l:executable) . l:exec_args
\ . (!empty(l:options) ? ' ' . l:options : '') \ . (!empty(l:options) ? ' ' . l:options : '')
endfunction endfunction

View File

@ -0,0 +1,45 @@
" Author: stewy33 <slocumstewy@gmail.com>
" Description: Lints mercury files using mmc
call ale#Set('mercury_mmc_executable', 'mmc')
call ale#Set('mercury_mmc_options', '--make --output-compile-error-lines 100')
function! ale_linters#mercury#mmc#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'mercury_mmc_executable')
endfunction
function! ale_linters#mercury#mmc#GetCommand(buffer) abort
let l:module_name = expand('#' . a:buffer . ':t:r')
return ale#path#BufferCdString(a:buffer)
\ . ale_linters#mercury#mmc#GetExecutable(a:buffer)
\ . ' --errorcheck-only '
\ . ale#Var(a:buffer, 'mercury_mmc_options')
\ . ' ' . l:module_name
endfunction
function! ale_linters#mercury#mmc#Handle(buffer, lines) abort
" output format
" <filename>:<line>: <issue type>: <message>
let l:pattern = '\v^\w+\.m:(\d+):\s+([W|w]arning|.*[E|e]rror.*): (.*)'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, {
\ 'lnum': substitute(l:match[1], '\v^0*', '', '') + 0,
\ 'type': l:match[2][0] =~? 'W' ? 'W' : 'E',
\ 'text': l:match[2] . ': ' . l:match[3]
\})
endfor
return l:output
endfunction
call ale#linter#Define('mercury', {
\ 'name': 'mmc',
\ 'output_stream': 'stderr',
\ 'executable_callback': 'ale_linters#mercury#mmc#GetExecutable',
\ 'command_callback': 'ale_linters#mercury#mmc#GetCommand',
\ 'callback': 'ale_linters#mercury#mmc#Handle',
\ 'lint_file': 1,
\})

View File

@ -0,0 +1,50 @@
" Author: Oyvind Ingvaldsen <oyvind.ingvaldsen@gmail.com>
" Description: NASM linter for asmsyntax nasm.
call ale#Set('nasm_nasm_executable', 'nasm')
call ale#Set('nasm_nasm_options', '')
function! ale_linters#nasm#nasm#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'nasm_nasm_executable')
endfunction
function! ale_linters#nasm#nasm#GetOptions(buffer) abort
return ale#Var(a:buffer, 'nasm_nasm_options')
endfunction
function! ale_linters#nasm#nasm#GetCommand(buffer) abort
" Note that NASM require a trailing slash to the -I option.
let l:executable = ale#Escape(ale_linters#nasm#nasm#GetExecutable(a:buffer))
let l:separator = has('win32') ? '\' : '/'
let l:path = ale#Escape(fnamemodify(bufname(a:buffer), ':p:h') . l:separator)
let l:options = ale_linters#nasm#nasm#GetOptions(a:buffer)
return l:executable
\ . ' -X gnu'
\ . ' -I ' . l:path
\ . ' ' . l:options
\ . ' %s'
endfunction
function! ale_linters#nasm#nasm#Handle(buffer, lines) abort
" Note that we treat 'fatal' as errors.
let l:pattern = '^.\+:\(\d\+\): \([^:]\+\): \(.\+\)$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, {
\ 'lnum': l:match[1] + 0,
\ 'type': l:match[2] =~? 'error\|fatal' ? 'E' : 'W',
\ 'text': l:match[3],
\})
endfor
return l:output
endfunction
call ale#linter#Define('nasm', {
\ 'name': 'nasm',
\ 'executable': 'nasm',
\ 'output_stream': 'stderr',
\ 'lint_file': 1,
\ 'command_callback': 'ale_linters#nasm#nasm#GetCommand',
\ 'callback': 'ale_linters#nasm#nasm#Handle',
\})

View File

@ -2,7 +2,7 @@
" Description: A language server for OCaml " Description: A language server for OCaml
call ale#Set('ocaml_ols_executable', 'ocaml-language-server') call ale#Set('ocaml_ols_executable', 'ocaml-language-server')
call ale#Set('ocaml_ols_use_global', 0) call ale#Set('ocaml_ols_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#linter#Define('ocaml', { call ale#linter#Define('ocaml', {
\ 'name': 'ols', \ 'name': 'ols',

View File

@ -18,9 +18,9 @@ function! ale_linters#perl#perlcritic#GetExecutable(buffer) abort
endfunction endfunction
function! ale_linters#perl#perlcritic#GetProfile(buffer) abort function! ale_linters#perl#perlcritic#GetProfile(buffer) abort
" first see if we've been overridden " first see if we've been overridden
let l:profile = ale#Var(a:buffer, 'perl_perlcritic_profile') let l:profile = ale#Var(a:buffer, 'perl_perlcritic_profile')
if l:profile is? '' if l:profile is? ''
return '' return ''
endif endif
@ -31,6 +31,7 @@ endfunction
function! ale_linters#perl#perlcritic#GetCommand(buffer) abort function! ale_linters#perl#perlcritic#GetCommand(buffer) abort
let l:critic_verbosity = '%l:%c %m\n' let l:critic_verbosity = '%l:%c %m\n'
if ale#Var(a:buffer, 'perl_perlcritic_showrules') if ale#Var(a:buffer, 'perl_perlcritic_showrules')
let l:critic_verbosity = '%l:%c %m [%p]\n' let l:critic_verbosity = '%l:%c %m [%p]\n'
endif endif
@ -38,17 +39,11 @@ function! ale_linters#perl#perlcritic#GetCommand(buffer) abort
let l:profile = ale_linters#perl#perlcritic#GetProfile(a:buffer) let l:profile = ale_linters#perl#perlcritic#GetProfile(a:buffer)
let l:options = ale#Var(a:buffer, 'perl_perlcritic_options') let l:options = ale#Var(a:buffer, 'perl_perlcritic_options')
let l:command = ale#Escape(ale_linters#perl#perlcritic#GetExecutable(a:buffer)) return ale#Escape(ale_linters#perl#perlcritic#GetExecutable(a:buffer))
\ . " --verbose '". l:critic_verbosity . "' --nocolor" \ . ' --verbose ' . ale#Escape(l:critic_verbosity)
\ . ' --nocolor'
if l:profile isnot? '' \ . (!empty(l:profile) ? ' --profile ' . ale#Escape(l:profile) : '')
let l:command .= ' --profile ' . ale#Escape(l:profile) \ . (!empty(l:options) ? ' ' . l:options : '')
endif
if l:options isnot? ''
let l:command .= ' ' . l:options
endif
return l:command
endfunction endfunction

View File

@ -2,7 +2,7 @@
" Description: PHP Language server integration for ALE " Description: PHP Language server integration for ALE
call ale#Set('php_langserver_executable', 'php-language-server.php') call ale#Set('php_langserver_executable', 'php-language-server.php')
call ale#Set('php_langserver_use_global', 0) call ale#Set('php_langserver_use_global', get(g:, 'ale_use_global_executables', 0))
function! ale_linters#php#langserver#GetExecutable(buffer) abort function! ale_linters#php#langserver#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'php_langserver', [ return ale#node#FindExecutable(a:buffer, 'php_langserver', [
@ -14,10 +14,6 @@ function! ale_linters#php#langserver#GetCommand(buffer) abort
return 'php ' . ale#Escape(ale_linters#php#langserver#GetExecutable(a:buffer)) return 'php ' . ale#Escape(ale_linters#php#langserver#GetExecutable(a:buffer))
endfunction endfunction
function! ale_linters#php#langserver#GetLanguage(buffer) abort
return 'php'
endfunction
function! ale_linters#php#langserver#GetProjectRoot(buffer) abort function! ale_linters#php#langserver#GetProjectRoot(buffer) abort
let l:git_path = ale#path#FindNearestDirectory(a:buffer, '.git') let l:git_path = ale#path#FindNearestDirectory(a:buffer, '.git')
@ -29,6 +25,6 @@ call ale#linter#Define('php', {
\ 'lsp': 'stdio', \ 'lsp': 'stdio',
\ 'executable_callback': 'ale_linters#php#langserver#GetExecutable', \ 'executable_callback': 'ale_linters#php#langserver#GetExecutable',
\ 'command_callback': 'ale_linters#php#langserver#GetCommand', \ 'command_callback': 'ale_linters#php#langserver#GetCommand',
\ 'language_callback': 'ale_linters#php#langserver#GetLanguage', \ 'language': 'php',
\ 'project_root_callback': 'ale_linters#php#langserver#GetProjectRoot', \ 'project_root_callback': 'ale_linters#php#langserver#GetProjectRoot',
\}) \})

View File

@ -1,28 +1,65 @@
" Author: diegoholiveira <https://github.com/diegoholiveira> " Author: diegoholiveira <https://github.com/diegoholiveira>, haginaga <https://github.com/haginaga>
" Description: static analyzer for PHP " Description: static analyzer for PHP
" Define the minimum severity " Define the minimum severity
let g:ale_php_phan_minimum_severity = get(g:, 'ale_php_phan_minimum_severity', 0) let g:ale_php_phan_minimum_severity = get(g:, 'ale_php_phan_minimum_severity', 0)
let g:ale_php_phan_executable = get(g:, 'ale_php_phan_executable', 'phan')
let g:ale_php_phan_use_client = get(g:, 'ale_php_phan_use_client', 0)
function! ale_linters#php#phan#GetExecutable(buffer) abort
let l:executable = ale#Var(a:buffer, 'php_phan_executable')
if ale#Var(a:buffer, 'php_phan_use_client') == 1 && l:executable is# 'phan'
let l:executable = 'phan_client'
endif
return l:executable
endfunction
function! ale_linters#php#phan#GetCommand(buffer) abort function! ale_linters#php#phan#GetCommand(buffer) abort
return 'phan -y ' if ale#Var(a:buffer, 'php_phan_use_client') == 1
\ . ale#Var(a:buffer, 'php_phan_minimum_severity') let l:args = '-l '
\ . ' %s' \ . ' %s'
else
let l:args = '-y '
\ . ale#Var(a:buffer, 'php_phan_minimum_severity')
\ . ' %s'
endif
let l:executable = ale_linters#php#phan#GetExecutable(a:buffer)
return ale#Escape(l:executable) . ' ' . l:args
endfunction endfunction
function! ale_linters#php#phan#Handle(buffer, lines) abort function! ale_linters#php#phan#Handle(buffer, lines) abort
" Matches against lines like the following: " Matches against lines like the following:
" if ale#Var(a:buffer, 'php_phan_use_client') == 1
" /path/to/some-filename.php:18 ERRORTYPE message " Phan error: ERRORTYPE: message in /path/to/some-filename.php on line nnn
let l:pattern = '^.*:\(\d\+\)\s\(\w\+\)\s\(.\+\)$' let l:pattern = '^Phan error: \(\w\+\): \(.\+\) in \(.\+\) on line \(\d\+\)$'
else
" /path/to/some-filename.php:18 ERRORTYPE message
let l:pattern = '^.*:\(\d\+\)\s\(\w\+\)\s\(.\+\)$'
endif
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, { if ale#Var(a:buffer, 'php_phan_use_client') == 1
\ 'lnum': l:match[1] + 0, let l:dict = {
\ 'text': l:match[3], \ 'lnum': l:match[4] + 0,
\ 'type': 'W', \ 'text': l:match[2],
\}) \ 'type': 'W',
\}
else
let l:dict = {
\ 'lnum': l:match[1] + 0,
\ 'text': l:match[3],
\ 'type': 'W',
\}
endif
call add(l:output, l:dict)
endfor endfor
return l:output return l:output
@ -30,7 +67,7 @@ endfunction
call ale#linter#Define('php', { call ale#linter#Define('php', {
\ 'name': 'phan', \ 'name': 'phan',
\ 'executable': 'phan', \ 'executable_callback': 'ale_linters#php#phan#GetExecutable',
\ 'command_callback': 'ale_linters#php#phan#GetCommand', \ 'command_callback': 'ale_linters#php#phan#GetCommand',
\ 'callback': 'ale_linters#php#phan#Handle', \ 'callback': 'ale_linters#php#phan#Handle',
\}) \})

View File

@ -4,7 +4,7 @@
let g:ale_php_phpcs_standard = get(g:, 'ale_php_phpcs_standard', '') let g:ale_php_phpcs_standard = get(g:, 'ale_php_phpcs_standard', '')
call ale#Set('php_phpcs_executable', 'phpcs') call ale#Set('php_phpcs_executable', 'phpcs')
call ale#Set('php_phpcs_use_global', 0) call ale#Set('php_phpcs_use_global', get(g:, 'ale_use_global_executables', 0))
function! ale_linters#php#phpcs#GetExecutable(buffer) abort function! ale_linters#php#phpcs#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'php_phpcs', [ return ale#node#FindExecutable(a:buffer, 'php_phpcs', [

View File

@ -1,10 +1,30 @@
" Author: Cian Butler https://github.com/butlerx " Author: Cian Butler https://github.com/butlerx
" Description: msgfmt for PO files " Description: msgfmt for PO files
function! ale_linters#po#msgfmt#Handle(buffer, lines) abort
let l:results = ale#handlers#unix#HandleAsWarning(a:buffer, a:lines)
let l:index = 0
for l:item in l:results
if l:index > 0 && l:item.text =~? 'this is the location of the first definition'
let l:last_item = l:results[l:index - 1]
if l:last_item.text =~? 'duplicate message definition'
let l:last_item.text = 'duplicate of message at line ' . l:item.lnum
let l:item.text = 'first location of duplicate of message at line ' . l:last_item.lnum
endif
endif
let l:index += 1
endfor
return l:results
endfunction
call ale#linter#Define('po', { call ale#linter#Define('po', {
\ 'name': 'msgfmt', \ 'name': 'msgfmt',
\ 'executable': 'msgfmt', \ 'executable': 'msgfmt',
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'command': 'msgfmt --statistics --output-file=- %t', \ 'command': 'msgfmt --statistics --output-file=- %t',
\ 'callback': 'ale#handlers#unix#HandleAsWarning', \ 'callback': 'ale_linters#po#msgfmt#Handle',
\}) \})

View File

@ -3,7 +3,7 @@
call ale#Set('pug_puglint_options', '') call ale#Set('pug_puglint_options', '')
call ale#Set('pug_puglint_executable', 'pug-lint') call ale#Set('pug_puglint_executable', 'pug-lint')
call ale#Set('pug_puglint_use_global', 0) call ale#Set('pug_puglint_use_global', get(g:, 'ale_use_global_executables', 0))
function! ale_linters#pug#puglint#GetExecutable(buffer) abort function! ale_linters#pug#puglint#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'pug_puglint', [ return ale#node#FindExecutable(a:buffer, 'pug_puglint', [

View File

@ -4,14 +4,15 @@ function! ale_linters#puppet#puppet#Handle(buffer, lines) abort
" Matches patterns like the following: " Matches patterns like the following:
" Error: Could not parse for environment production: Syntax error at ':' at /root/puppetcode/modules/nginx/manifests/init.pp:43:12 " Error: Could not parse for environment production: Syntax error at ':' at /root/puppetcode/modules/nginx/manifests/init.pp:43:12
" Error: Could not parse for environment production: Syntax error at '='; expected '}' at /root/puppetcode/modules/pancakes/manifests/init.pp:5" " Error: Could not parse for environment production: Syntax error at '='; expected '}' at /root/puppetcode/modules/pancakes/manifests/init.pp:5"
" Error: Could not parse for environment production: Syntax error at 'parameter1' (file: /tmp/modules/mariadb/manifests/slave.pp, line: 4, column: 5)
let l:pattern = '^Error: .*: \(.\+\) at .\+\.pp:\(\d\+\):\=\(\d*\)' let l:pattern = '^Error: .*: \(.\+\) \((file:\|at\) .\+\.pp\(, line: \|:\)\(\d\+\)\(, column: \|:\)\=\(\d*\)'
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, { call add(l:output, {
\ 'lnum': l:match[2] + 0, \ 'lnum': l:match[4] + 0,
\ 'col': l:match[3] + 0, \ 'col': l:match[6] + 0,
\ 'text': l:match[1], \ 'text': l:match[1],
\}) \})
endfor endfor

View File

@ -1,14 +1,15 @@
" Author: w0rp <devw0rp@gmail.com> " Author: w0rp <devw0rp@gmail.com>
" Description: flake8 for python files " Description: flake8 for python files
let g:ale_python_flake8_executable = " remove in 2.0
\ get(g:, 'ale_python_flake8_executable', 'flake8')
" Support an old setting as a fallback. " Support an old setting as a fallback.
let s:deprecation_warning_echoed = 0
let s:default_options = get(g:, 'ale_python_flake8_args', '') let s:default_options = get(g:, 'ale_python_flake8_args', '')
let g:ale_python_flake8_options =
\ get(g:, 'ale_python_flake8_options', s:default_options) call ale#Set('python_flake8_executable', 'flake8')
let g:ale_python_flake8_use_global = get(g:, 'ale_python_flake8_use_global', 0) call ale#Set('python_flake8_options', s:default_options)
call ale#Set('python_flake8_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('python_flake8_change_directory', 1)
function! s:UsingModule(buffer) abort function! s:UsingModule(buffer) abort
return ale#Var(a:buffer, 'python_flake8_options') =~# ' *-m flake8' return ale#Var(a:buffer, 'python_flake8_options') =~# ' *-m flake8'
@ -39,9 +40,22 @@ function! ale_linters#python#flake8#VersionCheck(buffer) abort
endfunction endfunction
function! ale_linters#python#flake8#GetCommand(buffer, version_output) abort function! ale_linters#python#flake8#GetCommand(buffer, version_output) abort
" remove in 2.0
if exists('g:ale_python_flake8_args') && !s:deprecation_warning_echoed
execute 'echom ''Rename your g:ale_python_flake8_args setting to g:ale_python_flake8_options instead. Support for this will removed in ALE 2.0.'''
let s:deprecation_warning_echoed = 1
endif
let l:cd_string = ale#Var(a:buffer, 'python_flake8_change_directory')
\ ? ale#path#BufferCdString(a:buffer)
\ : ''
let l:executable = ale_linters#python#flake8#GetExecutable(a:buffer) let l:executable = ale_linters#python#flake8#GetExecutable(a:buffer)
let l:version = ale#semver#GetVersion(l:executable, a:version_output) let l:version = ale#semver#GetVersion(l:executable, a:version_output)
let l:exec_args = l:executable =~? 'pipenv$'
\ ? ' run flake8'
\ : ''
" Only include the --stdin-display-name argument if we can parse the " Only include the --stdin-display-name argument if we can parse the
" flake8 version, and it is recent enough to support it. " flake8 version, and it is recent enough to support it.
let l:display_name_args = ale#semver#GTE(l:version, [3, 0, 0]) let l:display_name_args = ale#semver#GTE(l:version, [3, 0, 0])
@ -50,7 +64,8 @@ function! ale_linters#python#flake8#GetCommand(buffer, version_output) abort
let l:options = ale#Var(a:buffer, 'python_flake8_options') let l:options = ale#Var(a:buffer, 'python_flake8_options')
return ale#Escape(l:executable) return l:cd_string
\ . ale#Escape(l:executable) . l:exec_args
\ . (!empty(l:options) ? ' ' . l:options : '') \ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' --format=default' \ . ' --format=default'
\ . l:display_name_args . ' -' \ . l:display_name_args . ' -'

View File

@ -4,7 +4,7 @@
call ale#Set('python_mypy_executable', 'mypy') call ale#Set('python_mypy_executable', 'mypy')
call ale#Set('python_mypy_ignore_invalid_syntax', 0) call ale#Set('python_mypy_ignore_invalid_syntax', 0)
call ale#Set('python_mypy_options', '') call ale#Set('python_mypy_options', '')
call ale#Set('python_mypy_use_global', 0) call ale#Set('python_mypy_use_global', get(g:, 'ale_use_global_executables', 0))
function! ale_linters#python#mypy#GetExecutable(buffer) abort function! ale_linters#python#mypy#GetExecutable(buffer) abort
return ale#python#FindExecutable(a:buffer, 'python_mypy', ['mypy']) return ale#python#FindExecutable(a:buffer, 'python_mypy', ['mypy'])
@ -23,10 +23,14 @@ function! ale_linters#python#mypy#GetCommand(buffer) abort
let l:dir = s:GetDir(a:buffer) let l:dir = s:GetDir(a:buffer)
let l:executable = ale_linters#python#mypy#GetExecutable(a:buffer) let l:executable = ale_linters#python#mypy#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv$'
\ ? ' run mypy'
\ : ''
" We have to always switch to an explicit directory for a command so " We have to always switch to an explicit directory for a command so
" we can know with certainty the base path for the 'filename' keys below. " we can know with certainty the base path for the 'filename' keys below.
return ale#path#CdString(l:dir) return ale#path#CdString(l:dir)
\ . ale#Escape(l:executable) \ . ale#Escape(l:executable) . l:exec_args
\ . ' --show-column-numbers ' \ . ' --show-column-numbers '
\ . ale#Var(a:buffer, 'python_mypy_options') \ . ale#Var(a:buffer, 'python_mypy_options')
\ . ' --shadow-file %s %t %s' \ . ' --shadow-file %s %t %s'

View File

@ -7,14 +7,21 @@ let g:ale_python_prospector_executable =
let g:ale_python_prospector_options = let g:ale_python_prospector_options =
\ get(g:, 'ale_python_prospector_options', '') \ get(g:, 'ale_python_prospector_options', '')
let g:ale_python_prospector_use_global = get(g:, 'ale_python_prospector_use_global', 0) let g:ale_python_prospector_use_global = get(g:, 'ale_python_prospector_use_global', get(g:, 'ale_use_global_executables', 0))
function! ale_linters#python#prospector#GetExecutable(buffer) abort function! ale_linters#python#prospector#GetExecutable(buffer) abort
return ale#python#FindExecutable(a:buffer, 'python_prospector', ['prospector']) return ale#python#FindExecutable(a:buffer, 'python_prospector', ['prospector'])
endfunction endfunction
function! ale_linters#python#prospector#GetCommand(buffer) abort function! ale_linters#python#prospector#GetCommand(buffer) abort
return ale#Escape(ale_linters#python#prospector#GetExecutable(a:buffer)) let l:executable = ale_linters#python#prospector#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv$'
\ ? ' run prospector'
\ : ''
return ale#Escape(l:executable)
\ . l:exec_args
\ . ' ' . ale#Var(a:buffer, 'python_prospector_options') \ . ' ' . ale#Var(a:buffer, 'python_prospector_options')
\ . ' --messages-only --absolute-paths --zero-exit --output-format json' \ . ' --messages-only --absolute-paths --zero-exit --output-format json'
\ . ' %s' \ . ' %s'

View File

@ -3,14 +3,20 @@
call ale#Set('python_pycodestyle_executable', 'pycodestyle') call ale#Set('python_pycodestyle_executable', 'pycodestyle')
call ale#Set('python_pycodestyle_options', '') call ale#Set('python_pycodestyle_options', '')
call ale#Set('python_pycodestyle_use_global', 0) call ale#Set('python_pycodestyle_use_global', get(g:, 'ale_use_global_executables', 0))
function! ale_linters#python#pycodestyle#GetExecutable(buffer) abort function! ale_linters#python#pycodestyle#GetExecutable(buffer) abort
return ale#python#FindExecutable(a:buffer, 'python_pycodestyle', ['pycodestyle']) return ale#python#FindExecutable(a:buffer, 'python_pycodestyle', ['pycodestyle'])
endfunction endfunction
function! ale_linters#python#pycodestyle#GetCommand(buffer) abort function! ale_linters#python#pycodestyle#GetCommand(buffer) abort
return ale#Escape(ale_linters#python#pycodestyle#GetExecutable(a:buffer)) let l:executable = ale_linters#python#pycodestyle#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv$'
\ ? ' run pycodestyle'
\ : ''
return ale#Escape(l:executable) . l:exec_args
\ . ' ' \ . ' '
\ . ale#Var(a:buffer, 'python_pycodestyle_options') \ . ale#Var(a:buffer, 'python_pycodestyle_options')
\ . ' -' \ . ' -'

View File

@ -2,7 +2,7 @@
" Description: pyflakes for python files " Description: pyflakes for python files
call ale#Set('python_pyflakes_executable', 'pyflakes') call ale#Set('python_pyflakes_executable', 'pyflakes')
call ale#Set('python_pyflakes_use_global', 0) call ale#Set('python_pyflakes_use_global', get(g:, 'ale_use_global_executables', 0))
function! ale_linters#python#pyflakes#GetExecutable(buffer) abort function! ale_linters#python#pyflakes#GetExecutable(buffer) abort
return ale#python#FindExecutable(a:buffer, 'python_pyflakes', ['pyflakes']) return ale#python#FindExecutable(a:buffer, 'python_pyflakes', ['pyflakes'])
@ -11,7 +11,13 @@ endfunction
function! ale_linters#python#pyflakes#GetCommand(buffer) abort function! ale_linters#python#pyflakes#GetCommand(buffer) abort
let l:executable = ale_linters#python#pyflakes#GetExecutable(a:buffer) let l:executable = ale_linters#python#pyflakes#GetExecutable(a:buffer)
return ale#Escape(l:executable) . ' %t' let l:exec_args = l:executable =~? 'pipenv$'
\ ? ' run pyflakes'
\ : ''
return ale#Escape(l:executable)
\ . l:exec_args
\ . ' %t'
endfunction endfunction
function! ale_linters#python#pyflakes#Handle(buffer, lines) abort function! ale_linters#python#pyflakes#Handle(buffer, lines) abort

View File

@ -1,20 +1,28 @@
" Author: keith <k@keith.so> " Author: keith <k@keith.so>
" Description: pylint for python files " Description: pylint for python files
let g:ale_python_pylint_executable = call ale#Set('python_pylint_executable', 'pylint')
\ get(g:, 'ale_python_pylint_executable', 'pylint') call ale#Set('python_pylint_options', '')
call ale#Set('python_pylint_use_global', get(g:, 'ale_use_global_executables', 0))
let g:ale_python_pylint_options = call ale#Set('python_pylint_change_directory', 1)
\ get(g:, 'ale_python_pylint_options', '')
let g:ale_python_pylint_use_global = get(g:, 'ale_python_pylint_use_global', 0)
function! ale_linters#python#pylint#GetExecutable(buffer) abort function! ale_linters#python#pylint#GetExecutable(buffer) abort
return ale#python#FindExecutable(a:buffer, 'python_pylint', ['pylint']) return ale#python#FindExecutable(a:buffer, 'python_pylint', ['pylint'])
endfunction endfunction
function! ale_linters#python#pylint#GetCommand(buffer) abort function! ale_linters#python#pylint#GetCommand(buffer) abort
return ale#Escape(ale_linters#python#pylint#GetExecutable(a:buffer)) let l:cd_string = ale#Var(a:buffer, 'python_pylint_change_directory')
\ ? ale#path#BufferCdString(a:buffer)
\ : ''
let l:executable = ale_linters#python#pylint#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv$'
\ ? ' run pylint'
\ : ''
return l:cd_string
\ . ale#Escape(l:executable) . l:exec_args
\ . ' ' . ale#Var(a:buffer, 'python_pylint_options') \ . ' ' . ale#Var(a:buffer, 'python_pylint_options')
\ . ' --output-format text --msg-template="{path}:{line}:{column}: {msg_id} ({symbol}) {msg}" --reports n' \ . ' --output-format text --msg-template="{path}:{line}:{column}: {msg_id} ({symbol}) {msg}" --reports n'
\ . ' %s' \ . ' %s'
@ -24,7 +32,7 @@ function! ale_linters#python#pylint#Handle(buffer, lines) abort
" Matches patterns like the following: " Matches patterns like the following:
" "
" test.py:4:4: W0101 (unreachable) Unreachable code " test.py:4:4: W0101 (unreachable) Unreachable code
let l:pattern = '\v^[^:]+:(\d+):(\d+): ([[:alnum:]]+) \(([^(]*)\) (.*)$' let l:pattern = '\v^[a-zA-Z]?:?[^:]+:(\d+):(\d+): ([[:alnum:]]+) \(([^(]*)\) (.*)$'
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:match in ale#util#GetMatches(a:lines, l:pattern)

View File

@ -2,7 +2,7 @@
" Description: A language server for Python " Description: A language server for Python
call ale#Set('python_pyls_executable', 'pyls') call ale#Set('python_pyls_executable', 'pyls')
call ale#Set('python_pyls_use_global', 0) call ale#Set('python_pyls_use_global', get(g:, 'ale_use_global_executables', 0))
function! ale_linters#python#pyls#GetExecutable(buffer) abort function! ale_linters#python#pyls#GetExecutable(buffer) abort
return ale#python#FindExecutable(a:buffer, 'python_pyls', ['pyls']) return ale#python#FindExecutable(a:buffer, 'python_pyls', ['pyls'])
@ -11,11 +11,11 @@ endfunction
function! ale_linters#python#pyls#GetCommand(buffer) abort function! ale_linters#python#pyls#GetCommand(buffer) abort
let l:executable = ale_linters#python#pyls#GetExecutable(a:buffer) let l:executable = ale_linters#python#pyls#GetExecutable(a:buffer)
return ale#Escape(l:executable) let l:exec_args = l:executable =~? 'pipenv$'
endfunction \ ? ' run pyls'
\ : ''
function! ale_linters#python#pyls#GetLanguage(buffer) abort return ale#Escape(l:executable) . l:exec_args
return 'python'
endfunction endfunction
call ale#linter#Define('python', { call ale#linter#Define('python', {
@ -23,6 +23,7 @@ call ale#linter#Define('python', {
\ 'lsp': 'stdio', \ 'lsp': 'stdio',
\ 'executable_callback': 'ale_linters#python#pyls#GetExecutable', \ 'executable_callback': 'ale_linters#python#pyls#GetExecutable',
\ 'command_callback': 'ale_linters#python#pyls#GetCommand', \ 'command_callback': 'ale_linters#python#pyls#GetCommand',
\ 'language_callback': 'ale_linters#python#pyls#GetLanguage', \ 'language': 'python',
\ 'project_root_callback': 'ale#python#FindProjectRoot', \ 'project_root_callback': 'ale#python#FindProjectRoot',
\ 'completion_filter': 'ale#completion#python#CompletionItemFilter',
\}) \})

View File

@ -0,0 +1,40 @@
" Author: pylipp (www.github.com/pylipp)
" Description: qmlfmt for QML files
let g:ale_qml_qmlfmt_executable = get(g:, 'ale_qml_qmlfmt_executable', 'qmlfmt')
function! ale_linters#qml#qmlfmt#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'qml_qmlfmt_executable')
endfunction
function! ale_linters#qml#qmlfmt#GetCommand(buffer) abort
return ale#Escape(ale_linters#qml#qmlfmt#GetExecutable(a:buffer))
\ . ' -e'
endfunction
" Find lines like
" Error:11:1: Expected token `}'
function! ale_linters#qml#qmlfmt#Handle(buffer, lines) abort
let l:pattern = '\v^(Error|Warning):(\d+):(\d+): (.+)$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
let l:item = {
\ 'lnum': l:match[2] + 0,
\ 'col': l:match[3] + 0,
\ 'text': l:match[4],
\ 'type': l:match[1] is# 'Warning' ? 'W' : 'E',
\}
call add(l:output, l:item)
endfor
return l:output
endfunction
call ale#linter#Define('qml', {
\ 'name': 'qmlfmt',
\ 'output_stream': 'stderr',
\ 'executable_callback': 'ale_linters#qml#qmlfmt#GetExecutable',
\ 'command_callback': 'ale_linters#qml#qmlfmt#GetCommand',
\ 'callback': 'ale_linters#qml#qmlfmt#Handle',
\})

View File

@ -22,7 +22,7 @@ function! ale_linters#r#lintr#GetCommand(buffer) abort
\ . l:lint_cmd \ . l:lint_cmd
return ale#path#BufferCdString(a:buffer) return ale#path#BufferCdString(a:buffer)
\ . 'Rscript -e ' \ . 'Rscript --vanilla -e '
\ . ale#Escape(l:cmd_string) . ' %t' \ . ale#Escape(l:cmd_string) . ' %t'
endfunction endfunction

View File

@ -2,7 +2,7 @@
" Description: A language server for Reason " Description: A language server for Reason
call ale#Set('reason_ols_executable', 'ocaml-language-server') call ale#Set('reason_ols_executable', 'ocaml-language-server')
call ale#Set('reason_ols_use_global', 0) call ale#Set('reason_ols_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#linter#Define('reason', { call ale#linter#Define('reason', {
\ 'name': 'ols', \ 'name': 'ols',

View File

@ -4,6 +4,8 @@
call ale#Set('rust_cargo_use_check', 1) call ale#Set('rust_cargo_use_check', 1)
call ale#Set('rust_cargo_check_all_targets', 0) call ale#Set('rust_cargo_check_all_targets', 0)
call ale#Set('rust_cargo_check_examples', 0)
call ale#Set('rust_cargo_check_tests', 0)
call ale#Set('rust_cargo_default_feature_behavior', 'default') call ale#Set('rust_cargo_default_feature_behavior', 'default')
call ale#Set('rust_cargo_include_features', '') call ale#Set('rust_cargo_include_features', '')
@ -31,6 +33,12 @@ function! ale_linters#rust#cargo#GetCommand(buffer, version_output) abort
let l:use_all_targets = l:use_check let l:use_all_targets = l:use_check
\ && ale#Var(a:buffer, 'rust_cargo_check_all_targets') \ && ale#Var(a:buffer, 'rust_cargo_check_all_targets')
\ && ale#semver#GTE(l:version, [0, 22, 0]) \ && ale#semver#GTE(l:version, [0, 22, 0])
let l:use_examples = l:use_check
\ && ale#Var(a:buffer, 'rust_cargo_check_examples')
\ && ale#semver#GTE(l:version, [0, 22, 0])
let l:use_tests = l:use_check
\ && ale#Var(a:buffer, 'rust_cargo_check_tests')
\ && ale#semver#GTE(l:version, [0, 22, 0])
let l:include_features = ale#Var(a:buffer, 'rust_cargo_include_features') let l:include_features = ale#Var(a:buffer, 'rust_cargo_include_features')
if !empty(l:include_features) if !empty(l:include_features)
@ -50,6 +58,8 @@ function! ale_linters#rust#cargo#GetCommand(buffer, version_output) abort
return 'cargo ' return 'cargo '
\ . (l:use_check ? 'check' : 'build') \ . (l:use_check ? 'check' : 'build')
\ . (l:use_all_targets ? ' --all-targets' : '') \ . (l:use_all_targets ? ' --all-targets' : '')
\ . (l:use_examples ? ' --examples' : '')
\ . (l:use_tests ? ' --tests' : '')
\ . ' --frozen --message-format=json -q' \ . ' --frozen --message-format=json -q'
\ . l:default_feature \ . l:default_feature
\ . l:include_features \ . l:include_features

View File

@ -12,12 +12,11 @@ function! ale_linters#rust#rls#GetCommand(buffer) abort
let l:executable = ale_linters#rust#rls#GetExecutable(a:buffer) let l:executable = ale_linters#rust#rls#GetExecutable(a:buffer)
let l:toolchain = ale#Var(a:buffer, 'rust_rls_toolchain') let l:toolchain = ale#Var(a:buffer, 'rust_rls_toolchain')
return ale#Escape(l:executable) if empty(l:toolchain)
\ . ' +' . ale#Escape(l:toolchain) return ale#Escape(l:executable)
endfunction else
return ale#Escape(l:executable) . ' +' . ale#Escape(l:toolchain)
function! ale_linters#rust#rls#GetLanguage(buffer) abort endif
return 'rust'
endfunction endfunction
function! ale_linters#rust#rls#GetProjectRoot(buffer) abort function! ale_linters#rust#rls#GetProjectRoot(buffer) abort
@ -31,6 +30,6 @@ call ale#linter#Define('rust', {
\ 'lsp': 'stdio', \ 'lsp': 'stdio',
\ 'executable_callback': 'ale_linters#rust#rls#GetExecutable', \ 'executable_callback': 'ale_linters#rust#rls#GetExecutable',
\ 'command_callback': 'ale_linters#rust#rls#GetCommand', \ 'command_callback': 'ale_linters#rust#rls#GetCommand',
\ 'language_callback': 'ale_linters#rust#rls#GetLanguage', \ 'language': 'rust',
\ 'project_root_callback': 'ale_linters#rust#rls#GetProjectRoot', \ 'project_root_callback': 'ale_linters#rust#rls#GetProjectRoot',
\}) \})

View File

@ -1,8 +1,9 @@
" Author: KabbAmine - https://github.com/KabbAmine " Author: KabbAmine - https://github.com/KabbAmine,
" Ben Falconer <ben@falconers.me.uk>
call ale#linter#Define('sass', { call ale#linter#Define('sass', {
\ 'name': 'sasslint', \ 'name': 'sasslint',
\ 'executable': 'sass-lint', \ 'executable': 'sass-lint',
\ 'command': 'sass-lint -v -q -f compact %t', \ 'command_callback': 'ale#handlers#sasslint#GetCommand',
\ 'callback': 'ale#handlers#css#HandleCSSLintFormat', \ 'callback': 'ale#handlers#css#HandleCSSLintFormat',
\}) \})

View File

@ -1,7 +1,7 @@
" Author: diartyz <diartyz@gmail.com> " Author: diartyz <diartyz@gmail.com>
call ale#Set('sass_stylelint_executable', 'stylelint') call ale#Set('sass_stylelint_executable', 'stylelint')
call ale#Set('sass_stylelint_use_global', 0) call ale#Set('sass_stylelint_use_global', get(g:, 'ale_use_global_executables', 0))
function! ale_linters#sass#stylelint#GetExecutable(buffer) abort function! ale_linters#sass#stylelint#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'sass_stylelint', [ return ale#node#FindExecutable(a:buffer, 'sass_stylelint', [

View File

@ -0,0 +1,29 @@
" Author: Nils Leuzinger - https://github.com/PawkyPenguin
" Description: Basic scala support using fsc
"
function! ale_linters#scala#fsc#GetExecutable(buffer) abort
if index(split(getbufvar(a:buffer, '&filetype'), '\.'), 'sbt') >= 0
" Don't check sbt files
return ''
endif
return 'fsc'
endfunction
function! ale_linters#scala#fsc#GetCommand(buffer) abort
let l:executable = ale_linters#scala#fsc#GetExecutable(a:buffer)
if empty(l:executable)
return ''
endif
return ale#Escape(l:executable) . ' -Ystop-after:parser %t'
endfunction
call ale#linter#Define('scala', {
\ 'name': 'fsc',
\ 'executable_callback': 'ale_linters#scala#fsc#GetExecutable',
\ 'command_callback': 'ale_linters#scala#fsc#GetCommand',
\ 'callback': 'ale#handlers#scala#HandleScalacLintFormat',
\ 'output_stream': 'stderr',
\})

View File

@ -4,7 +4,7 @@
function! ale_linters#scala#scalac#GetExecutable(buffer) abort function! ale_linters#scala#scalac#GetExecutable(buffer) abort
if index(split(getbufvar(a:buffer, '&filetype'), '\.'), 'sbt') >= 0 if index(split(getbufvar(a:buffer, '&filetype'), '\.'), 'sbt') >= 0
" Don't check sbt files with scalac. " Don't check sbt files
return '' return ''
endif endif
@ -21,45 +21,10 @@ function! ale_linters#scala#scalac#GetCommand(buffer) abort
return ale#Escape(l:executable) . ' -Ystop-after:parser %t' return ale#Escape(l:executable) . ' -Ystop-after:parser %t'
endfunction endfunction
function! ale_linters#scala#scalac#Handle(buffer, lines) abort
" Matches patterns line the following:
"
" /var/folders/5q/20rgxx3x1s34g3m14n5bq0x80000gn/T/vv6pSsy/0:26: error: expected class or object definition
let l:pattern = '^.\+:\(\d\+\): \(\w\+\): \(.\+\)'
let l:output = []
let l:ln = 0
for l:line in a:lines
let l:ln = l:ln + 1
let l:match = matchlist(l:line, l:pattern)
if len(l:match) == 0
continue
endif
let l:text = l:match[3]
let l:type = l:match[2] is# 'error' ? 'E' : 'W'
let l:col = 0
if l:ln + 1 < len(a:lines)
let l:col = stridx(a:lines[l:ln + 1], '^')
endif
call add(l:output, {
\ 'lnum': l:match[1] + 0,
\ 'col': l:col + 1,
\ 'text': l:text,
\ 'type': l:type,
\})
endfor
return l:output
endfunction
call ale#linter#Define('scala', { call ale#linter#Define('scala', {
\ 'name': 'scalac', \ 'name': 'scalac',
\ 'executable_callback': 'ale_linters#scala#scalac#GetExecutable', \ 'executable_callback': 'ale_linters#scala#scalac#GetExecutable',
\ 'command_callback': 'ale_linters#scala#scalac#GetCommand', \ 'command_callback': 'ale_linters#scala#scalac#GetCommand',
\ 'callback': 'ale_linters#scala#scalac#Handle', \ 'callback': 'ale#handlers#scala#HandleScalacLintFormat',
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\}) \})

View File

@ -1,8 +1,18 @@
" Author: KabbAmine - https://github.com/KabbAmine " Author: KabbAmine - https://github.com/KabbAmine, Ben Falconer
" <ben@falconers.me.uk>
function! ale_linters#scss#sasslint#GetCommand(buffer) abort
return ale#path#BufferCdString(a:buffer)
\ . ale#Escape('sass-lint')
\ . ' -v'
\ . ' -q'
\ . ' -f compact'
\ . ' %t'
endfunction
call ale#linter#Define('scss', { call ale#linter#Define('scss', {
\ 'name': 'sasslint', \ 'name': 'sasslint',
\ 'executable': 'sass-lint', \ 'executable': 'sass-lint',
\ 'command': 'sass-lint -v -q -f compact %t', \ 'command_callback': 'ale_linters#scss#sasslint#GetCommand',
\ 'callback': 'ale#handlers#css#HandleCSSLintFormat', \ 'callback': 'ale#handlers#css#HandleCSSLintFormat',
\}) \})

View File

@ -1,7 +1,7 @@
" Author: diartyz <diartyz@gmail.com> " Author: diartyz <diartyz@gmail.com>
call ale#Set('scss_stylelint_executable', 'stylelint') call ale#Set('scss_stylelint_executable', 'stylelint')
call ale#Set('scss_stylelint_use_global', 0) call ale#Set('scss_stylelint_use_global', get(g:, 'ale_use_global_executables', 0))
function! ale_linters#scss#stylelint#GetExecutable(buffer) abort function! ale_linters#scss#stylelint#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'scss_stylelint', [ return ale#node#FindExecutable(a:buffer, 'scss_stylelint', [

View File

@ -2,7 +2,7 @@
call ale#Set('stylus_stylelint_executable', 'stylelint') call ale#Set('stylus_stylelint_executable', 'stylelint')
call ale#Set('stylus_stylelint_options', '') call ale#Set('stylus_stylelint_options', '')
call ale#Set('stylus_stylelint_use_global', 0) call ale#Set('stylus_stylelint_use_global', get(g:, 'ale_use_global_executables', 0))
function! ale_linters#stylus#stylelint#GetExecutable(buffer) abort function! ale_linters#stylus#stylelint#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'stylus_stylelint', [ return ale#node#FindExecutable(a:buffer, 'stylus_stylelint', [

View File

@ -4,7 +4,7 @@
call ale#Set('typescript_tslint_executable', 'tslint') call ale#Set('typescript_tslint_executable', 'tslint')
call ale#Set('typescript_tslint_config_path', '') call ale#Set('typescript_tslint_config_path', '')
call ale#Set('typescript_tslint_rules_dir', '') call ale#Set('typescript_tslint_rules_dir', '')
call ale#Set('typescript_tslint_use_global', 0) call ale#Set('typescript_tslint_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('typescript_tslint_ignore_empty_files', 0) call ale#Set('typescript_tslint_ignore_empty_files', 0)
function! ale_linters#typescript#tslint#GetExecutable(buffer) abort function! ale_linters#typescript#tslint#GetExecutable(buffer) abort

View File

@ -3,17 +3,13 @@
call ale#Set('typescript_tsserver_executable', 'tsserver') call ale#Set('typescript_tsserver_executable', 'tsserver')
call ale#Set('typescript_tsserver_config_path', '') call ale#Set('typescript_tsserver_config_path', '')
call ale#Set('typescript_tsserver_use_global', 0) call ale#Set('typescript_tsserver_use_global', get(g:, 'ale_use_global_executables', 0))
" These functions need to be defined just to comply with the API for LSP. " These functions need to be defined just to comply with the API for LSP.
function! ale_linters#typescript#tsserver#GetProjectRoot(buffer) abort function! ale_linters#typescript#tsserver#GetProjectRoot(buffer) abort
return '' return ''
endfunction endfunction
function! ale_linters#typescript#tsserver#GetLanguage(buffer) abort
return ''
endfunction
function! ale_linters#typescript#tsserver#GetExecutable(buffer) abort function! ale_linters#typescript#tsserver#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'typescript_tsserver', [ return ale#node#FindExecutable(a:buffer, 'typescript_tsserver', [
\ 'node_modules/.bin/tsserver', \ 'node_modules/.bin/tsserver',
@ -26,5 +22,5 @@ call ale#linter#Define('typescript', {
\ 'executable_callback': 'ale_linters#typescript#tsserver#GetExecutable', \ 'executable_callback': 'ale_linters#typescript#tsserver#GetExecutable',
\ 'command_callback': 'ale_linters#typescript#tsserver#GetExecutable', \ 'command_callback': 'ale_linters#typescript#tsserver#GetExecutable',
\ 'project_root_callback': 'ale_linters#typescript#tsserver#GetProjectRoot', \ 'project_root_callback': 'ale_linters#typescript#tsserver#GetProjectRoot',
\ 'language_callback': 'ale_linters#typescript#tsserver#GetLanguage', \ 'language': '',
\}) \})

View File

@ -2,31 +2,38 @@
" Description: This file adds support for checking Vim code with Vint. " Description: This file adds support for checking Vim code with Vint.
" This flag can be used to change enable/disable style issues. " This flag can be used to change enable/disable style issues.
let g:ale_vim_vint_show_style_issues = call ale#Set('vim_vint_show_style_issues', 1)
\ get(g:, 'ale_vim_vint_show_style_issues', 1) call ale#Set('vim_vint_executable', 'vint')
let s:enable_neovim = has('nvim') ? ' --enable-neovim ' : '' let s:enable_neovim = has('nvim') ? ' --enable-neovim' : ''
let s:format = '-f "{file_path}:{line_number}:{column_number}: {severity}: {description} (see {reference})"' let s:format = '-f "{file_path}:{line_number}:{column_number}: {severity}: {description} (see {reference})"'
function! ale_linters#vim#vint#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'vim_vint_executable')
endfunction
function! ale_linters#vim#vint#VersionCommand(buffer) abort function! ale_linters#vim#vint#VersionCommand(buffer) abort
let l:executable = ale_linters#vim#vint#GetExecutable(a:buffer)
" Check the Vint version if we haven't checked it already. " Check the Vint version if we haven't checked it already.
return !ale#semver#HasVersion('vint') return !ale#semver#HasVersion(l:executable)
\ ? 'vint --version' \ ? ale#Escape(l:executable) . ' --version'
\ : '' \ : ''
endfunction endfunction
function! ale_linters#vim#vint#GetCommand(buffer, version_output) abort function! ale_linters#vim#vint#GetCommand(buffer, version_output) abort
let l:version = ale#semver#GetVersion('vint', a:version_output) let l:executable = ale_linters#vim#vint#GetExecutable(a:buffer)
let l:version = ale#semver#GetVersion(l:executable, a:version_output)
let l:can_use_no_color_flag = empty(l:version) let l:can_use_no_color_flag = empty(l:version)
\ || ale#semver#GTE(l:version, [0, 3, 7]) \ || ale#semver#GTE(l:version, [0, 3, 7])
let l:warning_flag = ale#Var(a:buffer, 'vim_vint_show_style_issues') ? '-s' : '-w' let l:warning_flag = ale#Var(a:buffer, 'vim_vint_show_style_issues') ? '-s' : '-w'
return 'vint ' return ale#Escape(l:executable)
\ . l:warning_flag . ' ' \ . ' ' . l:warning_flag
\ . (l:can_use_no_color_flag ? '--no-color ' : '') \ . (l:can_use_no_color_flag ? ' --no-color' : '')
\ . s:enable_neovim \ . s:enable_neovim
\ . s:format \ . ' ' . s:format
\ . ' %t' \ . ' %t'
endfunction endfunction
@ -58,7 +65,7 @@ endfunction
call ale#linter#Define('vim', { call ale#linter#Define('vim', {
\ 'name': 'vint', \ 'name': 'vint',
\ 'executable': 'vint', \ 'executable_callback': 'ale_linters#vim#vint#GetExecutable',
\ 'command_chain': [ \ 'command_chain': [
\ {'callback': 'ale_linters#vim#vint#VersionCommand', 'output_stream': 'stderr'}, \ {'callback': 'ale_linters#vim#vint#VersionCommand', 'output_stream': 'stderr'},
\ {'callback': 'ale_linters#vim#vint#GetCommand', 'output_stream': 'stdout'}, \ {'callback': 'ale_linters#vim#vint#GetCommand', 'output_stream': 'stdout'},

View File

@ -2,7 +2,7 @@
" Description: This file adds support for linting Swagger / OpenAPI documents using swaglint " Description: This file adds support for linting Swagger / OpenAPI documents using swaglint
call ale#Set('yaml_swaglint_executable', 'swaglint') call ale#Set('yaml_swaglint_executable', 'swaglint')
call ale#Set('yaml_swaglint_use_global', 0) call ale#Set('yaml_swaglint_use_global', get(g:, 'ale_use_global_executables', 0))
function! ale_linters#yaml#swaglint#GetExecutable(buffer) abort function! ale_linters#yaml#swaglint#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'yaml_swaglint', [ return ale#node#FindExecutable(a:buffer, 'yaml_swaglint', [

View File

@ -2,6 +2,11 @@
" Description: Primary code path for the plugin " Description: Primary code path for the plugin
" Manages execution of linters when requested by autocommands " Manages execution of linters when requested by autocommands
" Strings used for severity in the echoed message
let g:ale_echo_msg_error_str = get(g:, 'ale_echo_msg_error_str', 'Error')
let g:ale_echo_msg_info_str = get(g:, 'ale_echo_msg_info_str', 'Info')
let g:ale_echo_msg_warning_str = get(g:, 'ale_echo_msg_warning_str', 'Warning')
let s:lint_timer = -1 let s:lint_timer = -1
let s:queued_buffer_number = -1 let s:queued_buffer_number = -1
let s:should_lint_file_for_buffer = {} let s:should_lint_file_for_buffer = {}
@ -32,8 +37,8 @@ function! ale#CallWithCooldown(timestamp_key, func, arglist) abort
endfunction endfunction
" Return 1 if a file is too large for ALE to handle. " Return 1 if a file is too large for ALE to handle.
function! ale#FileTooLarge() abort function! ale#FileTooLarge(buffer) abort
let l:max = ale#Var(bufnr(''), 'maximum_file_size') let l:max = getbufvar(a:buffer, 'ale_maximum_file_size', get(g:, 'ale_maximum_file_size', 0))
return l:max > 0 ? (line2byte(line('$') + 1) > l:max) : 0 return l:max > 0 ? (line2byte(line('$') + 1) > l:max) : 0
endfunction endfunction
@ -46,39 +51,47 @@ function! ale#ShouldDoNothing(buffer) abort
" The checks are split into separate if statements to make it possible to " The checks are split into separate if statements to make it possible to
" profile each check individually with Vim's profiling tools. " profile each check individually with Vim's profiling tools.
" Do nothing if ALE is disabled.
if !getbufvar(a:buffer, 'ale_enabled', get(g:, 'ale_enabled', 0))
return 1
endif
" Don't perform any checks when newer NeoVim versions are exiting. " Don't perform any checks when newer NeoVim versions are exiting.
if get(v:, 'exiting', v:null) isnot v:null if get(v:, 'exiting', v:null) isnot v:null
return 1 return 1
endif endif
" Do nothing for blacklisted files let l:filetype = getbufvar(a:buffer, '&filetype')
if index(g:ale_filetype_blacklist, getbufvar(a:buffer, '&filetype')) >= 0
" Do nothing when there's no filetype.
if l:filetype is# ''
return 1 return 1
endif endif
" Do nothing if running from command mode " Do nothing for blacklisted files.
if index(get(g:, 'ale_filetype_blacklist', []), l:filetype) >= 0
return 1
endif
" Do nothing if running from command mode.
if s:getcmdwintype_exists && !empty(getcmdwintype()) if s:getcmdwintype_exists && !empty(getcmdwintype())
return 1 return 1
endif endif
let l:filename = fnamemodify(bufname(a:buffer), ':t') let l:filename = fnamemodify(bufname(a:buffer), ':t')
" Do nothing for directories.
if l:filename is# '.' if l:filename is# '.'
return 1 return 1
endif endif
" Do nothing if running in the sandbox " Do nothing if running in the sandbox.
if ale#util#InSandbox() if ale#util#InSandbox()
return 1 return 1
endif endif
" Do nothing if ALE is disabled.
if !ale#Var(a:buffer, 'enabled')
return 1
endif
" Do nothing if the file is too large. " Do nothing if the file is too large.
if ale#FileTooLarge() if ale#FileTooLarge(a:buffer)
return 1 return 1
endif endif

View File

@ -0,0 +1,77 @@
function! ale#autocmd#InitAuGroups() abort
" This value used to be a Boolean as a Number, and is now a String.
let l:text_changed = '' . g:ale_lint_on_text_changed
augroup ALEPatternOptionsGroup
autocmd!
autocmd BufEnter,BufRead * call ale#pattern_options#SetOptions(str2nr(expand('<abuf>')))
augroup END
augroup ALERunOnTextChangedGroup
autocmd!
if g:ale_enabled
if l:text_changed is? 'always' || l:text_changed is# '1'
autocmd TextChanged,TextChangedI * call ale#Queue(g:ale_lint_delay)
elseif l:text_changed is? 'normal'
autocmd TextChanged * call ale#Queue(g:ale_lint_delay)
elseif l:text_changed is? 'insert'
autocmd TextChangedI * call ale#Queue(g:ale_lint_delay)
endif
endif
augroup END
augroup ALERunOnEnterGroup
autocmd!
if g:ale_enabled
" Handle everything that needs to happen when buffers are entered.
autocmd BufEnter * call ale#events#EnterEvent(str2nr(expand('<abuf>')))
endif
if g:ale_enabled && g:ale_lint_on_enter
autocmd BufWinEnter,BufRead * call ale#Queue(0, 'lint_file', str2nr(expand('<abuf>')))
" Track when the file is changed outside of Vim.
autocmd FileChangedShellPost * call ale#events#FileChangedEvent(str2nr(expand('<abuf>')))
endif
augroup END
augroup ALERunOnFiletypeChangeGroup
autocmd!
if g:ale_enabled && g:ale_lint_on_filetype_changed
" Only start linting if the FileType actually changes after
" opening a buffer. The FileType will fire when buffers are opened.
autocmd FileType * call ale#events#FileTypeEvent(
\ str2nr(expand('<abuf>')),
\ expand('<amatch>')
\)
endif
augroup END
augroup ALERunOnSaveGroup
autocmd!
autocmd BufWritePost * call ale#events#SaveEvent(str2nr(expand('<abuf>')))
augroup END
augroup ALERunOnInsertLeave
autocmd!
if g:ale_enabled && g:ale_lint_on_insert_leave
autocmd InsertLeave * call ale#Queue(0)
endif
augroup END
augroup ALECursorGroup
autocmd!
if g:ale_enabled && g:ale_echo_cursor
autocmd CursorMoved,CursorHold * call ale#cursor#EchoCursorWarningWithDelay()
" Look for a warning to echo as soon as we leave Insert mode.
" The script's position variable used when moving the cursor will
" not be changed here.
autocmd InsertLeave * call ale#cursor#EchoCursorWarning()
endif
augroup END
if !g:ale_enabled
augroup! ALERunOnTextChangedGroup
augroup! ALERunOnEnterGroup
augroup! ALERunOnInsertLeave
augroup! ALECursorGroup
endif
endfunction

View File

@ -12,7 +12,21 @@ function! ale#balloon#MessageForPos(bufnr, lnum, col) abort
let l:loclist = get(g:ale_buffer_info, a:bufnr, {'loclist': []}).loclist let l:loclist = get(g:ale_buffer_info, a:bufnr, {'loclist': []}).loclist
let l:index = ale#util#BinarySearch(l:loclist, a:bufnr, a:lnum, a:col) let l:index = ale#util#BinarySearch(l:loclist, a:bufnr, a:lnum, a:col)
return l:index >= 0 ? l:loclist[l:index].text : '' " Show the diagnostics message if found, 'Hover' output otherwise
if l:index >= 0
return l:loclist[l:index].text
elseif exists('*balloon_show') || getbufvar(
\ a:bufnr,
\ 'ale_set_balloons_legacy_echo',
\ get(g:, 'ale_set_balloons_legacy_echo', 0)
\)
" Request LSP/tsserver hover information, but only if this version of
" Vim supports the balloon_show function, or if we turned a legacy
" setting on.
call ale#hover#Show(a:bufnr, a:lnum, a:col, {'called_from_balloonexpr': 1})
endif
return ''
endfunction endfunction
function! ale#balloon#Expr() abort function! ale#balloon#Expr() abort
@ -20,9 +34,22 @@ function! ale#balloon#Expr() abort
endfunction endfunction
function! ale#balloon#Disable() abort function! ale#balloon#Disable() abort
set noballooneval balloonexpr= set noballooneval noballoonevalterm
set balloonexpr=
endfunction endfunction
function! ale#balloon#Enable() abort function! ale#balloon#Enable() abort
set ballooneval balloonexpr=ale#balloon#Expr() if !has('balloon_eval') && !has('balloon_eval_term')
return
endif
if has('balloon_eval')
set ballooneval
endif
if has('balloon_eval_term')
set balloonevalterm
endif
set balloonexpr=ale#balloon#Expr()
endfunction endfunction

View File

@ -1,6 +1,10 @@
" Author: w0rp <devw0rp@gmail.com> " Author: w0rp <devw0rp@gmail.com>
" Description: Completion support for LSP linters " Description: Completion support for LSP linters
let g:ale_completion_delay = get(g:, 'ale_completion_delay', 100)
let g:ale_completion_excluded_words = get(g:, 'ale_completion_excluded_words', [])
let g:ale_completion_max_suggestions = get(g:, 'ale_completion_max_suggestions', 50)
let s:timer_id = -1 let s:timer_id = -1
let s:last_done_pos = [] let s:last_done_pos = []
@ -28,6 +32,8 @@ let s:LSP_COMPLETION_REFERENCE_KIND = 18
" the insert cursor is. If one of these matches, we'll check for completions. " the insert cursor is. If one of these matches, we'll check for completions.
let s:should_complete_map = { let s:should_complete_map = {
\ '<default>': '\v[a-zA-Z$_][a-zA-Z$_0-9]*$|\.$', \ '<default>': '\v[a-zA-Z$_][a-zA-Z$_0-9]*$|\.$',
\ 'typescript': '\v[a-zA-Z$_][a-zA-Z$_0-9]*$|\.$|''$|"$',
\ 'rust': '\v[a-zA-Z$_][a-zA-Z$_0-9]*$|\.$|::$',
\} \}
" Regular expressions for finding the start column to replace with completion. " Regular expressions for finding the start column to replace with completion.
@ -38,6 +44,8 @@ let s:omni_start_map = {
" A map of exact characters for triggering LSP completions. " A map of exact characters for triggering LSP completions.
let s:trigger_character_map = { let s:trigger_character_map = {
\ '<default>': ['.'], \ '<default>': ['.'],
\ 'typescript': ['.', '''', '"'],
\ 'rust': ['.', '::'],
\} \}
function! s:GetFiletypeValue(map, filetype) abort function! s:GetFiletypeValue(map, filetype) abort
@ -74,33 +82,49 @@ function! ale#completion#GetTriggerCharacter(filetype, prefix) abort
return '' return ''
endfunction endfunction
function! ale#completion#Filter(suggestions, prefix) abort function! ale#completion#Filter(buffer, suggestions, prefix) abort
let l:excluded_words = ale#Var(a:buffer, 'completion_excluded_words')
" For completing... " For completing...
" foo. " foo.
" ^ " ^
" We need to include all of the given suggestions. " We need to include all of the given suggestions.
if a:prefix is# '.' if a:prefix is# '.'
return a:suggestions let l:filtered_suggestions = a:suggestions
else
let l:filtered_suggestions = []
" Filter suggestions down to those starting with the prefix we used for
" finding suggestions in the first place.
"
" Some completion tools will include suggestions which don't even start
" with the characters we have already typed.
for l:item in a:suggestions
" A List of String values or a List of completion item Dictionaries
" is accepted here.
let l:word = type(l:item) == type('') ? l:item : l:item.word
" Add suggestions if the suggestion starts with a case-insensitive
" match for the prefix.
if l:word[: len(a:prefix) - 1] is? a:prefix
call add(l:filtered_suggestions, l:item)
endif
endfor
endif endif
let l:filtered_suggestions = [] if !empty(l:excluded_words)
" Copy the List if needed. We don't want to modify the argument.
" Filter suggestions down to those starting with the prefix we used for " We shouldn't make a copy if we don't need to.
" finding suggestions in the first place. if l:filtered_suggestions is a:suggestions
" let l:filtered_suggestions = copy(a:suggestions)
" Some completion tools will include suggestions which don't even start
" with the characters we have already typed.
for l:item in a:suggestions
" A List of String values or a List of completion item Dictionaries
" is accepted here.
let l:word = type(l:item) == type('') ? l:item : l:item.word
" Add suggestions if the suggestion starts with a case-insensitive
" match for the prefix.
if l:word[: len(a:prefix) - 1] is? a:prefix
call add(l:filtered_suggestions, l:item)
endif endif
endfor
" Remove suggestions with words in the exclusion List.
call filter(
\ l:filtered_suggestions,
\ 'index(l:excluded_words, type(v:val) is type('''') ? v:val : v:val.word) < 0',
\)
endif
return l:filtered_suggestions return l:filtered_suggestions
endfunction endfunction
@ -178,7 +202,9 @@ function! ale#completion#ParseTSServerCompletions(response) abort
endfunction endfunction
function! ale#completion#ParseTSServerCompletionEntryDetails(response) abort function! ale#completion#ParseTSServerCompletionEntryDetails(response) abort
let l:buffer = bufnr('')
let l:results = [] let l:results = []
let l:names_with_details = []
for l:suggestion in a:response.body for l:suggestion in a:response.body
let l:displayParts = [] let l:displayParts = []
@ -212,10 +238,44 @@ function! ale#completion#ParseTSServerCompletionEntryDetails(response) abort
\}) \})
endfor endfor
let l:names = getbufvar(l:buffer, 'ale_tsserver_completion_names', [])
if !empty(l:names) && len(l:names) != len(l:results)
let l:names_with_details = map(copy(l:results), 'v:val.word')
let l:missing_names = filter(
\ copy(l:names),
\ 'index(l:names_with_details, v:val) < 0',
\)
for l:name in l:missing_names
call add(l:results, {
\ 'word': l:name,
\ 'kind': 'v',
\ 'icase': 1,
\ 'menu': '',
\ 'info': '',
\})
endfor
endif
return l:results return l:results
endfunction endfunction
function! ale#completion#NullFilter(buffer, item) abort
return 1
endfunction
function! ale#completion#ParseLSPCompletions(response) abort function! ale#completion#ParseLSPCompletions(response) abort
let l:buffer = bufnr('')
let l:info = get(b:, 'ale_completion_info', {})
let l:Filter = get(l:info, 'completion_filter', v:null)
if l:Filter is v:null
let l:Filter = function('ale#completion#NullFilter')
else
let l:Filter = ale#util#GetFunction(l:Filter)
endif
let l:item_list = [] let l:item_list = []
if type(get(a:response, 'result')) is type([]) if type(get(a:response, 'result')) is type([])
@ -228,6 +288,16 @@ function! ale#completion#ParseLSPCompletions(response) abort
let l:results = [] let l:results = []
for l:item in l:item_list for l:item in l:item_list
if !call(l:Filter, [l:buffer, l:item])
continue
endif
let l:word = matchstr(l:item.label, '\v^[^(]+')
if empty(l:word)
continue
endif
" See :help complete-items for Vim completion kinds " See :help complete-items for Vim completion kinds
if l:item.kind is s:LSP_COMPLETION_METHOD_KIND if l:item.kind is s:LSP_COMPLETION_METHOD_KIND
let l:kind = 'm' let l:kind = 'm'
@ -244,14 +314,18 @@ function! ale#completion#ParseLSPCompletions(response) abort
endif endif
call add(l:results, { call add(l:results, {
\ 'word': l:item.label, \ 'word': l:word,
\ 'kind': l:kind, \ 'kind': l:kind,
\ 'icase': 1, \ 'icase': 1,
\ 'menu': l:item.detail, \ 'menu': get(l:item, 'detail', ''),
\ 'info': l:item.documentation, \ 'info': get(l:item, 'documentation', ''),
\}) \})
endfor endfor
if has_key(l:info, 'prefix')
return ale#completion#Filter(l:buffer, l:results, l:info.prefix)
endif
return l:results return l:results
endfunction endfunction
@ -264,19 +338,25 @@ function! ale#completion#HandleTSServerResponse(conn_id, response) abort
return return
endif endif
let l:buffer = bufnr('')
let l:command = get(a:response, 'command', '') let l:command = get(a:response, 'command', '')
if l:command is# 'completions' if l:command is# 'completions'
let l:names = ale#completion#Filter( let l:names = ale#completion#Filter(
\ l:buffer,
\ ale#completion#ParseTSServerCompletions(a:response), \ ale#completion#ParseTSServerCompletions(a:response),
\ b:ale_completion_info.prefix, \ b:ale_completion_info.prefix,
\)[: g:ale_completion_max_suggestions - 1] \)[: g:ale_completion_max_suggestions - 1]
" We need to remember some names for tsserver, as it doesn't send
" details back for everything we send.
call setbufvar(l:buffer, 'ale_tsserver_completion_names', l:names)
if !empty(l:names) if !empty(l:names)
let b:ale_completion_info.request_id = ale#lsp#Send( let b:ale_completion_info.request_id = ale#lsp#Send(
\ b:ale_completion_info.conn_id, \ b:ale_completion_info.conn_id,
\ ale#lsp#tsserver_message#CompletionEntryDetails( \ ale#lsp#tsserver_message#CompletionEntryDetails(
\ bufnr(''), \ l:buffer,
\ b:ale_completion_info.line, \ b:ale_completion_info.line,
\ b:ale_completion_info.column, \ b:ale_completion_info.column,
\ l:names, \ l:names,
@ -349,6 +429,10 @@ function! s:GetLSPCompletions(linter) abort
if l:request_id if l:request_id
let b:ale_completion_info.conn_id = l:id let b:ale_completion_info.conn_id = l:id
let b:ale_completion_info.request_id = l:request_id let b:ale_completion_info.request_id = l:request_id
if has_key(a:linter, 'completion_filter')
let b:ale_completion_info.completion_filter = a:linter.completion_filter
endif
endif endif
endfunction endfunction
@ -378,10 +462,7 @@ function! ale#completion#GetCompletions() abort
for l:linter in ale#linter#Get(&filetype) for l:linter in ale#linter#Get(&filetype)
if !empty(l:linter.lsp) if !empty(l:linter.lsp)
if l:linter.lsp is# 'tsserver' call s:GetLSPCompletions(l:linter)
\|| get(g:, 'ale_completion_experimental_lsp_support', 0)
call s:GetLSPCompletions(l:linter)
endif
endif endif
endfor endfor
endfunction endfunction

View File

@ -0,0 +1,3 @@
function! ale#completion#python#CompletionItemFilter(buffer, item) abort
return a:item.label !~# '\v^__[a-z_]+__'
endfunction

View File

@ -1,6 +1,11 @@
" Author: w0rp <devw0rp@gmail.com> " Author: w0rp <devw0rp@gmail.com>
" Description: Echoes lint message for the current line, if any " Description: Echoes lint message for the current line, if any
" Controls the milliseconds delay before echoing a message.
let g:ale_echo_delay = get(g:, 'ale_echo_delay', 10)
" A string format for the echoed message.
let g:ale_echo_msg_format = get(g:, 'ale_echo_msg_format', '%code: %%s')
let s:cursor_timer = -1 let s:cursor_timer = -1
let s:last_pos = [0, 0, 0] let s:last_pos = [0, 0, 0]

View File

@ -51,6 +51,7 @@ let s:global_variable_list = [
\ 'ale_sign_warning', \ 'ale_sign_warning',
\ 'ale_statusline_format', \ 'ale_statusline_format',
\ 'ale_type_map', \ 'ale_type_map',
\ 'ale_use_global_executables',
\ 'ale_warn_about_trailing_blank_lines', \ 'ale_warn_about_trailing_blank_lines',
\ 'ale_warn_about_trailing_whitespace', \ 'ale_warn_about_trailing_whitespace',
\] \]
@ -167,6 +168,30 @@ function! s:EchoLinterAliases(all_linters) abort
endfor endfor
endfunction endfunction
function! s:EchoLSPErrorMessages(all_linter_names) abort
let l:lsp_error_messages = get(g:, 'ale_lsp_error_messages', {})
let l:header_echoed = 0
for l:linter_name in a:all_linter_names
let l:error_list = get(l:lsp_error_messages, l:linter_name, [])
if !empty(l:error_list)
if !l:header_echoed
call s:Echo(' LSP Error Messages:')
call s:Echo('')
endif
call s:Echo('(Errors for ' . l:linter_name . ')')
for l:message in l:error_list
for l:line in split(l:message, "\n")
call s:Echo(l:line)
endfor
endfor
endif
endfor
endfunction
function! ale#debugging#Info() abort function! ale#debugging#Info() abort
let l:filetype = &filetype let l:filetype = &filetype
@ -199,6 +224,7 @@ function! ale#debugging#Info() abort
call s:Echo(' Global Variables:') call s:Echo(' Global Variables:')
call s:Echo('') call s:Echo('')
call s:EchoGlobalVariables() call s:EchoGlobalVariables()
call s:EchoLSPErrorMessages(l:all_names)
call s:Echo(' Command History:') call s:Echo(' Command History:')
call s:Echo('') call s:Echo('')
call s:EchoCommandHistory() call s:EchoCommandHistory()
@ -211,3 +237,14 @@ function! ale#debugging#InfoToClipboard() abort
call s:Echo('ALEInfo copied to your clipboard') call s:Echo('ALEInfo copied to your clipboard')
endfunction endfunction
function! ale#debugging#InfoToFile(filename) abort
let l:expanded_filename = expand(a:filename)
redir => l:output
silent call ale#debugging#Info()
redir END
call writefile(split(l:output, "\n"), l:expanded_filename)
call s:Echo('ALEInfo written to ' . l:expanded_filename)
endfunction

View File

@ -13,37 +13,21 @@ function! ale#definition#SetMap(map) abort
let s:go_to_definition_map = a:map let s:go_to_definition_map = a:map
endfunction endfunction
" This function is used so we can check the execution of commands without
" running them.
function! ale#definition#Execute(expr) abort
execute a:expr
endfunction
function! ale#definition#ClearLSPData() abort function! ale#definition#ClearLSPData() abort
let s:go_to_definition_map = {} let s:go_to_definition_map = {}
endfunction endfunction
function! ale#definition#Open(options, filename, line, column) abort
if a:options.open_in_tab
call ale#definition#Execute('tabedit ' . fnameescape(a:filename))
else
call ale#definition#Execute('edit ' . fnameescape(a:filename))
endif
call cursor(a:line, a:column)
endfunction
function! ale#definition#HandleTSServerResponse(conn_id, response) abort function! ale#definition#HandleTSServerResponse(conn_id, response) abort
if get(a:response, 'command', '') is# 'definition' if get(a:response, 'command', '') is# 'definition'
\&& has_key(s:go_to_definition_map, a:response.request_seq) \&& has_key(s:go_to_definition_map, a:response.request_seq)
let l:options = remove(s:go_to_definition_map, a:response.request_seq) let l:options = remove(s:go_to_definition_map, a:response.request_seq)
if get(a:response, 'success', v:false) is v:true if get(a:response, 'success', v:false) is v:true && !empty(a:response.body)
let l:filename = a:response.body[0].file let l:filename = a:response.body[0].file
let l:line = a:response.body[0].start.line let l:line = a:response.body[0].start.line
let l:column = a:response.body[0].start.offset let l:column = a:response.body[0].start.offset
call ale#definition#Open(l:options, l:filename, l:line, l:column) call ale#util#Open(l:filename, l:line, l:column, l:options)
endif endif
endif endif
endfunction endfunction
@ -67,7 +51,7 @@ function! ale#definition#HandleLSPResponse(conn_id, response) abort
let l:line = l:item.range.start.line + 1 let l:line = l:item.range.start.line + 1
let l:column = l:item.range.start.character let l:column = l:item.range.start.character
call ale#definition#Open(l:options, l:filename, l:line, l:column) call ale#util#Open(l:filename, l:line, l:column, l:options)
break break
endfor endfor
endif endif

View File

@ -2,6 +2,9 @@
" Description: Backend execution and job management " Description: Backend execution and job management
" Executes linters in the background, using NeoVim or Vim 8 jobs " Executes linters in the background, using NeoVim or Vim 8 jobs
" Remapping of linter problems.
let g:ale_type_map = get(g:, 'ale_type_map', {})
" Stores information for each job including: " Stores information for each job including:
" "
" linter: The linter dictionary for the job. " linter: The linter dictionary for the job.
@ -44,7 +47,7 @@ function! ale#engine#IsExecutable(buffer, executable) abort
" Cache the executable check if we found it, or if the option to cache " Cache the executable check if we found it, or if the option to cache
" failing checks is on. " failing checks is on.
if l:result || g:ale_cache_executable_check_failures if l:result || get(g:, 'ale_cache_executable_check_failures', 0)
let s:executable_cache_map[a:executable] = l:result let s:executable_cache_map[a:executable] = l:result
endif endif
@ -81,6 +84,11 @@ function! ale#engine#ClearLSPData() abort
let s:lsp_linter_map = {} let s:lsp_linter_map = {}
endfunction endfunction
" Just for tests.
function! ale#engine#SetLSPLinterMap(replacement_map) abort
let s:lsp_linter_map = a:replacement_map
endfunction
" This function is documented and part of the public API. " This function is documented and part of the public API.
" "
" Return 1 if ALE is busy checking a given buffer " Return 1 if ALE is busy checking a given buffer
@ -93,11 +101,13 @@ endfunction
" Register a temporary file to be managed with the ALE engine for " Register a temporary file to be managed with the ALE engine for
" a current job run. " a current job run.
function! ale#engine#ManageFile(buffer, filename) abort function! ale#engine#ManageFile(buffer, filename) abort
call ale#engine#InitBufferInfo(a:buffer)
call add(g:ale_buffer_info[a:buffer].temporary_file_list, a:filename) call add(g:ale_buffer_info[a:buffer].temporary_file_list, a:filename)
endfunction endfunction
" Same as the above, but manage an entire directory. " Same as the above, but manage an entire directory.
function! ale#engine#ManageDirectory(buffer, directory) abort function! ale#engine#ManageDirectory(buffer, directory) abort
call ale#engine#InitBufferInfo(a:buffer)
call add(g:ale_buffer_info[a:buffer].temporary_directory_list, a:directory) call add(g:ale_buffer_info[a:buffer].temporary_directory_list, a:directory)
endfunction endfunction
@ -270,20 +280,38 @@ function! s:HandleTSServerDiagnostics(response, error_type) abort
call ale#engine#HandleLoclist('tsserver', l:buffer, l:loclist) call ale#engine#HandleLoclist('tsserver', l:buffer, l:loclist)
endfunction endfunction
function! s:HandleLSPErrorMessage(error_message) abort function! s:HandleLSPErrorMessage(linter_name, response) abort
execute 'echoerr ''Error from LSP:''' if !g:ale_history_enabled || !g:ale_history_log_output
return
endif
for l:line in split(a:error_message, "\n") if empty(a:linter_name)
execute 'echoerr l:line' return
endfor endif
let l:message = ale#lsp#response#GetErrorMessage(a:response)
if empty(l:message)
return
endif
" This global variable is set here so we don't load the debugging.vim file
" until someone uses :ALEInfo.
let g:ale_lsp_error_messages = get(g:, 'ale_lsp_error_messages', {})
if !has_key(g:ale_lsp_error_messages, a:linter_name)
let g:ale_lsp_error_messages[a:linter_name] = []
endif
call add(g:ale_lsp_error_messages[a:linter_name], l:message)
endfunction endfunction
function! ale#engine#HandleLSPResponse(conn_id, response) abort function! ale#engine#HandleLSPResponse(conn_id, response) abort
let l:method = get(a:response, 'method', '') let l:method = get(a:response, 'method', '')
let l:linter_name = get(s:lsp_linter_map, a:conn_id, '')
if get(a:response, 'jsonrpc', '') is# '2.0' && has_key(a:response, 'error') if get(a:response, 'jsonrpc', '') is# '2.0' && has_key(a:response, 'error')
" Uncomment this line to print LSP error messages. call s:HandleLSPErrorMessage(l:linter_name, a:response)
" call s:HandleLSPErrorMessage(a:response.error.message)
elseif l:method is# 'textDocument/publishDiagnostics' elseif l:method is# 'textDocument/publishDiagnostics'
call s:HandleLSPDiagnostics(a:conn_id, a:response) call s:HandleLSPDiagnostics(a:conn_id, a:response)
elseif get(a:response, 'type', '') is# 'event' elseif get(a:response, 'type', '') is# 'event'
@ -339,6 +367,7 @@ function! ale#engine#SetResults(buffer, loclist) abort
" Call user autocommands. This allows users to hook into ALE's lint cycle. " Call user autocommands. This allows users to hook into ALE's lint cycle.
silent doautocmd <nomodeline> User ALELintPost silent doautocmd <nomodeline> User ALELintPost
" remove in 2.0
" Old DEPRECATED name; call it for backwards compatibility. " Old DEPRECATED name; call it for backwards compatibility.
silent doautocmd <nomodeline> User ALELint silent doautocmd <nomodeline> User ALELint
endif endif
@ -393,7 +422,7 @@ function! ale#engine#FixLocList(buffer, linter_name, loclist) abort
\ 'text': l:old_item.text, \ 'text': l:old_item.text,
\ 'lnum': str2nr(l:old_item.lnum), \ 'lnum': str2nr(l:old_item.lnum),
\ 'col': str2nr(get(l:old_item, 'col', 0)), \ 'col': str2nr(get(l:old_item, 'col', 0)),
\ 'vcol': get(l:old_item, 'vcol', 0), \ 'vcol': 0,
\ 'type': get(l:old_item, 'type', 'E'), \ 'type': get(l:old_item, 'type', 'E'),
\ 'nr': get(l:old_item, 'nr', -1), \ 'nr': get(l:old_item, 'nr', -1),
\ 'linter_name': a:linter_name, \ 'linter_name': a:linter_name,
@ -453,6 +482,20 @@ function! ale#engine#FixLocList(buffer, linter_name, loclist) abort
" When errors go beyond the end of the file, put them at the end. " When errors go beyond the end of the file, put them at the end.
" This is only done for the current buffer. " This is only done for the current buffer.
let l:item.lnum = l:last_line_number let l:item.lnum = l:last_line_number
elseif get(l:old_item, 'vcol', 0)
" Convert virtual column positions to byte positions.
" The positions will be off if the buffer has changed recently.
let l:line = getbufline(a:buffer, l:item.lnum)[0]
let l:item.col = ale#util#Col(l:line, l:item.col)
if has_key(l:item, 'end_col')
let l:end_line = get(l:item, 'end_lnum', l:line) != l:line
\ ? getbufline(a:buffer, l:item.end_lnum)[0]
\ : l:line
let l:item.end_col = ale#util#Col(l:end_line, l:item.end_col)
endif
endif endif
call add(l:new_loclist, l:item) call add(l:new_loclist, l:item)
@ -572,6 +615,8 @@ function! s:RunJob(options) abort
\ 'output': [], \ 'output': [],
\ 'next_chain_index': l:next_chain_index, \ 'next_chain_index': l:next_chain_index,
\} \}
silent doautocmd <nomodeline> User ALEJobStarted
endif endif
if g:ale_history_enabled if g:ale_history_enabled

View File

@ -19,7 +19,7 @@ function! ale#events#SaveEvent(buffer) abort
endif endif
if ale#Var(a:buffer, 'fix_on_save') if ale#Var(a:buffer, 'fix_on_save')
let l:will_fix = ale#fix#Fix('save_file') let l:will_fix = ale#fix#Fix(a:buffer, 'save_file')
let l:should_lint = l:should_lint && !l:will_fix let l:should_lint = l:should_lint && !l:will_fix
endif endif

View File

@ -28,8 +28,6 @@ function! ale#fix#ApplyQueuedFixes() abort
call remove(g:ale_fix_buffer_data, l:buffer) call remove(g:ale_fix_buffer_data, l:buffer)
if l:data.changes_made if l:data.changes_made
call setline(1, l:data.output)
let l:start_line = len(l:data.output) + 1 let l:start_line = len(l:data.output) + 1
let l:end_line = len(l:data.lines_before) let l:end_line = len(l:data.lines_before)
@ -39,6 +37,8 @@ function! ale#fix#ApplyQueuedFixes() abort
call winrestview(l:save) call winrestview(l:save)
endif endif
call setline(1, l:data.output)
if l:data.should_save if l:data.should_save
if empty(&buftype) if empty(&buftype)
noautocmd :w! noautocmd :w!
@ -356,14 +356,16 @@ function! s:RunFixer(options) abort
call ale#fix#ApplyFixes(l:buffer, l:input) call ale#fix#ApplyFixes(l:buffer, l:input)
endfunction endfunction
function! s:GetCallbacks() abort function! s:GetCallbacks(buffer, linters) abort
if type(get(b:, 'ale_fixers')) is type([]) if len(a:linters)
let l:callback_list = a:linters
elseif type(get(b:, 'ale_fixers')) is type([])
" Lists can be used for buffer-local variables only " Lists can be used for buffer-local variables only
let l:callback_list = b:ale_fixers let l:callback_list = b:ale_fixers
else else
" buffer and global options can use dictionaries mapping filetypes to " buffer and global options can use dictionaries mapping filetypes to
" callbacks to run. " callbacks to run.
let l:fixers = ale#Var(bufnr(''), 'fixers') let l:fixers = ale#Var(a:buffer, 'fixers')
let l:callback_list = [] let l:callback_list = []
for l:sub_type in split(&filetype, '\.') for l:sub_type in split(&filetype, '\.')
@ -422,19 +424,13 @@ endfunction
" Accepts an optional argument for what to do when fixing. " Accepts an optional argument for what to do when fixing.
" "
" Returns 0 if no fixes can be applied, and 1 if fixing can be done. " Returns 0 if no fixes can be applied, and 1 if fixing can be done.
function! ale#fix#Fix(...) abort function! ale#fix#Fix(buffer, fixing_flag, ...) abort
if len(a:0) > 1 if a:fixing_flag isnot# '' && a:fixing_flag isnot# 'save_file'
throw 'too many arguments!'
endif
let l:fixing_flag = get(a:000, 0, '')
if l:fixing_flag isnot# '' && l:fixing_flag isnot# 'save_file'
throw "fixing_flag must be either '' or 'save_file'" throw "fixing_flag must be either '' or 'save_file'"
endif endif
try try
let l:callback_list = s:GetCallbacks() let l:callback_list = s:GetCallbacks(a:buffer, a:000)
catch /E700\|BADNAME/ catch /E700\|BADNAME/
let l:function_name = join(split(split(v:exception, ':')[3])) let l:function_name = join(split(split(v:exception, ':')[3]))
let l:echo_message = printf( let l:echo_message = printf(
@ -447,29 +443,27 @@ function! ale#fix#Fix(...) abort
endtry endtry
if empty(l:callback_list) if empty(l:callback_list)
if l:fixing_flag is# '' if a:fixing_flag is# ''
execute 'echom ''No fixers have been defined. Try :ALEFixSuggest''' execute 'echom ''No fixers have been defined. Try :ALEFixSuggest'''
endif endif
return 0 return 0
endif endif
let l:buffer = bufnr('')
for l:job_id in keys(s:job_info_map) for l:job_id in keys(s:job_info_map)
call remove(s:job_info_map, l:job_id) call remove(s:job_info_map, l:job_id)
call ale#job#Stop(l:job_id) call ale#job#Stop(l:job_id)
endfor endfor
" Clean up any files we might have left behind from a previous run. " Clean up any files we might have left behind from a previous run.
call ale#fix#RemoveManagedFiles(l:buffer) call ale#fix#RemoveManagedFiles(a:buffer)
call ale#fix#InitBufferData(l:buffer, l:fixing_flag) call ale#fix#InitBufferData(a:buffer, a:fixing_flag)
silent doautocmd <nomodeline> User ALEFixPre silent doautocmd <nomodeline> User ALEFixPre
call s:RunFixer({ call s:RunFixer({
\ 'buffer': l:buffer, \ 'buffer': a:buffer,
\ 'input': g:ale_fix_buffer_data[l:buffer].lines_before, \ 'input': g:ale_fix_buffer_data[a:buffer].lines_before,
\ 'callback_index': 0, \ 'callback_index': 0,
\ 'callback_list': l:callback_list, \ 'callback_list': l:callback_list,
\}) \})

View File

@ -17,6 +17,11 @@ let s:default_registry = {
\ 'suggested_filetypes': ['python'], \ 'suggested_filetypes': ['python'],
\ 'description': 'Fix PEP8 issues with autopep8.', \ 'description': 'Fix PEP8 issues with autopep8.',
\ }, \ },
\ 'black': {
\ 'function': 'ale#fixers#black#Fix',
\ 'suggested_filetypes': ['python'],
\ 'description': 'Fix PEP8 issues with black.',
\ },
\ 'prettier_standard': { \ 'prettier_standard': {
\ 'function': 'ale#fixers#prettier_standard#Fix', \ 'function': 'ale#fixers#prettier_standard#Fix',
\ 'suggested_filetypes': ['javascript'], \ 'suggested_filetypes': ['javascript'],
@ -90,6 +95,11 @@ let s:default_registry = {
\ 'suggested_filetypes': ['ruby'], \ 'suggested_filetypes': ['ruby'],
\ 'description': 'Fix ruby files with rufo', \ 'description': 'Fix ruby files with rufo',
\ }, \ },
\ 'scalafmt': {
\ 'function': 'ale#fixers#scalafmt#Fix',
\ 'suggested_filetypes': ['scala'],
\ 'description': 'Fix Scala files using scalafmt',
\ },
\ 'standard': { \ 'standard': {
\ 'function': 'ale#fixers#standard#Fix', \ 'function': 'ale#fixers#standard#Fix',
\ 'suggested_filetypes': ['javascript'], \ 'suggested_filetypes': ['javascript'],
@ -180,6 +190,21 @@ let s:default_registry = {
\ 'suggested_filetypes': ['json'], \ 'suggested_filetypes': ['json'],
\ 'description': 'Fix JSON files with jq.', \ 'description': 'Fix JSON files with jq.',
\ }, \ },
\ 'perltidy': {
\ 'function': 'ale#fixers#perltidy#Fix',
\ 'suggested_filetypes': ['perl'],
\ 'description': 'Fix Perl files with perltidy.',
\ },
\ 'xo': {
\ 'function': 'ale#fixers#xo#Fix',
\ 'suggested_filetypes': ['javascript'],
\ 'description': 'Fix JavaScript files using xo --fix.',
\ },
\ 'qmlfmt': {
\ 'function': 'ale#fixers#qmlfmt#Fix',
\ 'suggested_filetypes': ['qml'],
\ 'description': 'Fix QML files with qmlfmt.',
\ },
\} \}
" Reset the function registry to the default entries. " Reset the function registry to the default entries.
@ -272,6 +297,14 @@ function! s:ShouldSuggestForType(suggested_filetypes, type_list) abort
return 0 return 0
endfunction endfunction
function! s:IsGenericFixer(suggested_filetypes) abort
if empty(a:suggested_filetypes)
return 1
endif
return 0
endfunction
function! s:FormatEntry(key, entry) abort function! s:FormatEntry(key, entry) abort
let l:aliases_str = '' let l:aliases_str = ''
@ -291,6 +324,27 @@ function! s:FormatEntry(key, entry) abort
\) \)
endfunction endfunction
" Get list of applicable fixers for filetype, including generic fixers
function! ale#fix#registry#GetApplicableFixers(filetype) abort
let l:type_list = split(a:filetype, '\.')
let l:fixer_name_list = []
for l:key in sort(keys(s:entries))
let l:suggested_filetypes = s:entries[l:key].suggested_filetypes
if s:IsGenericFixer(l:suggested_filetypes) || s:ShouldSuggestForType(l:suggested_filetypes, l:type_list)
call add(l:fixer_name_list, l:key)
endif
endfor
return l:fixer_name_list
endfunction
" Function that returns autocomplete candidates for ALEFix command
function! ale#fix#registry#CompleteFixers(ArgLead, CmdLine, CursorPos) abort
return filter(ale#fix#registry#GetApplicableFixers(&filetype), 'v:val =~? a:ArgLead')
endfunction
" Suggest functions to use from the registry. " Suggest functions to use from the registry.
function! ale#fix#registry#Suggest(filetype) abort function! ale#fix#registry#Suggest(filetype) abort
let l:type_list = split(a:filetype, '\.') let l:type_list = split(a:filetype, '\.')
@ -310,7 +364,7 @@ function! ale#fix#registry#Suggest(filetype) abort
let l:generic_fixer_list = [] let l:generic_fixer_list = []
for l:key in sort(keys(s:entries)) for l:key in sort(keys(s:entries))
if empty(s:entries[l:key].suggested_filetypes) if s:IsGenericFixer(s:entries[l:key].suggested_filetypes)
call add( call add(
\ l:generic_fixer_list, \ l:generic_fixer_list,
\ s:FormatEntry(l:key, s:entries[l:key]), \ s:FormatEntry(l:key, s:entries[l:key]),

View File

@ -2,7 +2,7 @@
" Description: Fixing files with autopep8. " Description: Fixing files with autopep8.
call ale#Set('python_autopep8_executable', 'autopep8') call ale#Set('python_autopep8_executable', 'autopep8')
call ale#Set('python_autopep8_use_global', 0) call ale#Set('python_autopep8_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('python_autopep8_options', '') call ale#Set('python_autopep8_options', '')
function! ale#fixers#autopep8#Fix(buffer) abort function! ale#fixers#autopep8#Fix(buffer) abort

View File

@ -0,0 +1,26 @@
" Author: w0rp <devw0rp@gmail.com>
" Description: Fixing Python files with black.
"
call ale#Set('python_black_executable', 'black')
call ale#Set('python_black_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('python_black_options', '')
function! ale#fixers#black#Fix(buffer) abort
let l:executable = ale#python#FindExecutable(
\ a:buffer,
\ 'python_black',
\ ['black'],
\)
if !executable(l:executable)
return 0
endif
let l:options = ale#Var(a:buffer, 'python_black_options')
return {
\ 'command': ale#Escape(l:executable)
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' -',
\}
endfunction

View File

@ -1,4 +1,4 @@
" Author: eborden <evan@evan-borden.com> " Author: eborden <evan@evan-borden.com>, ifyouseewendy <ifyouseewendy@gmail.com>, aspidiets <emarshall85@gmail.com>
" Description: Integration of brittany with ALE. " Description: Integration of brittany with ALE.
call ale#Set('haskell_brittany_executable', 'brittany') call ale#Set('haskell_brittany_executable', 'brittany')
@ -8,6 +8,7 @@ function! ale#fixers#brittany#Fix(buffer) abort
return { return {
\ 'command': ale#Escape(l:executable) \ 'command': ale#Escape(l:executable)
\ . ' --write-mode inplace'
\ . ' %t', \ . ' %t',
\ 'read_temporary_file': 1, \ 'read_temporary_file': 1,
\} \}

View File

@ -3,7 +3,7 @@ scriptencoding utf-8
" Description: Fixing C/C++ files with clang-format. " Description: Fixing C/C++ files with clang-format.
call ale#Set('c_clangformat_executable', 'clang-format') call ale#Set('c_clangformat_executable', 'clang-format')
call ale#Set('c_clangformat_use_global', 0) call ale#Set('c_clangformat_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('c_clangformat_options', '') call ale#Set('c_clangformat_options', '')
function! ale#fixers#clangformat#GetExecutable(buffer) abort function! ale#fixers#clangformat#GetExecutable(buffer) abort

View File

@ -2,7 +2,7 @@
" Description: Integration of elm-format with ALE. " Description: Integration of elm-format with ALE.
call ale#Set('elm_format_executable', 'elm-format') call ale#Set('elm_format_executable', 'elm-format')
call ale#Set('elm_format_use_global', 0) call ale#Set('elm_format_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('elm_format_options', '--yes') call ale#Set('elm_format_options', '--yes')
function! ale#fixers#elm_format#GetExecutable(buffer) abort function! ale#fixers#elm_format#GetExecutable(buffer) abort

View File

@ -3,7 +3,7 @@
call ale#Set('json_fixjson_executable', 'fixjson') call ale#Set('json_fixjson_executable', 'fixjson')
call ale#Set('json_fixjson_options', '') call ale#Set('json_fixjson_options', '')
call ale#Set('json_fixjson_use_global', 0) call ale#Set('json_fixjson_use_global', get(g:, 'ale_use_global_executables', 0))
function! ale#fixers#fixjson#GetExecutable(buffer) abort function! ale#fixers#fixjson#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'json_fixjson', [ return ale#node#FindExecutable(a:buffer, 'json_fixjson', [

View File

@ -2,7 +2,7 @@
" Description: Integration of Google-java-format with ALE. " Description: Integration of Google-java-format with ALE.
call ale#Set('google_java_format_executable', 'google-java-format') call ale#Set('google_java_format_executable', 'google-java-format')
call ale#Set('google_java_format_use_global', 0) call ale#Set('google_java_format_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('google_java_format_options', '') call ale#Set('google_java_format_options', '')
function! ale#fixers#google_java_format#Fix(buffer) abort function! ale#fixers#google_java_format#Fix(buffer) abort

View File

@ -2,7 +2,7 @@
" Description: Fixing Python imports with isort. " Description: Fixing Python imports with isort.
call ale#Set('python_isort_executable', 'isort') call ale#Set('python_isort_executable', 'isort')
call ale#Set('python_isort_use_global', 0) call ale#Set('python_isort_use_global', get(g:, 'ale_use_global_executables', 0))
function! ale#fixers#isort#Fix(buffer) abort function! ale#fixers#isort#Fix(buffer) abort
let l:executable = ale#python#FindExecutable( let l:executable = ale#python#FindExecutable(

View File

@ -0,0 +1,18 @@
" Author: kfly8 <kentafly88@gmail.com>
" Description: Integration of perltidy with ALE.
call ale#Set('perl_perltidy_executable', 'perltidy')
call ale#Set('perl_perltidy_options', '')
function! ale#fixers#perltidy#Fix(buffer) abort
let l:executable = ale#Var(a:buffer, 'perl_perltidy_executable')
let l:options = ale#Var(a:buffer, 'perl_perltidy_options')
return {
\ 'command': ale#Escape(l:executable)
\ . ' -b'
\ . (empty(l:options) ? '' : ' ' . l:options)
\ . ' %t',
\ 'read_temporary_file': 1,
\}
endfunction

View File

@ -2,7 +2,8 @@
" Description: Fixing files with php-cs-fixer. " Description: Fixing files with php-cs-fixer.
call ale#Set('php_cs_fixer_executable', 'php-cs-fixer') call ale#Set('php_cs_fixer_executable', 'php-cs-fixer')
call ale#Set('php_cs_fixer_use_global', 0) call ale#Set('php_cs_fixer_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('php_cs_fixer_options', '')
function! ale#fixers#php_cs_fixer#GetExecutable(buffer) abort function! ale#fixers#php_cs_fixer#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'php_cs_fixer', [ return ale#node#FindExecutable(a:buffer, 'php_cs_fixer', [
@ -14,10 +15,9 @@ endfunction
function! ale#fixers#php_cs_fixer#Fix(buffer) abort function! ale#fixers#php_cs_fixer#Fix(buffer) abort
let l:executable = ale#fixers#php_cs_fixer#GetExecutable(a:buffer) let l:executable = ale#fixers#php_cs_fixer#GetExecutable(a:buffer)
return { return {
\ 'command': ale#Escape(l:executable) . ' fix %t', \ 'command': ale#Escape(l:executable)
\ . ' ' . ale#Var(a:buffer, 'php_cs_fixer_options')
\ . ' fix %t',
\ 'read_temporary_file': 1, \ 'read_temporary_file': 1,
\} \}
endfunction endfunction

View File

@ -3,7 +3,7 @@
call ale#Set('php_phpcbf_standard', '') call ale#Set('php_phpcbf_standard', '')
call ale#Set('php_phpcbf_executable', 'phpcbf') call ale#Set('php_phpcbf_executable', 'phpcbf')
call ale#Set('php_phpcbf_use_global', 0) call ale#Set('php_phpcbf_use_global', get(g:, 'ale_use_global_executables', 0))
function! ale#fixers#phpcbf#GetExecutable(buffer) abort function! ale#fixers#phpcbf#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'php_phpcbf', [ return ale#node#FindExecutable(a:buffer, 'php_phpcbf', [

View File

@ -3,7 +3,7 @@
" Description: Integration of Prettier with ALE. " Description: Integration of Prettier with ALE.
call ale#Set('javascript_prettier_executable', 'prettier') call ale#Set('javascript_prettier_executable', 'prettier')
call ale#Set('javascript_prettier_use_global', 0) call ale#Set('javascript_prettier_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('javascript_prettier_options', '') call ale#Set('javascript_prettier_options', '')
function! ale#fixers#prettier#GetExecutable(buffer) abort function! ale#fixers#prettier#GetExecutable(buffer) abort

View File

@ -4,7 +4,7 @@
function! ale#fixers#prettier_eslint#SetOptionDefaults() abort function! ale#fixers#prettier_eslint#SetOptionDefaults() abort
call ale#Set('javascript_prettier_eslint_executable', 'prettier-eslint') call ale#Set('javascript_prettier_eslint_executable', 'prettier-eslint')
call ale#Set('javascript_prettier_eslint_use_global', 0) call ale#Set('javascript_prettier_eslint_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('javascript_prettier_eslint_options', '') call ale#Set('javascript_prettier_eslint_options', '')
endfunction endfunction

View File

@ -2,7 +2,7 @@
" Description: Integration of Prettier Standard with ALE. " Description: Integration of Prettier Standard with ALE.
call ale#Set('javascript_prettier_standard_executable', 'prettier-standard') call ale#Set('javascript_prettier_standard_executable', 'prettier-standard')
call ale#Set('javascript_prettier_standard_use_global', 0) call ale#Set('javascript_prettier_standard_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('javascript_prettier_standard_options', '') call ale#Set('javascript_prettier_standard_options', '')
function! ale#fixers#prettier_standard#GetExecutable(buffer) abort function! ale#fixers#prettier_standard#GetExecutable(buffer) abort

View File

@ -0,0 +1,11 @@
call ale#Set('qml_qmlfmt_executable', 'qmlfmt')
function! ale#fixers#qmlfmt#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'qml_qmlfmt_executable')
endfunction
function! ale#fixers#qmlfmt#Fix(buffer) abort
return {
\ 'command': ale#Escape(ale#fixers#qmlfmt#GetExecutable(a:buffer)),
\}
endfunction

View File

@ -0,0 +1,26 @@
" Author: Jeffrey Lau https://github.com/zoonfafer
" Description: Integration of Scalafmt with ALE.
call ale#Set('scala_scalafmt_executable', 'scalafmt')
call ale#Set('scala_scalafmt_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('scala_scalafmt_options', '')
function! ale#fixers#scalafmt#GetCommand(buffer) abort
let l:executable = ale#Var(a:buffer, 'scala_scalafmt_executable')
let l:options = ale#Var(a:buffer, 'scala_scalafmt_options')
let l:exec_args = l:executable =~? 'ng$'
\ ? ' scalafmt'
\ : ''
return ale#Escape(l:executable) . l:exec_args
\ . (empty(l:options) ? '' : ' ' . l:options)
\ . ' %t'
endfunction
function! ale#fixers#scalafmt#Fix(buffer) abort
return {
\ 'command': ale#fixers#scalafmt#GetCommand(a:buffer),
\ 'read_temporary_file': 1,
\}
endfunction

View File

@ -2,7 +2,7 @@
" Description: Fixing files with Standard. " Description: Fixing files with Standard.
call ale#Set('javascript_standard_executable', 'standard') call ale#Set('javascript_standard_executable', 'standard')
call ale#Set('javascript_standard_use_global', 0) call ale#Set('javascript_standard_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('javascript_standard_options', '') call ale#Set('javascript_standard_options', '')
function! ale#fixers#standard#GetExecutable(buffer) abort function! ale#fixers#standard#GetExecutable(buffer) abort

View File

@ -2,7 +2,7 @@
" Description: Fixing files with stylelint. " Description: Fixing files with stylelint.
call ale#Set('stylelint_executable', 'stylelint') call ale#Set('stylelint_executable', 'stylelint')
call ale#Set('stylelint_use_global', 0) call ale#Set('stylelint_use_global', get(g:, 'ale_use_global_executables', 0))
function! ale#fixers#stylelint#GetExecutable(buffer) abort function! ale#fixers#stylelint#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'stylelint', [ return ale#node#FindExecutable(a:buffer, 'stylelint', [

View File

@ -2,7 +2,7 @@
" Description: Integration of SwiftFormat with ALE. " Description: Integration of SwiftFormat with ALE.
call ale#Set('swift_swiftformat_executable', 'swiftformat') call ale#Set('swift_swiftformat_executable', 'swiftformat')
call ale#Set('swift_swiftformat_use_global', 0) call ale#Set('swift_swiftformat_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('swift_swiftformat_options', '') call ale#Set('swift_swiftformat_options', '')
function! ale#fixers#swiftformat#GetExecutable(buffer) abort function! ale#fixers#swiftformat#GetExecutable(buffer) abort

View File

@ -0,0 +1,23 @@
" Author: Albert Marquez - https://github.com/a-marquez
" Description: Fixing files with XO.
call ale#Set('javascript_xo_executable', 'xo')
call ale#Set('javascript_xo_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('javascript_xo_options', '')
function! ale#fixers#xo#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'javascript_xo', [
\ 'node_modules/xo/cli.js',
\ 'node_modules/.bin/xo',
\])
endfunction
function! ale#fixers#xo#Fix(buffer) abort
let l:executable = ale#fixers#xo#GetExecutable(a:buffer)
return {
\ 'command': ale#node#Executable(a:buffer, l:executable)
\ . ' --fix %t',
\ 'read_temporary_file': 1,
\}
endfunction

View File

@ -2,7 +2,7 @@
" Description: Fixing Python files with yapf. " Description: Fixing Python files with yapf.
call ale#Set('python_yapf_executable', 'yapf') call ale#Set('python_yapf_executable', 'yapf')
call ale#Set('python_yapf_use_global', 0) call ale#Set('python_yapf_use_global', get(g:, 'ale_use_global_executables', 0))
function! ale#fixers#yapf#Fix(buffer) abort function! ale#fixers#yapf#Fix(buffer) abort
let l:executable = ale#python#FindExecutable( let l:executable = ale#python#FindExecutable(

View File

@ -5,7 +5,7 @@ let s:sep = has('win32') ? '\' : '/'
call ale#Set('javascript_eslint_options', '') call ale#Set('javascript_eslint_options', '')
call ale#Set('javascript_eslint_executable', 'eslint') call ale#Set('javascript_eslint_executable', 'eslint')
call ale#Set('javascript_eslint_use_global', 0) call ale#Set('javascript_eslint_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('javascript_eslint_suppress_eslintignore', 0) call ale#Set('javascript_eslint_suppress_eslintignore', 0)
call ale#Set('javascript_eslint_suppress_missing_config', 0) call ale#Set('javascript_eslint_suppress_missing_config', 0)

View File

@ -48,7 +48,7 @@ function! ale#handlers#gcc#HandleGCCFormat(buffer, lines) abort
let l:item = { let l:item = {
\ 'lnum': str2nr(l:match[2]), \ 'lnum': str2nr(l:match[2]),
\ 'type': l:match[4] is# 'error' ? 'E' : 'W', \ 'type': (l:match[4] is# 'error' || l:match[4] is# 'fatal error') ? 'E' : 'W',
\ 'text': s:RemoveUnicodeQuotes(l:match[5]), \ 'text': s:RemoveUnicodeQuotes(l:match[5]),
\} \}

View File

@ -0,0 +1,8 @@
" Author: KabbAmine - https://github.com/KabbAmine,
" Ben Falconer <ben@falconers.me.uk>
function! ale#handlers#sasslint#GetCommand(buffer) abort
return ale#path#BufferCdString(a:buffer)
\ . ale#Escape('sass-lint')
\ . ' -v -q -f compact %t'
endfunction

View File

@ -0,0 +1,37 @@
" Author: Nils Leuzinger - https://github.com/PawkyPenguin
" Description: Scala linting handlers for scalac-like compilers.
function! ale#handlers#scala#HandleScalacLintFormat(buffer, lines) abort
" Matches patterns line the following:
"
" /var/folders/5q/20rgxx3x1s34g3m14n5bq0x80000gn/T/vv6pSsy/0:26: error: expected class or object definition
let l:pattern = '^.\+:\(\d\+\): \(\w\+\): \(.\+\)'
let l:output = []
let l:ln = 0
for l:line in a:lines
let l:ln = l:ln + 1
let l:match = matchlist(l:line, l:pattern)
if len(l:match) == 0
continue
endif
let l:text = l:match[3]
let l:type = l:match[2] is# 'error' ? 'E' : 'W'
let l:col = 0
if l:ln + 1 < len(a:lines)
let l:col = stridx(a:lines[l:ln + 1], '^')
endif
call add(l:output, {
\ 'lnum': l:match[1] + 0,
\ 'col': l:col + 1,
\ 'text': l:text,
\ 'type': l:type,
\})
endfor
return l:output
endfunction

View File

@ -2,7 +2,7 @@
" Description: textlint, a proofreading tool (https://textlint.github.io/) " Description: textlint, a proofreading tool (https://textlint.github.io/)
call ale#Set('textlint_executable', 'textlint') call ale#Set('textlint_executable', 'textlint')
call ale#Set('textlint_use_global', 0) call ale#Set('textlint_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('textlint_options', '') call ale#Set('textlint_options', '')
function! ale#handlers#textlint#GetExecutable(buffer) abort function! ale#handlers#textlint#GetExecutable(buffer) abort

View File

@ -4,7 +4,7 @@
function! ale#handlers#writegood#ResetOptions() abort function! ale#handlers#writegood#ResetOptions() abort
call ale#Set('writegood_options', '') call ale#Set('writegood_options', '')
call ale#Set('writegood_executable', 'write-good') call ale#Set('writegood_executable', 'write-good')
call ale#Set('writegood_use_global', 0) call ale#Set('writegood_use_global', get(g:, 'ale_use_global_executables', 0))
endfunction endfunction
" Reset the options so the tests can test how they are set. " Reset the options so the tests can test how they are set.

View File

@ -1,6 +1,9 @@
" Author: w0rp <devw0rp@gmail.com> " Author: w0rp <devw0rp@gmail.com>
" Description: Tools for managing command history " Description: Tools for managing command history
" A flag for controlling the maximum size of the command history to store.
let g:ale_max_buffer_history_size = get(g:, 'ale_max_buffer_history_size', 20)
" Return a shallow copy of the command history for a given buffer number. " Return a shallow copy of the command history for a given buffer number.
function! ale#history#Get(buffer) abort function! ale#history#Get(buffer) abort
return copy(getbufvar(a:buffer, 'ale_history', [])) return copy(getbufvar(a:buffer, 'ale_history', []))

View File

@ -0,0 +1,152 @@
" Author: w0rp <devw0rp@gmail.com>
" Description: Hover support for LSP linters.
let s:hover_map = {}
" Used to get the hover map in tests.
function! ale#hover#GetMap() abort
return deepcopy(s:hover_map)
endfunction
" Used to set the hover map in tests.
function! ale#hover#SetMap(map) abort
let s:hover_map = a:map
endfunction
function! ale#hover#ClearLSPData() abort
let s:hover_map = {}
endfunction
function! ale#hover#HandleTSServerResponse(conn_id, response) abort
if get(a:response, 'command', '') is# 'quickinfo'
\&& has_key(s:hover_map, a:response.request_seq)
let l:options = remove(s:hover_map, a:response.request_seq)
if get(a:response, 'success', v:false) is v:true
\&& get(a:response, 'body', v:null) isnot v:null
if get(l:options, 'hover_from_balloonexpr', 0)
\&& exists('*balloon_show')
\&& ale#Var(l:options.buffer, 'set_balloons')
call balloon_show(a:response.body.displayString)
else
call ale#util#ShowMessage(a:response.body.displayString)
endif
endif
endif
endfunction
function! ale#hover#HandleLSPResponse(conn_id, response) abort
if has_key(a:response, 'id')
\&& has_key(s:hover_map, a:response.id)
let l:options = remove(s:hover_map, a:response.id)
" If the call did __not__ come from balloonexpr...
if !get(l:options, 'hover_from_balloonexpr', 0)
let l:buffer = bufnr('')
let [l:line, l:column] = getcurpos()[1:2]
let l:end = len(getline(l:line))
if l:buffer isnot l:options.buffer
\|| l:line isnot l:options.line
\|| min([l:column, l:end]) isnot min([l:options.column, l:end])
" ... Cancel display the message if the cursor has moved.
return
endif
endif
" The result can be a Dictionary item, a List of the same, or null.
let l:result = get(a:response, 'result', v:null)
if l:result is v:null
return
endif
let l:result = l:result.contents
if type(l:result) is type('')
" The result can be just a string.
let l:result = [l:result]
endif
if type(l:result) is type({})
" If the result is an object, then it's markup content.
let l:result = [l:result.value]
endif
if type(l:result) is type([])
" Replace objects with text values.
call map(l:result, 'type(v:val) is type('''') ? v:val : v:val.value')
let l:str = join(l:result, "\n")
let l:str = substitute(l:str, '^\s*\(.\{-}\)\s*$', '\1', '')
if !empty(l:str)
if get(l:options, 'hover_from_balloonexpr', 0)
\&& exists('*balloon_show')
\&& ale#Var(l:options.buffer, 'set_balloons')
call balloon_show(l:str)
else
call ale#util#ShowMessage(l:str)
endif
endif
endif
endif
endfunction
function! s:ShowDetails(linter, buffer, line, column, opt) abort
let l:Callback = a:linter.lsp is# 'tsserver'
\ ? function('ale#hover#HandleTSServerResponse')
\ : function('ale#hover#HandleLSPResponse')
let l:lsp_details = ale#linter#StartLSP(a:buffer, a:linter, l:Callback)
if empty(l:lsp_details)
return 0
endif
let l:id = l:lsp_details.connection_id
let l:root = l:lsp_details.project_root
if a:linter.lsp is# 'tsserver'
let l:column = a:column
let l:message = ale#lsp#tsserver_message#Quickinfo(
\ a:buffer,
\ a:line,
\ l:column
\)
else
" Send a message saying the buffer has changed first, or the
" hover position probably won't make sense.
call ale#lsp#Send(l:id, ale#lsp#message#DidChange(a:buffer), l:root)
let l:column = min([a:column, len(getbufline(a:buffer, a:line)[0])])
let l:message = ale#lsp#message#Hover(a:buffer, a:line, l:column)
endif
let l:request_id = ale#lsp#Send(l:id, l:message, l:root)
let s:hover_map[l:request_id] = {
\ 'buffer': a:buffer,
\ 'line': a:line,
\ 'column': l:column,
\ 'hover_from_balloonexpr': get(a:opt, 'called_from_balloonexpr', 0),
\}
endfunction
" Obtain Hover information for the specified position
" Pass optional arguments in the dictionary opt.
" Currently, only one key/value is useful:
" - called_from_balloonexpr, this flag marks if we want the result from this
" ale#hover#Show to display in a balloon if possible
"
" Currently, the callbacks displays the info from hover :
" - in the balloon if opt.called_from_balloonexpr and balloon_show is detected
" - as status message otherwise
function! ale#hover#Show(buffer, line, col, opt) abort
for l:linter in ale#linter#Get(getbufvar(a:buffer, '&filetype'))
if !empty(l:linter.lsp)
call s:ShowDetails(l:linter, a:buffer, a:line, a:col, a:opt)
endif
endfor
endfunction

View File

@ -8,6 +8,9 @@
" ale#job#IsRunning(job_id) -> 1 if running, 0 otherwise. " ale#job#IsRunning(job_id) -> 1 if running, 0 otherwise.
" ale#job#Stop(job_id) " ale#job#Stop(job_id)
" A setting for wrapping commands.
let g:ale_command_wrapper = get(g:, 'ale_command_wrapper', '')
if !has_key(s:, 'job_map') if !has_key(s:, 'job_map')
let s:job_map = {} let s:job_map = {}
endif endif
@ -119,7 +122,7 @@ function! s:VimCloseCallback(channel) abort
if job_status(l:job) is# 'dead' if job_status(l:job) is# 'dead'
try try
if !empty(l:info) && has_key(l:info, 'exit_cb') if !empty(l:info) && has_key(l:info, 'exit_cb')
call ale#util#GetFunction(l:info.exit_cb)(l:job_id, l:info.exit_code) call ale#util#GetFunction(l:info.exit_cb)(l:job_id, get(l:info, 'exit_code', 1))
endif endif
finally finally
" Automatically forget about the job after it's done. " Automatically forget about the job after it's done.
@ -208,7 +211,7 @@ function! ale#job#PrepareCommand(buffer, command) abort
return 'cmd /s/c "' . l:command . '"' return 'cmd /s/c "' . l:command . '"'
endif endif
if &shell =~? 'fish$' if &shell =~? 'fish$\|pwsh$'
return ['/bin/sh', '-c', l:command] return ['/bin/sh', '-c', l:command]
endif endif

Some files were not shown because too many files have changed in this diff Show More