Skip to content

Commit c3e92c1

Browse files
committed
patch 8.1.1044: no way to check the reference count of objects
Problem: No way to check the reference count of objects. Solution: Add test_refcount(). (Ozaki Kiichi, closes #4124)
1 parent b782869 commit c3e92c1

4 files changed

Lines changed: 182 additions & 2 deletions

File tree

runtime/doc/eval.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2672,6 +2672,7 @@ test_null_partial() Funcref null value for testing
26722672
test_null_string() String null value for testing
26732673
test_option_not_set({name}) none reset flag indicating option was set
26742674
test_override({expr}, {val}) none test with Vim internal overrides
2675+
test_refcount({expr}) Number get the reference count of {expr}
26752676
test_scrollbar({which}, {value}, {dragging})
26762677
none scroll in the GUI for testing
26772678
test_settime({expr}) none set current time for testing
@@ -9589,6 +9590,11 @@ test_override({name}, {val}) *test_override()*
95899590
< The value of "starting" is saved. It is restored by: >
95909591
call test_override('starting', 0)
95919592
9593+
test_refcount({expr}) *test_refcount()*
9594+
Return the reference count of {expr}. When {expr} is of a
9595+
type that does not have a reference count, returns -1. Only
9596+
to be used for testing.
9597+
95929598
test_scrollbar({which}, {value}, {dragging}) *test_scrollbar()*
95939599
Pretend using scrollbar {which} to move it to position
95949600
{value}. {which} can be:

src/evalfunc.c

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,7 @@ static void f_test_autochdir(typval_T *argvars, typval_T *rettv);
428428
static void f_test_feedinput(typval_T *argvars, typval_T *rettv);
429429
static void f_test_option_not_set(typval_T *argvars, typval_T *rettv);
430430
static void f_test_override(typval_T *argvars, typval_T *rettv);
431+
static void f_test_refcount(typval_T *argvars, typval_T *rettv);
431432
static void f_test_garbagecollect_now(typval_T *argvars, typval_T *rettv);
432433
static void f_test_ignore_error(typval_T *argvars, typval_T *rettv);
433434
static void f_test_null_blob(typval_T *argvars, typval_T *rettv);
@@ -952,7 +953,7 @@ static struct fst
952953
{"test_feedinput", 1, 1, f_test_feedinput},
953954
{"test_garbagecollect_now", 0, 0, f_test_garbagecollect_now},
954955
{"test_ignore_error", 1, 1, f_test_ignore_error},
955-
{"test_null_blob", 0, 0, f_test_null_blob},
956+
{"test_null_blob", 0, 0, f_test_null_blob},
956957
#ifdef FEAT_JOB_CHANNEL
957958
{"test_null_channel", 0, 0, f_test_null_channel},
958959
#endif
@@ -964,7 +965,8 @@ static struct fst
964965
{"test_null_partial", 0, 0, f_test_null_partial},
965966
{"test_null_string", 0, 0, f_test_null_string},
966967
{"test_option_not_set", 1, 1, f_test_option_not_set},
967-
{"test_override", 2, 2, f_test_override},
968+
{"test_override", 2, 2, f_test_override},
969+
{"test_refcount", 1, 1, f_test_refcount},
968970
#ifdef FEAT_GUI
969971
{"test_scrollbar", 3, 3, f_test_scrollbar},
970972
#endif
@@ -13846,6 +13848,67 @@ f_test_override(typval_T *argvars, typval_T *rettv UNUSED)
1384613848
}
1384713849
}
1384813850

13851+
/*
13852+
* "test_refcount({expr})" function
13853+
*/
13854+
static void
13855+
f_test_refcount(typval_T *argvars, typval_T *rettv)
13856+
{
13857+
int retval = -1;
13858+
13859+
switch (argvars[0].v_type)
13860+
{
13861+
case VAR_UNKNOWN:
13862+
case VAR_NUMBER:
13863+
case VAR_FLOAT:
13864+
case VAR_SPECIAL:
13865+
case VAR_STRING:
13866+
break;
13867+
case VAR_JOB:
13868+
#ifdef FEAT_JOB_CHANNEL
13869+
if (argvars[0].vval.v_job != NULL)
13870+
retval = argvars[0].vval.v_job->jv_refcount - 1;
13871+
#endif
13872+
break;
13873+
case VAR_CHANNEL:
13874+
#ifdef FEAT_JOB_CHANNEL
13875+
if (argvars[0].vval.v_channel != NULL)
13876+
retval = argvars[0].vval.v_channel->ch_refcount - 1;
13877+
#endif
13878+
break;
13879+
case VAR_FUNC:
13880+
if (argvars[0].vval.v_string != NULL)
13881+
{
13882+
ufunc_T *fp;
13883+
13884+
fp = find_func(argvars[0].vval.v_string);
13885+
if (fp != NULL)
13886+
retval = fp->uf_refcount;
13887+
}
13888+
break;
13889+
case VAR_PARTIAL:
13890+
if (argvars[0].vval.v_partial != NULL)
13891+
retval = argvars[0].vval.v_partial->pt_refcount - 1;
13892+
break;
13893+
case VAR_BLOB:
13894+
if (argvars[0].vval.v_blob != NULL)
13895+
retval = argvars[0].vval.v_blob->bv_refcount - 1;
13896+
break;
13897+
case VAR_LIST:
13898+
if (argvars[0].vval.v_list != NULL)
13899+
retval = argvars[0].vval.v_list->lv_refcount - 1;
13900+
break;
13901+
case VAR_DICT:
13902+
if (argvars[0].vval.v_dict != NULL)
13903+
retval = argvars[0].vval.v_dict->dv_refcount - 1;
13904+
break;
13905+
}
13906+
13907+
rettv->v_type = VAR_NUMBER;
13908+
rettv->vval.v_number = retval;
13909+
13910+
}
13911+
1384913912
/*
1385013913
* "test_garbagecollect_now()" function
1385113914
*/

src/testdir/test_vimscript.vim

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1556,6 +1556,115 @@ func Test_compound_assignment_operators()
15561556
let @/ = ''
15571557
endfunc
15581558

1559+
func Test_refcount()
1560+
" Immediate values
1561+
call assert_equal(-1, test_refcount(1))
1562+
call assert_equal(-1, test_refcount('s'))
1563+
call assert_equal(-1, test_refcount(v:true))
1564+
call assert_equal(0, test_refcount([]))
1565+
call assert_equal(0, test_refcount({}))
1566+
call assert_equal(0, test_refcount(0zff))
1567+
call assert_equal(0, test_refcount({-> line('.')}))
1568+
if has('float')
1569+
call assert_equal(-1, test_refcount(0.1))
1570+
endif
1571+
if has('job')
1572+
call assert_equal(0, test_refcount(job_start([&shell, &shellcmdflag, 'echo .'])))
1573+
endif
1574+
1575+
" No refcount types
1576+
let x = 1
1577+
call assert_equal(-1, test_refcount(x))
1578+
let x = 's'
1579+
call assert_equal(-1, test_refcount(x))
1580+
let x = v:true
1581+
call assert_equal(-1, test_refcount(x))
1582+
if has('float')
1583+
let x = 0.1
1584+
call assert_equal(-1, test_refcount(x))
1585+
endif
1586+
1587+
" Check refcount
1588+
let x = []
1589+
call assert_equal(1, test_refcount(x))
1590+
1591+
let x = {}
1592+
call assert_equal(1, test_refcount(x))
1593+
1594+
let x = 0zff
1595+
call assert_equal(1, test_refcount(x))
1596+
1597+
let X = {-> line('.')}
1598+
call assert_equal(1, test_refcount(X))
1599+
let Y = X
1600+
call assert_equal(2, test_refcount(X))
1601+
1602+
if has('job')
1603+
let job = job_start([&shell, &shellcmdflag, 'echo .'])
1604+
call assert_equal(1, test_refcount(job))
1605+
call assert_equal(1, test_refcount(job_getchannel(job)))
1606+
call assert_equal(1, test_refcount(job))
1607+
endif
1608+
1609+
" Function arguments, copying and unassigning
1610+
func ExprCheck(x, i)
1611+
let i = a:i + 1
1612+
call assert_equal(i, test_refcount(a:x))
1613+
let Y = a:x
1614+
call assert_equal(i + 1, test_refcount(a:x))
1615+
call assert_equal(test_refcount(a:x), test_refcount(Y))
1616+
let Y = 0
1617+
call assert_equal(i, test_refcount(a:x))
1618+
endfunc
1619+
call ExprCheck([], 0)
1620+
call ExprCheck({}, 0)
1621+
call ExprCheck(0zff, 0)
1622+
call ExprCheck({-> line('.')}, 0)
1623+
if has('job')
1624+
call ExprCheck(job, 1)
1625+
call ExprCheck(job_getchannel(job), 1)
1626+
call job_stop(job)
1627+
endif
1628+
delfunc ExprCheck
1629+
1630+
" Regarding function
1631+
func Func(x) abort
1632+
call assert_equal(2, test_refcount(function('Func')))
1633+
call assert_equal(0, test_refcount(funcref('Func')))
1634+
endfunc
1635+
call assert_equal(1, test_refcount(function('Func')))
1636+
call assert_equal(0, test_refcount(function('Func', [1])))
1637+
call assert_equal(0, test_refcount(funcref('Func')))
1638+
call assert_equal(0, test_refcount(funcref('Func', [1])))
1639+
let X = function('Func')
1640+
let Y = X
1641+
call assert_equal(1, test_refcount(X))
1642+
let X = function('Func', [1])
1643+
let Y = X
1644+
call assert_equal(2, test_refcount(X))
1645+
let X = funcref('Func')
1646+
let Y = X
1647+
call assert_equal(2, test_refcount(X))
1648+
let X = funcref('Func', [1])
1649+
let Y = X
1650+
call assert_equal(2, test_refcount(X))
1651+
unlet X
1652+
unlet Y
1653+
call Func(1)
1654+
delfunc Func
1655+
1656+
" Function with dict
1657+
func DictFunc() dict
1658+
call assert_equal(3, test_refcount(self))
1659+
endfunc
1660+
let d = {'Func': function('DictFunc')}
1661+
call assert_equal(1, test_refcount(d))
1662+
call assert_equal(0, test_refcount(d.Func))
1663+
call d.Func()
1664+
unlet d
1665+
delfunc DictFunc
1666+
endfunc
1667+
15591668
"-------------------------------------------------------------------------------
15601669
" Modelines {{{1
15611670
" vim: ts=8 sw=4 tw=80 fdm=marker

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -775,6 +775,8 @@ static char *(features[]) =
775775

776776
static int included_patches[] =
777777
{ /* Add new patch number below this line */
778+
/**/
779+
1044,
778780
/**/
779781
1043,
780782
/**/

0 commit comments

Comments
 (0)