Skip to content

Commit

Permalink
Added tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ubaldot committed Jul 24, 2024
1 parent 5a442e5 commit 8ff2101
Show file tree
Hide file tree
Showing 13 changed files with 648 additions and 18 deletions.
11 changes: 11 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file

version: 2
updates:
- package-ecosystem: "github-actions" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "weekly"
60 changes: 60 additions & 0 deletions .github/workflows/unittests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: unit-tests
on: [push, pull_request]
jobs:
unit_test:
name: unit_test
runs-on: ${{ matrix.os }}
strategy:
matrix:
vim:
- nightly
- v9.0.0000
os: [ubuntu-latest, macos-latest]

steps:

- name: Setup Vim
uses: rhysd/action-setup-vim@v1
id: vim
with:
version: ${{ matrix.vim }}

- name: Checkout vim9-conversion-aid plugin code
uses: actions/checkout@v4

- name: Run Tests
run: |
uname -a
export VIMPRG=${{ steps.vim.outputs.executable }}
$VIMPRG --version
cd test
source ./run_tests.sh 1
unit_test_windows:
name: unit_test_windows
runs-on: windows-latest
strategy:
matrix:
vim:
- nightly
- v9.0.0000


- name: Setup Vim
uses: rhysd/action-setup-vim@v1
id: vim
with:
version: ${{ matrix.vim }}

- name: Checkout vim9-conversion-aid replica plugin code
uses: actions/checkout@v4

- name: Run Tests
run: |
systeminfo
echo "Vim command setup."
$Env:VIMPRG = "${{ steps.vim.outputs.executable }}"
& $Env:VIMPRG --version
cd test
.\run_tests.cmd
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# vim9-conversion-aid (WIP)
# vim9-conversion-aid

A little help for upgrading to Vim9.

Expand Down Expand Up @@ -30,9 +30,9 @@ Also, mind that `:h vim9` can be a great support for fixing the remaining
errors if you really don't know how.

To see how the tool perform the upgrade you can take a look at the
`testfile.vim` and `targetfile.vim` in the test folder of this repo. As you
will see, some manual work is still required, but the starting point is rather
favorable compared to starting from scratch.
`test_script.vim` and `expected_script.vim` in the test folder of this repo.
As you will see, some manual work is still required, but the starting point is
rather favorable compared to starting from scratch.

## Limitations

Expand Down
25 changes: 11 additions & 14 deletions lib/vim9_convert_functions.vim
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export def TransformBuffer(...bufnr: list<string>)

# In very-magic form
# var comparison_operators_regex = '(\=*[\^\=\~]|!\=|\<\=|\>\=|\<|\>|\=\~|!\~)'
var comparison_operators_regex = '(\=+|!\=|\<\=|\>\=|\<|\>|!\~)'
var comparison_operators_regex = '(\=[\=\~]?|!\=|\<\=|\>\=|\<|\>|!\~)'

for line in source_lines
# Comments " -> #
Expand All @@ -41,7 +41,7 @@ export def TransformBuffer(...bufnr: list<string>)
transformed_line = transformed_line
# Replace all occurrences of 'func', etc. with 'def', etc
->substitute('\v(^func!?|^function!?)\s', 'def ', 'g')
->substitute('abort', '', 'g')
->substitute(' abort', '', 'g')
->substitute('\v(endfunction|endfunc)', 'enddef', 'g')
# Remove all occurrences of 'call'
->substitute('call\s', '', 'g')
Expand All @@ -54,29 +54,26 @@ export def TransformBuffer(...bufnr: list<string>)
# TODO; it add leading and trailing space no matter what.
# If you already have a space, now you will have two, and then remove
# the extras with the next 2 substitute functions
->substitute($'\v{comparison_operators_regex}([#?]?)', ' \0 ', 'g')
->substitute($'\v{comparison_operators_regex}([#?]?)\s\s', '\1\2 ', 'g')
->substitute($'\v\s\s{comparison_operators_regex}([#?]?)', ' \1\2', 'g')
->substitute($'\v{comparison_operators_regex}([#?]?)', ' \0 ', '')
->substitute($'\v{comparison_operators_regex}([#?]?)\s\s', '\1\2 ', '')
->substitute($'\v\s\s{comparison_operators_regex}([#?]?)', ' \1\2', '')

# HACK: Special case for '=~' because now you have '= ~'
->substitute('\v\=\s\~(\S)', '=~\1 ', 'g')
->substitute('\v\=\s\~\s', '=~ ', 'g')

# space after ':' or ',' - no space before ':' or ','
# Trailing space AND no leading space for [:,]
# TODO: It replaces only the first match
->substitute('\v([,:])(\S)', '\1 \2', 'g')
->substitute('\v\s*([,:])', '\1', 'g')
# Surrounding space between : in brackets[1:3] => [1 : 3]
# I assumes that what is inside a list is a \w* and not a \S*
# TODO FIX
->substitute('\v\[\s*(\w+)\s*:\s*(\w+)\s*\]', '[\1 : \2]', 'g')
# ->substitute('\v\[\s*(\w+)\s*:\s*(\w+)\s*\]', '[\1 : \2]', 'g')
->substitute('\v\[\s*(\S+)\s*:\s*(\S+)\s*\]', '[\1 : \2]', '')
# String concatenation
->substitute('\s\+\.\s\+', ' \.\.\ ', 'g')
# Remove line continuation
->substitute('\v(^\s*)\\', '\1', 'g')
->substitute('\v(^\s*)\\', '\1', '')
# Replace v:true, v:false with true, false (OBS! We need to remove v:
# spaces)
->substitute('v:\([true, false]\)', '\1'[2 : ], 'g')
->substitute('v:[true, false]', '\0'[2 : ], 'g')
endif

# Re-compact b: w: t: g: v: a:, s: e.g. from 'b : foo' to 'b:foo'.
Expand All @@ -100,7 +97,7 @@ export def TransformBuffer(...bufnr: list<string>)
if transformed_line =~ '^\s*let\s'
# Store variable name without 'let'.
var var_name = transformed_line->matchlist('\v\s*let\s+([sabwtgv]:)?(\w+)\W')[1 : 2]->join('')
echom var_name
# echom var_name

# Remove 'let' from all the lines containing variables, with the exception of s: and
# '' (e.g. 'let foo'). The latter because 'let foo" can be either
Expand Down
6 changes: 6 additions & 0 deletions test/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Tests

Setup is heavily copied from yegappan/lsp.

Use sleep in the test_vim9-conversion-aid.vim to see what happens on screen in
combination with sleep.
81 changes: 81 additions & 0 deletions test/common.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
vim9scrip
# Common routines used for running the unit tests


# The WaitFor*() functions are reused from the Vim test suite.
#
# Wait for up to five seconds for "assert" to return zero. "assert" must be a
# (lambda) function containing one assert function. Example:
# call WaitForAssert({-> assert_equal("dead", job_status(job)})
#
# A second argument can be used to specify a different timeout in msec.
#
# Return zero for success, one for failure (like the assert function).
export def WaitForAssert(assert: any, ...itemlist: list<number>): number
var timeout = get(itemlist, 0, 5000)
if WaitForCommon(null, assert, timeout) < 0
return 1
endif
return 0
enddef

# Either "expr" or "assert" is not null
# Return the waiting time for success, -1 for failure.
export def WaitForCommon(Expr: any, Assert: any, timeout: number): number
# using reltime() is more accurate, but not always available
var slept = 0
var success = false
var starttime = exists('*reltimefloat') ? reltime() : 0

while 1
if typename(Expr) == 'func()'
success = Expr()
elseif type(Assert) == v:t_func
success = Assert() == 0
else
success = eval(Expr)
endif
if success
return slept
endif

if slept >= timeout
break
endif
if type(Assert) == v:t_func
# Remove the error added by the assert function.
remove(v:errors, -1)
endif

sleep 10m
if exists('*reltimefloat')
slept = float2nr(reltimefloat(reltime(starttime)) * 1000)
else
slept += 10
endif
endwhile

return -1 # timed out
enddef

# Wait for up to five seconds for "expr" to become true. "expr" can be a
# stringified expr to evaluate, or a funcref without arguments.
# Using a lambda works best. Example:
# call WaitFor({-> status == "ok"})
#
# A second argument can be used to specify a different timeout in msec.
#
# When successful the time slept is returned.
# When running into the timeout an exception is thrown, thus the function does
# not return.
export def WaitFor(expr: any, ...itemlist: list<number>)
var timeout = get(itemlist, 0, 5000)
var slept = WaitForCommon(expr, null, timeout)
if slept < 0
throw 'WaitFor() timed out after ' .. timeout .. ' msec'
endif
return slept
enddef


# vim: shiftwidth=2 softtabstop=2 noexpandtab
126 changes: 126 additions & 0 deletions test/expected_script.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
vim9script

# Define a dictionary with the #{ } syntax
g:mydict = {}

# Add key-value pairs to the dictionary
g:mydict.name = "Vim Script Example"
g:mydict.version = 1.0

g:mydict['name'] = "Vim Script Example"

# Test on random variables defined/updated in a in a messy layout
g:foo = 'potato'

var s:bar = 'banana'
s:bar = 'strawberry'

g:one_global_var = 1
var s:one_list = [-1, 2, 3, 4, 5, 6, 4, 5, 6, 3, 2, 3, 4, 5, 6, 4, 3, 3, 4, 58, 7]
g:one_list_slice = s:one_list[7 : 12]
var s:one_const = 2
s:one_list[0] = s:one_const
g:one_list_slice = s:one_list[s:one_const: 9]

g:one_script_var = 'name'
b:one_buffer_var = -99

# Test leading-trailing white-space around comparison operators
echom s:bar == 'blueberry'
echom s:bar ==# 'blueberry'
echom s:bar ==? 'blueberry'
echom s:bar != 'blueberry'
echom s:one_list[3] >? s:one_list[4]
echom s:one_list[3] <= s:one_list[4]
echom foo =~? 'carot'
echom foo =~ 'carot'
echom foo !~# 'carot'

# Test on line continuation
g:another_dict = {'foo': 'FOO', 'bar': s:bar,
'baz': 'BAZ'}

# Test on booleans
var s:one_boolean = true
s:one_boolean = false

if s:one_boolean == true
echo "foo"
endif

if exists('b:one_function')
echom 'foo'
endif


# Test functions
# Test on variables shadowing
g:shadow = 2
var s:shadow = 3
b:shadow = 4

def TestShadow1()
var shadow = 3
echom shadow
enddef

def TestShadow2()
s:shadow = 3
echom s:shadow
enddef

def TestShadow3(shadow)
s:shadow = a:shadow
var shadow = a:shadow
echom a:shadow
enddef

TestShadow3(shadow)
TestShadow3(s:shadow)
TestShadow3(b:shadow)

# Test script/function scopes
def PrintSomeText()
var s:foo = false
if false
echom a.foo
else
echom A.BAR
b:one_buffer_var = -66
endif
enddef

# Define a function that takes a dictionary as an argument and prints its content
def PrintDictContent(dict)
echo "Dictionary Content: "
for [key, value] in items(a:dict)
echo key .. ": " .. value
endfor
g:one_global_var = 66
enddef

# Define a function that updates a dictionary value
def UpdateDict(dict, key, value)
let a:dict[a:key] = a:value
b:another_buffer_var = 33
var one_script_var = 'monkey'
enddef

# Define a function that returns a dictionary
def CreateDict()
var newdict = { key1: "value1", key2: "value2", }
newdict[g:one_global_var] = "one global"
s:bar = 22
return newdict
enddef

# Call the functions
PrintDictContent(mydict)
UpdateDict(mydict, 'version', 2.0)
PrintDictContent(mydict)

g:newdict = CreateDict()
PrintDictContent(newdict)

# Test on function() removal
w:one_function = PrintDictContent
1 change: 1 addition & 0 deletions test/results.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Test_converted_script(): pass
Loading

0 comments on commit 8ff2101

Please sign in to comment.