aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMitermayer Reis <mitermayer.reis@gmail.com>2023-10-10 12:02:33 +1100
committerGitHub <noreply@github.com>2023-10-10 12:02:33 +1100
commitd10bdd15af8a61eff9d279bd2815b4192506d1c0 (patch)
tree5cf0fd4ce325299bb3d989563ac862525e99b846
parent5e6cca21e12587c02e32a06bf423519eb1e9f1b2 (diff)
parentba1d24036b35df89728344a46ed1f2006fbd1255 (diff)
downloadvim-prettier-d10bdd15af8a61eff9d279bd2815b4192506d1c0.tar.xz
Merge pull request #348 from victorspt/fix/consider_option_version
Fix/consider option version
-rw-r--r--autoload/prettier/resolver/config.vim294
-rw-r--r--autoload/prettier/utils/buffer.vim14
-rw-r--r--autoload/prettier/utils/version.vim25
-rw-r--r--plugin/prettier.vim2
-rw-r--r--tests/vimscript/version.vim126
5 files changed, 411 insertions, 50 deletions
diff --git a/autoload/prettier/resolver/config.vim b/autoload/prettier/resolver/config.vim
index 9a18444..7a9d813 100644
--- a/autoload/prettier/resolver/config.vim
+++ b/autoload/prettier/resolver/config.vim
@@ -3,55 +3,51 @@
function! prettier#resolver#config#resolve(config, hasSelection, start, end) abort
" Allow params to be passed as json format
" convert bellow usage of globals to a get function o the params defaulting to global
- " TODO: Use a list, filter() and join() to get a nicer list of args.
- let l:cmd = s:Flag_use_tabs(a:config) . ' ' .
- \ s:Flag_tab_width(a:config) . ' ' .
- \ s:Flag_print_width(a:config) . ' ' .
- \ s:Flag_parser(a:config) . ' ' .
- \ s:Flag_range_delimiter(a:config, a:hasSelection, a:start, a:end) . ' ' .
- \ ' --semi=' .
- \ get(a:config, 'semi', g:prettier#config#semi) .
- \ ' --single-quote=' .
- \ get(a:config, 'singleQuote', g:prettier#config#single_quote) .
- \ ' --bracket-spacing=' .
- \ get(a:config, 'bracketSpacing', g:prettier#config#bracket_spacing) .
- \ ' --jsx-bracket-same-line=' .
- \ get(a:config, 'jsxBracketSameLine', g:prettier#config#jsx_bracket_same_line) .
- \ ' --arrow-parens=' .
- \ get(a:config, 'arrowParens', g:prettier#config#arrow_parens) .
- \ ' --trailing-comma=' .
- \ get(a:config, 'trailingComma', g:prettier#config#trailing_comma) .
- \ ' --config-precedence=' .
- \ get(a:config, 'configPrecedence', g:prettier#config#config_precedence) .
- \ ' --prose-wrap=' .
- \ get(a:config, 'proseWrap', g:prettier#config#prose_wrap) .
- \ ' --html-whitespace-sensitivity ' .
- \ get(a:config, 'htmlWhitespaceSensitivity', g:prettier#config#html_whitespace_sensitivity) .
- \ ' --stdin-filepath="'.simplify(expand('%:p')).'"' .
- \ ' --require-pragma=' .
- \ get(a:config, 'requirePragma', g:prettier#config#require_pragma) .
- \ ' --end-of-line=' .
- \ get(a:config, 'endOfLine', g:prettier#config#end_of_line) .
- \ ' --loglevel error '.
- \ ' --stdin '
+ let l:config_and_sel = {
+ \ 'config': a:config,
+ \ 'hasSelection': a:hasSelection,
+ \ 'start': a:start,
+ \ 'end': a:end}
+
+ let l:cmd = ' ' . s:Get_current_version_flags(s:FLAGS)
+ \ ->map(function('s:Map_flag_to_cmd_part', [l:config_and_sel]))
+ \ ->values()
+ \ ->join(' ')
return l:cmd
endfunction
-" Returns either '--range-start X --range-end Y' or an empty string.
-function! s:Flag_range_delimiter(config, partialFormatEnabled, start, end) abort
- if (!a:partialFormatEnabled)
+" Mapper functions: {{{
+" Returns either '--range-start X' or an empty string.
+function! s:Flag_range_start(config_and_sel, ...) abort
+ if (!a:config_and_sel.hasSelection)
+ return ''
+ endif
+
+ let l:rangeStart =
+ \ prettier#utils#buffer#getCharRangeStart(a:config_and_sel.start)
+
+ return '--range-start=' . l:rangeStart
+endfunction
+
+" Returns either '--range-end Y' or an empty string.
+function! s:Flag_range_end(config_and_sel, ...) abort
+ if (!a:config_and_sel.hasSelection)
return ''
endif
- let l:range = prettier#utils#buffer#getCharRange(a:start, a:end)
+ let l:rangeEnd =
+ \ prettier#utils#buffer#getCharRangeEnd(a:config_and_sel.end)
- return '--range-start=' . l:range[0] . ' --range-end=' . l:range[1]
+ return '--range-end=' . l:rangeEnd
endfunction
" Returns '--tab-width=NN'
-function! s:Flag_tab_width(config) abort
- let l:value = get(a:config, 'tabWidth', g:prettier#config#tab_width)
+function! s:Flag_tab_width(config_and_sel, ...) abort
+ let l:value = get(
+ \ a:config_and_sel.config,
+ \ 'tabWidth',
+ \ g:prettier#config#tab_width)
if (l:value ==# 'auto')
let l:value = prettier#utils#shim#shiftwidth()
@@ -61,8 +57,12 @@ function! s:Flag_tab_width(config) abort
endfunction
" Returns either '--use-tabs' or an empty string.
-function! s:Flag_use_tabs(config) abort
- let l:value = get(a:config, 'useTabs', g:prettier#config#use_tabs)
+function! s:Flag_use_tabs(config_and_sel, ...) abort
+ let l:value = get(
+ \ a:config_and_sel.config,
+ \ 'useTabs',
+ \ g:prettier#config#use_tabs)
+
if (l:value ==# 'auto')
let l:value = &expandtab ? 'false' : 'true'
endif
@@ -75,8 +75,11 @@ function! s:Flag_use_tabs(config) abort
endfunction
" Returns '--print-width=NN' or ''
-function! s:Flag_print_width(config) abort
- let l:value = get(a:config, 'printWidth', g:prettier#config#print_width)
+function! s:Flag_print_width(config_and_sel, ...) abort
+ let l:value = get(
+ \ a:config_and_sel.config,
+ \ 'printWidth',
+ \ g:prettier#config#print_width)
if (l:value ==# 'auto')
let l:value = &textwidth
@@ -90,8 +93,11 @@ function! s:Flag_print_width(config) abort
endfunction
" Returns '--parser=PARSER' or ''
-function! s:Flag_parser(config) abort
- let l:value = get(a:config, 'parser', g:prettier#config#parser)
+function! s:Flag_parser(config_and_sel, ...) abort
+ let l:value = get(
+ \ a:config_and_sel.config,
+ \ 'parser',
+ \ g:prettier#config#parser)
if (l:value !=# '')
return '--parser=' . l:value
@@ -99,3 +105,203 @@ function! s:Flag_parser(config) abort
return ''
endif
endfunction
+
+" Returns '--stdin-filepath=' concatenated with the full path of the opened
+" file.
+function! s:Flag_stdin_filepath(...) abort
+ let l:current_file = simplify(expand('%:p'))
+ return '--stdin-filepath="' . l:current_file . '"'
+endfunction
+
+" Returns '--loglevel error' or '--log-level error'.
+function! s:Flag_loglevel(config_and_sel, flag, props) abort
+ let l:level = 'error'
+ return a:flag . ' ' . l:level
+endfunction
+
+" Returns '--stdin'.
+function! s:Flag_stdin(...) abort
+ return '--stdin '
+endfunction
+
+" Returns a flag name concantenated with its value in the JSON config object or
+" in the default global Prettier config.
+function! s:Concat_value_to_flag(config_and_sel, flag, props) abort
+ let l:global_value = get(g:, 'prettier#config#' . a:props.global_name, "")
+
+ let l:value = get(a:config_and_sel.config, a:props.json_name, l:global_value)
+
+ return a:flag . '=' . l:value
+endfunction
+
+" Maps a flag name to a part of a command.
+function! s:Map_flag_to_cmd_part(config_and_sel, flag, props) abort
+ return a:props.mapper(a:config_and_sel, a:flag, a:props)
+endfunction
+" }}}
+
+" Constants: {{{
+let s:concat_value = function('s:Concat_value_to_flag')
+
+let s:FLAGS = {
+ \ '--use-tabs': {
+ \ 'json_name': 'useTabs',
+ \ 'global_name': 'use_tabs',
+ \ 'mapper': function('s:Flag_use_tabs')},
+ \ '--tab-width': {
+ \ 'json_name': 'tabWidth',
+ \ 'global_name': 'tab_width',
+ \ 'mapper': function('s:Flag_tab_width')},
+ \ '--print-width': {
+ \ 'json_name': 'printWidth',
+ \ 'global_name': 'print_width',
+ \ 'mapper': function('s:Flag_print_width')},
+ \ '--parser': {
+ \ 'json_name': 'parser',
+ \ 'global_name': 'parser',
+ \ 'mapper': function('s:Flag_parser')},
+ \ '--range-start': {
+ \ 'json_name': '',
+ \ 'global_name': '',
+ \ 'mapper': function('s:Flag_range_start')},
+ \ '--range-end': {
+ \ 'json_name': '',
+ \ 'global_name': '',
+ \ 'mapper': function('s:Flag_range_end')},
+ \ '--semi': {
+ \ 'json_name': 'semi',
+ \ 'global_name': 'semi',
+ \ 'mapper': s:concat_value},
+ \ '--single-quote': {
+ \ 'json_name': 'singleQuote',
+ \ 'global_name': 'single_quote',
+ \ 'mapper': s:concat_value},
+ \ '--bracket-spacing': {
+ \ 'json_name': 'bracketSpacing',
+ \ 'global_name': 'bracket_spacing',
+ \ 'mapper': s:concat_value},
+ \ '--bracket-same-line': {
+ \ 'json_name': 'bracketSameLine',
+ \ 'global_name': 'bracket_same_line',
+ \ 'mapper': s:concat_value,
+ \ 'since': '2.4.0'},
+ \ '--jsx-bracket-same-line': {
+ \ 'json_name': 'jsxBracketSameLine',
+ \ 'global_name': 'jsx_bracket_same_line',
+ \ 'mapper': s:concat_value,
+ \ 'deprecated': '2.4.0'},
+ \ '--arrow-parens': {
+ \ 'json_name': 'arrowParens',
+ \ 'global_name': 'arrow_parens',
+ \ 'mapper': s:concat_value,
+ \ 'since': '1.9.0'},
+ \ '--trailing-comma': {
+ \ 'json_name': 'trailingComma',
+ \ 'global_name': 'trailing_comma',
+ \ 'mapper': s:concat_value},
+ \ '--config-precedence': {
+ \ 'json_name': 'configPrecedence',
+ \ 'global_name': 'config_precedence',
+ \ 'mapper': s:concat_value},
+ \ '--prose-wrap': {
+ \ 'json_name': 'proseWrap',
+ \ 'global_name': 'prose_wrap',
+ \ 'mapper': s:concat_value,
+ \ 'since': '1.8.2'},
+ \ '--html-whitespace-sensitivity': {
+ \ 'json_name': 'htmlWhitespaceSensitivity',
+ \ 'global_name': 'html_whitespace_sensitivity',
+ \ 'mapper': s:concat_value,
+ \ 'since': '1.15.0'},
+ \ '--stdin-filepath': {
+ \ 'json_name': '',
+ \ 'global_name': '',
+ \ 'mapper': function('s:Flag_stdin_filepath')},
+ \ '--require-pragma': {
+ \ 'json_name': 'requirePragma',
+ \ 'global_name': 'require_pragma',
+ \ 'mapper': s:concat_value,
+ \ 'since': '1.7.0'},
+ \ '--end-of-line': {
+ \ 'json_name': 'endOfLine',
+ \ 'global_name': 'end_of_line',
+ \ 'mapper': s:concat_value,
+ \ 'since': '1.15.0'},
+ \ '--loglevel': {
+ \ 'json_name': '',
+ \ 'global_name': '',
+ \ 'mapper': function('s:Flag_loglevel'),
+ \ 'deprecated': '3.0.0'},
+ \ '--log-level': {
+ \ 'json_name': '',
+ \ 'global_name': '',
+ \ 'mapper': function('s:Flag_loglevel'),
+ \ 'since': '3.0.0'},
+ \ '--stdin': {
+ \ 'json_name': '',
+ \ 'global_name': '',
+ \ 'mapper': function('s:Flag_stdin'),
+ \ 'deprecated': '2.0.0'}}
+" }}}
+
+" Flags selector: {{{
+" Returns the argument string with unprintable characters represented in Vim
+" internal format removed from both ends.
+function! s:Trim_internal_unprintable(text) abort
+ let l:char_patt = '\%(\%(\^\m.\)\|\%(<\x\x>\)\)\{}'
+ let l:patt_at_ends = '^' . l:char_patt . '\|' . l:char_patt . '$'
+ let l:trimmed_text = a:text->substitute(l:patt_at_ends, '', 'g')
+ return l:trimmed_text
+endfunction
+
+" Returns the version of the Prettier CLI as a string.
+function! s:Get_prettier_cli_version() abort
+ let l:output = ''
+ redir => l:output
+ silent call prettier#PrettierCli('--version')
+ redir END
+ " The shell sends the string with whitespaces at both ends.
+ let l:prettier_cli_version = s:Trim_internal_unprintable(trim(l:output))
+ return l:prettier_cli_version
+endfunction
+
+" Returns 1 if the version of the flag argument is compatible with the
+" version argument, otherwise returns 0.
+function! s:Filter_uncompatible_flag(version, _, flag) abort
+ let l:is_deprecated = exists('a:flag.deprecated')
+ \ && prettier#utils#version#Is_greater_or_equal_version(
+ \ a:version, a:flag.deprecated)
+ if l:is_deprecated
+ return 0
+ endif
+
+ let l:is_added = !exists('a:flag.since')
+ \ || prettier#utils#version#Is_greater_or_equal_version(
+ \ a:version, a:flag.since)
+ if !l:is_added
+ return 0
+ endif
+ return 1
+endfunction
+
+" Returns an object with the flags from the argument object that are compatible
+" with the version of the Prettier CLI being used.
+function! s:Get_current_version_flags(flags) abort
+ let l:prettier_version = s:Get_prettier_cli_version()
+
+ let l:is_cached = exists('b:prettier_cached_flags')
+ \ && exists('b:prettier_last_used_cli_version')
+ \ && b:prettier_last_used_cli_version ==# l:prettier_version
+ if l:is_cached
+ return b:prettier_cached_flags->copy()
+ endif
+
+ let l:compatible_flags = a:flags->copy()->filter(
+ \ function('s:Filter_uncompatible_flag', [l:prettier_version]))
+ let b:prettier_cached_flags = l:compatible_flags
+ let b:prettier_last_used_cli_version = l:prettier_version
+ return l:compatible_flags->copy()
+endfunction
+" }}}
+
+" vim:foldmethod=marker:foldmarker={{{,}}}:
diff --git a/autoload/prettier/utils/buffer.vim b/autoload/prettier/utils/buffer.vim
index 3125bcc..922a0db 100644
--- a/autoload/prettier/utils/buffer.vim
+++ b/autoload/prettier/utils/buffer.vim
@@ -61,10 +61,12 @@ function! s:getCharPosition(line, col) abort
return line2byte(a:line) + (a:col - 2)
endfun
-" Returns [start, end] byte range when on visual mode
-function! prettier#utils#buffer#getCharRange(startSelection, endSelection) abort
- let l:range = []
- call add(l:range, s:getCharPosition(a:startSelection, col("'<")))
- call add(l:range, s:getCharPosition(a:endSelection, col("'>")))
- return l:range
+" Return the start byte when on visual mode
+function! prettier#utils#buffer#getCharRangeStart(startSelection) abort
+ return s:getCharPosition(a:startSelection, col("'<"))
+endfunction
+
+" Return the end byte when on visual mode
+function! prettier#utils#buffer#getCharRangeEnd(endSelection) abort
+ return s:getCharPosition(a:endSelection, col("'>"))
endfunction
diff --git a/autoload/prettier/utils/version.vim b/autoload/prettier/utils/version.vim
new file mode 100644
index 0000000..3cbbb73
--- /dev/null
+++ b/autoload/prettier/utils/version.vim
@@ -0,0 +1,25 @@
+" Returns 1 if the first argument is the greater version, returns 0 if the
+" arguments are the same version, or returns -1 if the first argument is the
+" lesser version.
+function! prettier#utils#version#Compare_versions(a, b) abort
+ let [l:a_major, l:a_minor, l:a_patch; l:rest] = a:a->split('\D')
+ \ ->map('str2nr(v:val)')
+ let [l:b_major, l:b_minor, l:b_patch; l:rest] = a:b->split('\D')
+ \ ->map('str2nr(v:val)')
+ let l:is_a_greater =
+ \ l:a_major > l:b_major
+ \ || (l:a_major == l:b_major && l:a_minor > l:b_minor)
+ \ || (l:a_major == l:b_major && l:a_minor == l:b_minor
+ \ && l:a_patch > l:b_patch)
+ let l:is_a_equal_b =
+ \ l:a_major == l:b_major
+ \ && l:a_minor == l:b_minor
+ \ && l:a_patch == l:b_patch
+ return l:is_a_greater ? 1 : (l:is_a_equal_b ? 0 : -1)
+endfunction
+
+" Returns 1 if the first argument is greater than or equal to the second,
+" otherwise returns 0.
+function! prettier#utils#version#Is_greater_or_equal_version(a, b) abort
+ return prettier#utils#version#Compare_versions(a:a, a:b) != -1
+endfunction
diff --git a/plugin/prettier.vim b/plugin/prettier.vim
index b85195e..7ef774b 100644
--- a/plugin/prettier.vim
+++ b/plugin/prettier.vim
@@ -113,6 +113,8 @@ let g:prettier#config#bracket_spacing = get(g:,'prettier#config#bracket_spacing'
" default: 'false'
" See more: https://prettier.io/docs/en/options.html#jsx-brackets
let g:prettier#config#jsx_bracket_same_line = get(g:,'prettier#config#jsx_bracket_same_line', 'false')
+" This option has another name for Prettier versions 2.4.0 and higher:
+let g:prettier#config#bracket_same_line = get(g:, 'prettier#config#bracket_same_line', 'false')
" avoid wrapping a single arrow function param in parens
" avoid|always
diff --git a/tests/vimscript/version.vim b/tests/vimscript/version.vim
new file mode 100644
index 0000000..9718011
--- /dev/null
+++ b/tests/vimscript/version.vim
@@ -0,0 +1,126 @@
+" To run the tests in this script, first add the vim-prettier plugin and let
+" Vim load it, then uncomment the last line in this script, and source this
+" file in Vim with the command
+" ":source <file-path>" where <file-path> is the path to this file, e.g.
+" ":source %".
+
+function! s:Test_version_comparison_greater_case() abort
+ echomsg 'Testing version comparison, greater case.'
+
+ let l:ver_1 = '2.7.3'
+ let l:ver_2 = '0.9.8'
+ let l:value = prettier#utils#version#Compare_versions(l:ver_1, l:ver_2)
+ let l:expected = 1
+ return assert_equal(
+ \ l:value,
+ \ l:expected,
+ \ 'Expected ' . l:expected . ' but received ' . l:value
+ \ . ' instead.')
+endfunction
+
+function! s:Test_version_comparison_lesser_case() abort
+ echomsg 'Testing version comparison, lesser case.'
+
+ let l:ver_1 = '3.9.5'
+ let l:ver_2 = '10.5.2'
+ let l:value = prettier#utils#version#Compare_versions(l:ver_1, l:ver_2)
+ let l:expected = -1
+ return assert_equal(
+ \ l:value,
+ \ l:expected,
+ \ 'Expected ' . l:expected . ' but received ' . l:value
+ \ . ' instead.')
+endfunction
+
+function! s:Test_version_comparison_equal_case() abort
+ echomsg 'Testing version comparison, equal case.'
+
+ let l:ver_1 = '8.2.4'
+ let l:ver_2 = '8.2.4'
+ let l:value = prettier#utils#version#Compare_versions(l:ver_1, l:ver_2)
+ let l:expected = 0
+ return assert_equal(
+ \ l:value,
+ \ l:expected,
+ \ 'Expected ' . l:expected . ' but received ' . l:value
+ \ . ' instead.')
+endfunction
+
+function! s:Test_is_greater_or_equal_version_greater_case() abort
+ echomsg 'Testing function that checks if is lesser version, greater case.'
+
+ let l:ver_1 = '3.8.1'
+ let l:ver_2 = '0.2.9'
+ let l:value = prettier#utils#version#Is_greater_or_equal_version(
+ \ l:ver_1, l:ver_2)
+ let l:expected = 1
+ return assert_equal(
+ \ l:value,
+ \ l:expected,
+ \ 'Expected ' . l:expected . ' but received ' . l:value
+ \ . ' instead.')
+endfunction
+
+function! s:Test_is_greater_or_equal_version_lesser_case() abort
+ echomsg 'Testing function that checks if is lesser version, lesser case.'
+
+ let l:ver_1 = '7.2.8'
+ let l:ver_2 = '15.1.6'
+ let l:value = prettier#utils#version#Is_greater_or_equal_version(
+ \ l:ver_1, l:ver_2)
+ let l:expected = 0
+ return assert_equal(
+ \ l:value,
+ \ l:expected,
+ \ 'Expected ' . l:expected . ' but received ' . l:value
+ \ . ' instead.')
+endfunction
+
+function! s:Test_is_greater_or_equal_version_equal_case() abort
+ echomsg 'Testing function that checks if is lesser version, lesser case.'
+
+ let l:ver_1 = '4.12.185'
+ let l:ver_2 = '4.12.185'
+ let l:value = prettier#utils#version#Is_greater_or_equal_version(
+ \ l:ver_1, l:ver_2)
+ let l:expected = 1
+ return assert_equal(
+ \ l:value,
+ \ l:expected,
+ \ 'Expected ' . l:expected . ' but received ' . l:value
+ \ . ' instead.')
+endfunction
+
+function! s:Run_tests() abort
+ let v:errors = []
+
+ let l:test_functions = [
+ \ function('s:Test_version_comparison_greater_case'),
+ \ function('s:Test_version_comparison_lesser_case'),
+ \ function('s:Test_version_comparison_equal_case'),
+ \ function('s:Test_is_greater_or_equal_version_greater_case'),
+ \ function('s:Test_is_greater_or_equal_version_lesser_case'),
+ \ function('s:Test_is_greater_or_equal_version_equal_case')]
+
+ let l:results_as_returned = l:test_functions->copy()->map('v:val()')
+ let l:results_as_text = l:results_as_returned
+ \ ->copy()
+ \ ->map('v:key + 1 .. '': '' .. (v:val ? "failed" : "passed")')
+
+ let l:has_failed_test = v:errors->len() > 0
+ \ || l:results_as_returned->index(1) >= 0
+ if l:has_failed_test
+ echoerr 'The tests failed.'
+ echoerr 'Results:'
+ echoerr l:results_as_text->join('; ')
+ echoerr 'Errors:'
+ echoerr v:errors->join('; ')
+ else
+ echomsg 'The tests were completed successfully.'
+ echomsg 'Results:'
+ echomsg l:results_as_text->join('; ')
+ endif
+endfunction
+
+" Uncomment the next line to run the tests.
+" call s:Run_tests()