2022-12-08 15:32:33 +00:00
|
|
|
" Test Vim9 classes
|
|
|
|
|
|
|
|
source check.vim
|
|
|
|
import './vim9.vim' as v9
|
|
|
|
|
|
|
|
def Test_class_basic()
|
2023-09-18 19:56:49 +02:00
|
|
|
# Class supported only in "vim9script"
|
2022-12-08 15:32:33 +00:00
|
|
|
var lines =<< trim END
|
|
|
|
class NotWorking
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1316:')
|
2022-12-08 15:32:33 +00:00
|
|
|
|
2023-09-18 19:56:49 +02:00
|
|
|
# First character in a class name should be capitalized.
|
2022-12-08 15:32:33 +00:00
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class notWorking
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1314:')
|
2022-12-08 15:32:33 +00:00
|
|
|
|
2023-09-18 19:56:49 +02:00
|
|
|
# Only alphanumeric characters are supported in a class name
|
2022-12-08 15:32:33 +00:00
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class Not@working
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1315:')
|
2022-12-08 15:32:33 +00:00
|
|
|
|
2023-09-18 19:56:49 +02:00
|
|
|
# Unsupported keyword (instead of class)
|
2022-12-08 15:32:33 +00:00
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
abstract noclass Something
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E475:')
|
2022-12-08 15:32:33 +00:00
|
|
|
|
2023-09-18 19:56:49 +02:00
|
|
|
# Only the completed word "class" should be recognized
|
2022-12-08 15:32:33 +00:00
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
abstract classy Something
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E475:')
|
2022-12-08 15:32:33 +00:00
|
|
|
|
2023-09-18 19:56:49 +02:00
|
|
|
# The complete "endclass" should be specified.
|
2022-12-08 15:32:33 +00:00
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class Something
|
|
|
|
endcl
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1065:')
|
2022-12-08 15:32:33 +00:00
|
|
|
|
2023-09-18 19:56:49 +02:00
|
|
|
# Additional words after "endclass"
|
2022-12-08 15:32:33 +00:00
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class Something
|
2023-01-28 19:19:03 +00:00
|
|
|
endclass school's out
|
2022-12-08 15:32:33 +00:00
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E488:')
|
2022-12-08 15:32:33 +00:00
|
|
|
|
2023-09-18 19:56:49 +02:00
|
|
|
# Additional commands after "endclass"
|
2022-12-08 15:32:33 +00:00
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class Something
|
|
|
|
endclass | echo 'done'
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E488:')
|
2022-12-08 15:32:33 +00:00
|
|
|
|
2023-09-18 19:56:49 +02:00
|
|
|
# Use "this" without any member variable name
|
2022-12-08 15:32:33 +00:00
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class Something
|
|
|
|
this
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1317:')
|
2022-12-08 15:32:33 +00:00
|
|
|
|
2023-09-18 19:56:49 +02:00
|
|
|
# Use "this." without any member variable name
|
2022-12-08 15:32:33 +00:00
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class Something
|
|
|
|
this.
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1317:')
|
2022-12-08 15:32:33 +00:00
|
|
|
|
2023-09-18 19:56:49 +02:00
|
|
|
# Space between "this" and ".<variable>"
|
2022-12-08 15:32:33 +00:00
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class Something
|
|
|
|
this .count
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1317:')
|
2022-12-08 15:32:33 +00:00
|
|
|
|
2023-09-18 19:56:49 +02:00
|
|
|
# Space between "this." and the member variable name
|
2022-12-08 15:32:33 +00:00
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class Something
|
|
|
|
this. count
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1317:')
|
2022-12-08 15:32:33 +00:00
|
|
|
|
2023-09-18 19:56:49 +02:00
|
|
|
# Use "that" instead of "this"
|
2022-12-08 15:32:33 +00:00
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class Something
|
|
|
|
this.count: number
|
|
|
|
that.count
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: that.count')
|
2022-12-08 15:32:33 +00:00
|
|
|
|
2023-09-18 19:56:49 +02:00
|
|
|
# Member variable without a type or initialization
|
2022-12-08 15:32:33 +00:00
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class Something
|
|
|
|
this.count
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1022:')
|
2022-12-08 15:32:33 +00:00
|
|
|
|
2023-09-18 19:56:49 +02:00
|
|
|
# Use a non-existing member variable in new()
|
2022-12-23 17:56:27 +00:00
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class Something
|
|
|
|
def new()
|
|
|
|
this.state = 0
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
var obj = Something.new()
|
|
|
|
END
|
2023-09-18 19:56:49 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1326: Member not found on object "Something": state')
|
2022-12-23 17:56:27 +00:00
|
|
|
|
2023-09-18 19:56:49 +02:00
|
|
|
# Space before ":" in a member variable declaration
|
2022-12-08 15:32:33 +00:00
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class Something
|
|
|
|
this.count : number
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1059:')
|
2022-12-08 15:32:33 +00:00
|
|
|
|
2023-09-18 19:56:49 +02:00
|
|
|
# No space after ":" in a member variable declaration
|
2022-12-08 15:32:33 +00:00
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class Something
|
|
|
|
this.count:number
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1069:')
|
2022-12-08 15:32:33 +00:00
|
|
|
|
2023-08-19 11:26:42 +02:00
|
|
|
# Test for unsupported comment specifier
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class Something
|
|
|
|
# comment
|
|
|
|
#{
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1170:')
|
2023-08-19 11:26:42 +02:00
|
|
|
|
2023-09-17 17:03:19 +02:00
|
|
|
# Test for using class as a bool
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
endclass
|
|
|
|
if A
|
|
|
|
endif
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1319: Using a class as a Number')
|
|
|
|
|
|
|
|
# Test for using object as a bool
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
endclass
|
|
|
|
var a = A.new()
|
|
|
|
if a
|
|
|
|
endif
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1320: Using an object as a Number')
|
|
|
|
|
|
|
|
# Test for using class as a float
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
endclass
|
|
|
|
sort([1.1, A], 'f')
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1321: Using a class as a Float')
|
|
|
|
|
|
|
|
# Test for using object as a float
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
endclass
|
|
|
|
var a = A.new()
|
|
|
|
sort([1.1, a], 'f')
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1322: Using an object as a Float')
|
|
|
|
|
|
|
|
# Test for using class as a string
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
endclass
|
|
|
|
:exe 'call ' .. A
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1323: Using a class as a String')
|
|
|
|
|
|
|
|
# Test for using object as a string
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
endclass
|
|
|
|
var a = A.new()
|
|
|
|
:exe 'call ' .. a
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1324: Using an object as a String')
|
|
|
|
|
2023-09-18 19:56:49 +02:00
|
|
|
# Test creating a class with member variables and methods, calling a object
|
|
|
|
# method. Check for using type() and typename() with a class and an object.
|
2022-12-08 15:32:33 +00:00
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class TextPosition
|
|
|
|
this.lnum: number
|
2022-12-10 18:42:12 +00:00
|
|
|
this.col: number
|
2022-12-09 21:41:48 +00:00
|
|
|
|
2022-12-20 13:38:22 +00:00
|
|
|
# make a nicely formatted string
|
2022-12-09 21:41:48 +00:00
|
|
|
def ToString(): string
|
|
|
|
return $'({this.lnum}, {this.col})'
|
|
|
|
enddef
|
2022-12-08 15:32:33 +00:00
|
|
|
endclass
|
|
|
|
|
2022-12-08 20:42:00 +00:00
|
|
|
# use the automatically generated new() method
|
|
|
|
var pos = TextPosition.new(2, 12)
|
|
|
|
assert_equal(2, pos.lnum)
|
|
|
|
assert_equal(12, pos.col)
|
2022-12-09 21:41:48 +00:00
|
|
|
|
|
|
|
# call an object method
|
|
|
|
assert_equal('(2, 12)', pos.ToString())
|
2023-01-12 21:08:53 +00:00
|
|
|
|
|
|
|
assert_equal(v:t_class, type(TextPosition))
|
|
|
|
assert_equal(v:t_object, type(pos))
|
|
|
|
assert_equal('class<TextPosition>', typename(TextPosition))
|
|
|
|
assert_equal('object<TextPosition>', typename(pos))
|
2022-12-08 15:32:33 +00:00
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-08-19 11:26:42 +02:00
|
|
|
|
|
|
|
# When referencing object methods, space cannot be used after a "."
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
def Foo(): number
|
|
|
|
return 10
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
var a = A.new()
|
|
|
|
var v = a. Foo()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1202:')
|
2023-08-19 11:26:42 +02:00
|
|
|
|
|
|
|
# Using an object without specifying a method or a member variable
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
def Foo(): number
|
|
|
|
return 10
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
var a = A.new()
|
|
|
|
var v = a.
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E15:')
|
2023-08-19 11:26:42 +02:00
|
|
|
|
|
|
|
# Error when parsing the arguments of an object method.
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
def Foo()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
var a = A.new()
|
|
|
|
var v = a.Foo(,)
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E15:')
|
2023-08-22 21:29:28 +02:00
|
|
|
|
2023-09-18 19:56:49 +02:00
|
|
|
# Use a multi-line initialization for a member variable
|
2023-08-22 21:29:28 +02:00
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
this.y = {
|
|
|
|
X: 1
|
|
|
|
}
|
|
|
|
endclass
|
|
|
|
var a = A.new()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2022-12-08 15:32:33 +00:00
|
|
|
enddef
|
|
|
|
|
2023-02-25 19:59:31 +00:00
|
|
|
def Test_class_defined_twice()
|
|
|
|
# class defined twice should fail
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class There
|
|
|
|
endclass
|
|
|
|
class There
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1041: Redefining script item: "There"')
|
2023-02-25 19:59:31 +00:00
|
|
|
|
|
|
|
# one class, reload same script twice is OK
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class There
|
|
|
|
endclass
|
|
|
|
END
|
|
|
|
writefile(lines, 'XclassTwice.vim', 'D')
|
|
|
|
source XclassTwice.vim
|
|
|
|
source XclassTwice.vim
|
|
|
|
enddef
|
|
|
|
|
2023-02-26 18:58:23 +00:00
|
|
|
def Test_returning_null_object()
|
|
|
|
# this was causing an internal error
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class BufferList
|
|
|
|
def Current(): any
|
|
|
|
return null_object
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var buffers = BufferList.new()
|
|
|
|
echo buffers.Current()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-02-26 18:58:23 +00:00
|
|
|
enddef
|
|
|
|
|
2023-03-11 20:56:35 +00:00
|
|
|
def Test_using_null_class()
|
|
|
|
var lines =<< trim END
|
|
|
|
@_ = null_class.member
|
|
|
|
END
|
|
|
|
v9.CheckDefExecAndScriptFailure(lines, ['E715:', 'E1363:'])
|
|
|
|
enddef
|
|
|
|
|
2023-01-27 13:16:19 +00:00
|
|
|
def Test_class_interface_wrong_end()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
abstract class SomeName
|
|
|
|
this.member = 'text'
|
|
|
|
endinterface
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E476: Invalid command: endinterface, expected endclass')
|
2023-01-27 13:16:19 +00:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
export interface AnotherName
|
|
|
|
this.member: string
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E476: Invalid command: endclass, expected endinterface')
|
2023-01-27 13:16:19 +00:00
|
|
|
enddef
|
|
|
|
|
2023-02-17 21:08:50 +00:00
|
|
|
def Test_object_not_set()
|
2023-09-18 19:56:49 +02:00
|
|
|
# Use an uninitialized object in script context
|
2023-02-17 21:08:50 +00:00
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class State
|
|
|
|
this.value = 'xyz'
|
|
|
|
endclass
|
|
|
|
|
2023-02-17 21:29:57 +00:00
|
|
|
var state: State
|
2023-02-17 21:08:50 +00:00
|
|
|
var db = {'xyz': 789}
|
|
|
|
echo db[state.value]
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1360:')
|
2023-02-18 14:42:44 +00:00
|
|
|
|
2023-09-18 19:56:49 +02:00
|
|
|
# Use an uninitialized object from a def function
|
2023-03-02 17:38:33 +00:00
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class Class
|
|
|
|
this.id: string
|
|
|
|
def Method1()
|
|
|
|
echo 'Method1' .. this.id
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var obj: Class
|
|
|
|
def Func()
|
|
|
|
obj.Method1()
|
|
|
|
enddef
|
|
|
|
Func()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1360:')
|
2023-03-02 17:38:33 +00:00
|
|
|
|
2023-09-18 19:56:49 +02:00
|
|
|
# Pass an uninitialized object variable to a "new" function and try to call an
|
|
|
|
# object method.
|
2023-02-18 14:42:44 +00:00
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class Background
|
|
|
|
this.background = 'dark'
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class Colorscheme
|
|
|
|
this._bg: Background
|
|
|
|
|
|
|
|
def GetBackground(): string
|
|
|
|
return this._bg.background
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var bg: Background # UNINITIALIZED
|
|
|
|
echo Colorscheme.new(bg).GetBackground()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1360:')
|
2023-03-03 15:05:30 +00:00
|
|
|
|
|
|
|
# TODO: this should not give an error but be handled at runtime
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class Class
|
|
|
|
this.id: string
|
|
|
|
def Method1()
|
|
|
|
echo 'Method1' .. this.id
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var obj = null_object
|
|
|
|
def Func()
|
|
|
|
obj.Method1()
|
|
|
|
enddef
|
|
|
|
Func()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1363:')
|
2023-02-17 21:08:50 +00:00
|
|
|
enddef
|
|
|
|
|
2023-09-18 19:56:49 +02:00
|
|
|
" Null object assignment and comparison
|
2023-08-27 18:40:26 +02:00
|
|
|
def Test_null_object_assign_compare()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
var nullo = null_object
|
|
|
|
def F(): any
|
|
|
|
return nullo
|
|
|
|
enddef
|
|
|
|
assert_equal('object<Unknown>', typename(F()))
|
|
|
|
|
|
|
|
var o0 = F()
|
|
|
|
assert_true(o0 == null_object)
|
|
|
|
assert_true(o0 == null)
|
|
|
|
|
|
|
|
var o1: any = nullo
|
|
|
|
assert_true(o1 == null_object)
|
|
|
|
assert_true(o1 == null)
|
|
|
|
|
|
|
|
def G()
|
|
|
|
var x = null_object
|
|
|
|
enddef
|
|
|
|
|
|
|
|
class C
|
|
|
|
endclass
|
|
|
|
var o2: C
|
|
|
|
assert_true(o2 == null_object)
|
|
|
|
assert_true(o2 == null)
|
|
|
|
|
|
|
|
o2 = null_object
|
|
|
|
assert_true(o2 == null)
|
|
|
|
|
|
|
|
o2 = C.new()
|
|
|
|
assert_true(o2 != null)
|
|
|
|
|
|
|
|
o2 = null_object
|
|
|
|
assert_true(o2 == null)
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-08-27 18:40:26 +02:00
|
|
|
enddef
|
|
|
|
|
2023-09-18 19:56:49 +02:00
|
|
|
" Test for object member initialization and disassembly
|
2022-12-10 18:42:12 +00:00
|
|
|
def Test_class_member_initializer()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class TextPosition
|
|
|
|
this.lnum: number = 1
|
|
|
|
this.col: number = 1
|
|
|
|
|
2022-12-20 13:38:22 +00:00
|
|
|
# constructor with only the line number
|
2022-12-10 18:42:12 +00:00
|
|
|
def new(lnum: number)
|
|
|
|
this.lnum = lnum
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var pos = TextPosition.new(3)
|
|
|
|
assert_equal(3, pos.lnum)
|
|
|
|
assert_equal(1, pos.col)
|
|
|
|
|
|
|
|
var instr = execute('disassemble TextPosition.new')
|
|
|
|
assert_match('new\_s*' ..
|
2022-12-10 19:03:51 +00:00
|
|
|
'0 NEW TextPosition size \d\+\_s*' ..
|
2022-12-10 18:42:12 +00:00
|
|
|
'\d PUSHNR 1\_s*' ..
|
|
|
|
'\d STORE_THIS 0\_s*' ..
|
|
|
|
'\d PUSHNR 1\_s*' ..
|
|
|
|
'\d STORE_THIS 1\_s*' ..
|
|
|
|
'this.lnum = lnum\_s*' ..
|
|
|
|
'\d LOAD arg\[-1]\_s*' ..
|
|
|
|
'\d PUSHNR 0\_s*' ..
|
|
|
|
'\d LOAD $0\_s*' ..
|
|
|
|
'\d\+ STOREINDEX object\_s*' ..
|
|
|
|
'\d\+ RETURN object.*',
|
|
|
|
instr)
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2022-12-10 18:42:12 +00:00
|
|
|
enddef
|
|
|
|
|
2023-02-18 18:38:37 +00:00
|
|
|
def Test_member_any_used_as_object()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class Inner
|
|
|
|
this.value: number = 0
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class Outer
|
|
|
|
this.inner: any
|
|
|
|
endclass
|
|
|
|
|
|
|
|
def F(outer: Outer)
|
|
|
|
outer.inner.value = 1
|
|
|
|
enddef
|
|
|
|
|
|
|
|
var inner_obj = Inner.new(0)
|
|
|
|
var outer_obj = Outer.new(inner_obj)
|
|
|
|
F(outer_obj)
|
|
|
|
assert_equal(1, inner_obj.value)
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-02-18 18:38:37 +00:00
|
|
|
|
2023-09-15 20:14:55 +02:00
|
|
|
# Try modifying a private variable using an "any" object
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class Inner
|
|
|
|
this._value: string = ''
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class Outer
|
|
|
|
this.inner: any
|
|
|
|
endclass
|
|
|
|
|
|
|
|
def F(outer: Outer)
|
|
|
|
outer.inner._value = 'b'
|
|
|
|
enddef
|
|
|
|
|
|
|
|
var inner_obj = Inner.new('a')
|
|
|
|
var outer_obj = Outer.new(inner_obj)
|
|
|
|
F(outer_obj)
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1333: Cannot access private member: _value')
|
|
|
|
|
|
|
|
# Try modifying a non-existing variable using an "any" object
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class Inner
|
|
|
|
this.value: string = ''
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class Outer
|
|
|
|
this.inner: any
|
|
|
|
endclass
|
|
|
|
|
|
|
|
def F(outer: Outer)
|
|
|
|
outer.inner.someval = 'b'
|
|
|
|
enddef
|
|
|
|
|
|
|
|
var inner_obj = Inner.new('a')
|
|
|
|
var outer_obj = Outer.new(inner_obj)
|
|
|
|
F(outer_obj)
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1326: Member not found on object "Inner": someval')
|
2023-02-18 18:38:37 +00:00
|
|
|
enddef
|
|
|
|
|
2023-09-18 19:56:49 +02:00
|
|
|
" Nested assignment to a object variable which is of another class type
|
|
|
|
def Test_assignment_nested_type()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class Inner
|
|
|
|
public this.value: number = 0
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class Outer
|
|
|
|
this.inner: Inner
|
|
|
|
endclass
|
|
|
|
|
|
|
|
def F(outer: Outer)
|
|
|
|
outer.inner.value = 1
|
|
|
|
enddef
|
|
|
|
|
|
|
|
def Test_assign_to_nested_typed_member()
|
|
|
|
var inner = Inner.new(0)
|
|
|
|
var outer = Outer.new(inner)
|
|
|
|
F(outer)
|
|
|
|
assert_equal(1, inner.value)
|
|
|
|
enddef
|
|
|
|
|
|
|
|
Test_assign_to_nested_typed_member()
|
|
|
|
END
|
|
|
|
v9.CheckSourceSuccess(lines)
|
|
|
|
enddef
|
|
|
|
|
2023-01-15 15:51:48 +00:00
|
|
|
def Test_assignment_with_operator()
|
2023-09-18 19:56:49 +02:00
|
|
|
# Use "+=" to assign to a object variable
|
2023-01-15 15:51:48 +00:00
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class Foo
|
2023-08-31 18:10:46 +02:00
|
|
|
public this.x: number
|
2023-01-15 15:51:48 +00:00
|
|
|
|
|
|
|
def Add(n: number)
|
|
|
|
this.x += n
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var f = Foo.new(3)
|
|
|
|
f.Add(17)
|
|
|
|
assert_equal(20, f.x)
|
2023-04-24 17:15:25 +01:00
|
|
|
|
|
|
|
def AddToFoo(obj: Foo)
|
|
|
|
obj.x += 3
|
|
|
|
enddef
|
|
|
|
|
|
|
|
AddToFoo(f)
|
|
|
|
assert_equal(23, f.x)
|
2023-01-15 15:51:48 +00:00
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-09-04 22:30:41 +02:00
|
|
|
|
|
|
|
# do the same thing, but through an interface
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
interface I
|
|
|
|
public this.x: number
|
|
|
|
endinterface
|
|
|
|
|
|
|
|
class Foo implements I
|
|
|
|
public this.x: number
|
|
|
|
|
|
|
|
def Add(n: number)
|
|
|
|
var i: I = this
|
|
|
|
i.x += n
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var f = Foo.new(3)
|
|
|
|
f.Add(17)
|
|
|
|
assert_equal(20, f.x)
|
|
|
|
|
|
|
|
def AddToFoo(i: I)
|
|
|
|
i.x += 3
|
|
|
|
enddef
|
|
|
|
|
|
|
|
AddToFoo(f)
|
|
|
|
assert_equal(23, f.x)
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-01-15 15:51:48 +00:00
|
|
|
enddef
|
|
|
|
|
2023-01-15 16:54:57 +00:00
|
|
|
def Test_list_of_objects()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class Foo
|
|
|
|
def Add()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
def ProcessList(fooList: list<Foo>)
|
|
|
|
for foo in fooList
|
|
|
|
foo.Add()
|
|
|
|
endfor
|
|
|
|
enddef
|
|
|
|
|
|
|
|
var l: list<Foo> = [Foo.new()]
|
|
|
|
ProcessList(l)
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-01-15 16:54:57 +00:00
|
|
|
enddef
|
|
|
|
|
2023-01-15 20:18:55 +00:00
|
|
|
def Test_expr_after_using_object()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class Something
|
|
|
|
this.label: string = ''
|
|
|
|
endclass
|
|
|
|
|
|
|
|
def Foo(): Something
|
|
|
|
var v = Something.new()
|
|
|
|
echo 'in Foo(): ' .. typename(v)
|
|
|
|
return v
|
|
|
|
enddef
|
|
|
|
|
|
|
|
Foo()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-01-15 20:18:55 +00:00
|
|
|
enddef
|
|
|
|
|
2022-12-13 18:43:22 +00:00
|
|
|
def Test_class_default_new()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class TextPosition
|
|
|
|
this.lnum: number = 1
|
|
|
|
this.col: number = 1
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var pos = TextPosition.new()
|
|
|
|
assert_equal(1, pos.lnum)
|
|
|
|
assert_equal(1, pos.col)
|
|
|
|
|
|
|
|
pos = TextPosition.new(v:none, v:none)
|
|
|
|
assert_equal(1, pos.lnum)
|
|
|
|
assert_equal(1, pos.col)
|
|
|
|
|
|
|
|
pos = TextPosition.new(3, 22)
|
|
|
|
assert_equal(3, pos.lnum)
|
|
|
|
assert_equal(22, pos.col)
|
|
|
|
|
|
|
|
pos = TextPosition.new(v:none, 33)
|
|
|
|
assert_equal(1, pos.lnum)
|
|
|
|
assert_equal(33, pos.col)
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2022-12-13 18:43:22 +00:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class Person
|
|
|
|
this.name: string
|
|
|
|
this.age: number = 42
|
|
|
|
this.education: string = "unknown"
|
|
|
|
|
|
|
|
def new(this.name, this.age = v:none, this.education = v:none)
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var piet = Person.new("Piet")
|
|
|
|
assert_equal("Piet", piet.name)
|
|
|
|
assert_equal(42, piet.age)
|
|
|
|
assert_equal("unknown", piet.education)
|
|
|
|
|
|
|
|
var chris = Person.new("Chris", 4, "none")
|
|
|
|
assert_equal("Chris", chris.name)
|
|
|
|
assert_equal(4, chris.age)
|
|
|
|
assert_equal("none", chris.education)
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2022-12-13 21:14:28 +00:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class Person
|
|
|
|
this.name: string
|
|
|
|
this.age: number = 42
|
|
|
|
this.education: string = "unknown"
|
|
|
|
|
|
|
|
def new(this.name, this.age = v:none, this.education = v:none)
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var missing = Person.new()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E119:')
|
2023-09-17 17:03:19 +02:00
|
|
|
|
|
|
|
# Using a specific value to initialize an instance variable in the new()
|
|
|
|
# method.
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
this.val: string
|
|
|
|
def new(this.val = 'a')
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, "E1328: Constructor default value must be v:none: = 'a'")
|
2022-12-13 18:43:22 +00:00
|
|
|
enddef
|
|
|
|
|
2023-08-16 21:49:54 +09:00
|
|
|
def Test_class_new_with_object_member()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class C
|
|
|
|
this.str: string
|
|
|
|
this.num: number
|
|
|
|
def new(this.str, this.num)
|
|
|
|
enddef
|
|
|
|
def newVals(this.str, this.num)
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
def Check()
|
|
|
|
try
|
|
|
|
var c = C.new('cats', 2)
|
|
|
|
assert_equal('cats', c.str)
|
|
|
|
assert_equal(2, c.num)
|
|
|
|
|
|
|
|
c = C.newVals('dogs', 4)
|
|
|
|
assert_equal('dogs', c.str)
|
|
|
|
assert_equal(4, c.num)
|
|
|
|
catch
|
|
|
|
assert_report($'Unexpected exception was caught: {v:exception}')
|
|
|
|
endtry
|
|
|
|
enddef
|
|
|
|
|
|
|
|
Check()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-08-16 21:49:54 +09:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class C
|
|
|
|
this.str: string
|
|
|
|
this.num: number
|
|
|
|
def new(this.str, this.num)
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
def Check()
|
|
|
|
try
|
|
|
|
var c = C.new(1, 2)
|
|
|
|
catch
|
|
|
|
assert_report($'Unexpected exception was caught: {v:exception}')
|
|
|
|
endtry
|
|
|
|
enddef
|
|
|
|
|
|
|
|
Check()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1013:')
|
2023-08-16 21:49:54 +09:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class C
|
|
|
|
this.str: string
|
|
|
|
this.num: number
|
|
|
|
def newVals(this.str, this.num)
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
def Check()
|
|
|
|
try
|
|
|
|
var c = C.newVals('dogs', 'apes')
|
|
|
|
catch
|
|
|
|
assert_report($'Unexpected exception was caught: {v:exception}')
|
|
|
|
endtry
|
|
|
|
enddef
|
|
|
|
|
|
|
|
Check()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1013:')
|
2023-08-16 21:49:54 +09:00
|
|
|
enddef
|
|
|
|
|
2022-12-13 21:14:28 +00:00
|
|
|
def Test_class_object_member_inits()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class TextPosition
|
|
|
|
this.lnum: number
|
|
|
|
this.col = 1
|
|
|
|
this.addcol: number = 2
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var pos = TextPosition.new()
|
|
|
|
assert_equal(0, pos.lnum)
|
|
|
|
assert_equal(1, pos.col)
|
|
|
|
assert_equal(2, pos.addcol)
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2022-12-13 21:14:28 +00:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class TextPosition
|
|
|
|
this.lnum
|
|
|
|
this.col = 1
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1022:')
|
2022-12-13 21:14:28 +00:00
|
|
|
|
2023-08-22 21:29:28 +02:00
|
|
|
# If the type is not specified for a member, then it should be set during
|
|
|
|
# object creation and not when defining the class.
|
2022-12-13 21:14:28 +00:00
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
2023-08-22 21:29:28 +02:00
|
|
|
|
|
|
|
var init_count = 0
|
|
|
|
def Init(): string
|
|
|
|
init_count += 1
|
|
|
|
return 'foo'
|
|
|
|
enddef
|
|
|
|
|
|
|
|
class A
|
|
|
|
this.str1 = Init()
|
|
|
|
this.str2: string = Init()
|
2022-12-13 21:14:28 +00:00
|
|
|
this.col = 1
|
|
|
|
endclass
|
2023-08-22 21:29:28 +02:00
|
|
|
|
|
|
|
assert_equal(init_count, 0)
|
|
|
|
var a = A.new()
|
|
|
|
assert_equal(init_count, 2)
|
2022-12-13 21:14:28 +00:00
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-08-19 11:26:42 +02:00
|
|
|
|
|
|
|
# Test for initializing an object member with an unknown variable/type
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
this.value = init_val
|
|
|
|
endclass
|
2023-08-22 21:29:28 +02:00
|
|
|
var a = A.new()
|
2023-08-19 11:26:42 +02:00
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1001:')
|
2023-09-17 17:03:19 +02:00
|
|
|
|
|
|
|
# Test for initializing an object member with an special type
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
this.value: void
|
|
|
|
endclass
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1330: Invalid type for object member: void')
|
2022-12-13 21:14:28 +00:00
|
|
|
enddef
|
|
|
|
|
2023-09-15 20:14:55 +02:00
|
|
|
" Test for instance variable access
|
|
|
|
def Test_instance_variable_access()
|
2022-12-14 20:59:32 +00:00
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class Triple
|
|
|
|
this._one = 1
|
|
|
|
this.two = 2
|
|
|
|
public this.three = 3
|
|
|
|
|
|
|
|
def GetOne(): number
|
|
|
|
return this._one
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var trip = Triple.new()
|
|
|
|
assert_equal(1, trip.GetOne())
|
|
|
|
assert_equal(2, trip.two)
|
|
|
|
assert_equal(3, trip.three)
|
|
|
|
assert_fails('echo trip._one', 'E1333')
|
|
|
|
|
|
|
|
assert_fails('trip._one = 11', 'E1333')
|
|
|
|
assert_fails('trip.two = 22', 'E1335')
|
|
|
|
trip.three = 33
|
|
|
|
assert_equal(33, trip.three)
|
2022-12-18 21:42:55 +00:00
|
|
|
|
2023-09-15 20:14:55 +02:00
|
|
|
assert_fails('trip.four = 4', 'E1326')
|
2022-12-18 21:42:55 +00:00
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2022-12-24 21:24:06 +00:00
|
|
|
|
2023-08-19 11:26:42 +02:00
|
|
|
# Test for a public member variable name beginning with an underscore
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
public this._val = 10
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1332:')
|
2023-08-19 11:26:42 +02:00
|
|
|
|
2022-12-24 21:24:06 +00:00
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class MyCar
|
|
|
|
this.make: string
|
2023-01-03 19:08:50 +00:00
|
|
|
this.age = 5
|
2022-12-24 21:24:06 +00:00
|
|
|
|
|
|
|
def new(make_arg: string)
|
|
|
|
this.make = make_arg
|
|
|
|
enddef
|
|
|
|
|
|
|
|
def GetMake(): string
|
|
|
|
return $"make = {this.make}"
|
|
|
|
enddef
|
2023-01-03 19:08:50 +00:00
|
|
|
def GetAge(): number
|
|
|
|
return this.age
|
|
|
|
enddef
|
2022-12-24 21:24:06 +00:00
|
|
|
endclass
|
|
|
|
|
|
|
|
var c = MyCar.new("abc")
|
|
|
|
assert_equal('make = abc', c.GetMake())
|
|
|
|
|
|
|
|
c = MyCar.new("def")
|
|
|
|
assert_equal('make = def', c.GetMake())
|
|
|
|
|
|
|
|
var c2 = MyCar.new("123")
|
|
|
|
assert_equal('make = 123', c2.GetMake())
|
2023-01-03 19:08:50 +00:00
|
|
|
|
|
|
|
def CheckCar()
|
|
|
|
assert_equal("make = def", c.GetMake())
|
|
|
|
assert_equal(5, c.GetAge())
|
|
|
|
enddef
|
|
|
|
CheckCar()
|
2022-12-24 21:24:06 +00:00
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2022-12-25 19:31:36 +00:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class MyCar
|
|
|
|
this.make: string
|
|
|
|
|
|
|
|
def new(make_arg: string)
|
|
|
|
this.make = make_arg
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var c = MyCar.new("abc")
|
|
|
|
var c = MyCar.new("def")
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1041:')
|
2023-01-24 13:03:37 +00:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class Foo
|
|
|
|
this.x: list<number> = []
|
|
|
|
|
|
|
|
def Add(n: number): any
|
|
|
|
this.x->add(n)
|
|
|
|
return this
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
echo Foo.new().Add(1).Add(2).x
|
|
|
|
echo Foo.new().Add(1).Add(2)
|
|
|
|
.x
|
|
|
|
echo Foo.new().Add(1)
|
|
|
|
.Add(2).x
|
|
|
|
echo Foo.new()
|
|
|
|
.Add(1).Add(2).x
|
|
|
|
echo Foo.new()
|
|
|
|
.Add(1)
|
|
|
|
.Add(2)
|
|
|
|
.x
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-08-19 11:26:42 +02:00
|
|
|
|
|
|
|
# Test for "public" cannot be abbreviated
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class Something
|
|
|
|
pub this.val = 1
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1065:')
|
2023-08-19 11:26:42 +02:00
|
|
|
|
|
|
|
# Test for "public" keyword must be followed by "this" or "static".
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class Something
|
|
|
|
public val = 1
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1331:')
|
2023-08-19 11:26:42 +02:00
|
|
|
|
2023-09-15 20:14:55 +02:00
|
|
|
# Modify a instance variable using the class name in the script context
|
2023-08-19 11:26:42 +02:00
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
2023-09-15 20:14:55 +02:00
|
|
|
class A
|
|
|
|
public this.val = 1
|
2023-08-19 11:26:42 +02:00
|
|
|
endclass
|
2023-09-15 20:14:55 +02:00
|
|
|
A.val = 1
|
2023-08-19 11:26:42 +02:00
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1376: Object member "val" accessible only using class "A" object')
|
2023-08-28 21:26:23 +02:00
|
|
|
|
2023-09-15 20:14:55 +02:00
|
|
|
# Read a instance variable using the class name in the script context
|
2023-08-28 21:26:23 +02:00
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
2023-09-15 20:14:55 +02:00
|
|
|
class A
|
|
|
|
public this.val = 1
|
|
|
|
endclass
|
|
|
|
var i = A.val
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1376: Object member "val" accessible only using class "A" object')
|
|
|
|
|
|
|
|
# Modify a instance variable using the class name in a def function
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
public this.val = 1
|
|
|
|
endclass
|
|
|
|
def T()
|
|
|
|
A.val = 1
|
|
|
|
enddef
|
|
|
|
T()
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1376: Object member "val" accessible only using class "A" object')
|
|
|
|
|
|
|
|
# Read a instance variable using the class name in a def function
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
public this.val = 1
|
2023-08-28 21:26:23 +02:00
|
|
|
endclass
|
2023-09-15 20:14:55 +02:00
|
|
|
def T()
|
|
|
|
var i = A.val
|
|
|
|
enddef
|
|
|
|
T()
|
2023-08-28 21:26:23 +02:00
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1376: Object member "val" accessible only using class "A" object')
|
2023-09-06 20:45:03 +02:00
|
|
|
|
|
|
|
# Access from child class extending a class:
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
this.ro_obj_var = 10
|
|
|
|
public this.rw_obj_var = 20
|
|
|
|
this._priv_obj_var = 30
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class B extends A
|
|
|
|
def Foo()
|
|
|
|
var x: number
|
|
|
|
x = this.ro_obj_var
|
|
|
|
this.ro_obj_var = 0
|
|
|
|
x = this.rw_obj_var
|
|
|
|
this.rw_obj_var = 0
|
|
|
|
x = this._priv_obj_var
|
|
|
|
this._priv_obj_var = 0
|
2023-09-15 20:14:55 +02:00
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var b = B.new()
|
|
|
|
b.Foo()
|
|
|
|
END
|
|
|
|
v9.CheckSourceSuccess(lines)
|
|
|
|
enddef
|
|
|
|
|
|
|
|
" Test for class variable access
|
|
|
|
def Test_class_variable_access()
|
|
|
|
# Test for "static" cannot be abbreviated
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class Something
|
|
|
|
stat this.val = 1
|
|
|
|
endclass
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1065:')
|
|
|
|
|
|
|
|
# Test for "static" cannot be followed by "this".
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class Something
|
|
|
|
static this.val = 1
|
|
|
|
endclass
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1368: Static cannot be followed by "this" in a member name')
|
|
|
|
|
|
|
|
# Test for "static" cannot be followed by "public".
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class Something
|
|
|
|
static public val = 1
|
|
|
|
endclass
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1022: Type or initialization required')
|
|
|
|
|
|
|
|
# A readonly class variable cannot be modified from a child class
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
static ro_class_var = 40
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class B extends A
|
|
|
|
def Foo()
|
|
|
|
A.ro_class_var = 50
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var b = B.new()
|
|
|
|
b.Foo()
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E46: Cannot change read-only variable "ro_class_var"')
|
|
|
|
|
|
|
|
# A private class variable cannot be accessed from a child class
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
static _priv_class_var = 60
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class B extends A
|
|
|
|
def Foo()
|
|
|
|
var i = A._priv_class_var
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var b = B.new()
|
|
|
|
b.Foo()
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1333: Cannot access private member: _priv_class_var')
|
|
|
|
|
|
|
|
# A private class variable cannot be modified from a child class
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
static _priv_class_var = 60
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class B extends A
|
|
|
|
def Foo()
|
|
|
|
A._priv_class_var = 0
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var b = B.new()
|
|
|
|
b.Foo()
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1333: Cannot access private member: _priv_class_var')
|
2023-09-06 20:45:03 +02:00
|
|
|
|
2023-09-15 20:14:55 +02:00
|
|
|
# Access from child class extending a class and from script context
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
static ro_class_var = 10
|
|
|
|
public static rw_class_var = 20
|
|
|
|
static _priv_class_var = 30
|
|
|
|
endclass
|
2023-09-06 20:45:03 +02:00
|
|
|
|
2023-09-15 20:14:55 +02:00
|
|
|
class B extends A
|
|
|
|
def Foo()
|
|
|
|
var x: number
|
2023-09-06 20:45:03 +02:00
|
|
|
x = A.ro_class_var
|
2023-09-15 20:14:55 +02:00
|
|
|
assert_equal(10, x)
|
2023-09-06 20:45:03 +02:00
|
|
|
x = A.rw_class_var
|
2023-09-15 20:14:55 +02:00
|
|
|
assert_equal(25, x)
|
|
|
|
A.rw_class_var = 20
|
|
|
|
assert_equal(20, A.rw_class_var)
|
2023-09-06 20:45:03 +02:00
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
2023-09-15 20:14:55 +02:00
|
|
|
assert_equal(10, A.ro_class_var)
|
|
|
|
assert_equal(20, A.rw_class_var)
|
|
|
|
A.rw_class_var = 25
|
|
|
|
assert_equal(25, A.rw_class_var)
|
2023-09-06 20:45:03 +02:00
|
|
|
var b = B.new()
|
|
|
|
b.Foo()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2022-12-18 21:42:55 +00:00
|
|
|
enddef
|
|
|
|
|
2023-01-02 20:32:24 +00:00
|
|
|
def Test_class_object_compare()
|
|
|
|
var class_lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class Item
|
|
|
|
this.nr = 0
|
|
|
|
this.name = 'xx'
|
|
|
|
endclass
|
|
|
|
END
|
|
|
|
|
|
|
|
# used at the script level and in a compiled function
|
|
|
|
var test_lines =<< trim END
|
|
|
|
var i1 = Item.new()
|
|
|
|
assert_equal(i1, i1)
|
|
|
|
assert_true(i1 is i1)
|
|
|
|
var i2 = Item.new()
|
|
|
|
assert_equal(i1, i2)
|
|
|
|
assert_false(i1 is i2)
|
|
|
|
var i3 = Item.new(0, 'xx')
|
|
|
|
assert_equal(i1, i3)
|
|
|
|
|
|
|
|
var io1 = Item.new(1, 'xx')
|
|
|
|
assert_notequal(i1, io1)
|
|
|
|
var io2 = Item.new(0, 'yy')
|
|
|
|
assert_notequal(i1, io2)
|
|
|
|
END
|
|
|
|
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(class_lines + test_lines)
|
|
|
|
v9.CheckSourceSuccess(
|
2023-01-03 14:01:21 +00:00
|
|
|
class_lines + ['def Test()'] + test_lines + ['enddef', 'Test()'])
|
2023-01-02 20:32:24 +00:00
|
|
|
|
|
|
|
for op in ['>', '>=', '<', '<=', '=~', '!~']
|
|
|
|
var op_lines = [
|
|
|
|
'var i1 = Item.new()',
|
|
|
|
'var i2 = Item.new()',
|
|
|
|
'echo i1 ' .. op .. ' i2',
|
|
|
|
]
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(class_lines + op_lines, 'E1153: Invalid operation for object')
|
|
|
|
v9.CheckSourceFailure(class_lines
|
2023-01-03 14:01:21 +00:00
|
|
|
+ ['def Test()'] + op_lines + ['enddef', 'Test()'], 'E1153: Invalid operation for object')
|
2023-01-02 20:32:24 +00:00
|
|
|
endfor
|
|
|
|
enddef
|
|
|
|
|
2023-01-11 21:14:17 +00:00
|
|
|
def Test_object_type()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class One
|
|
|
|
this.one = 1
|
|
|
|
endclass
|
|
|
|
class Two
|
|
|
|
this.two = 2
|
|
|
|
endclass
|
|
|
|
class TwoMore extends Two
|
|
|
|
this.more = 9
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var o: One = One.new()
|
|
|
|
var t: Two = Two.new()
|
|
|
|
var m: TwoMore = TwoMore.new()
|
|
|
|
var tm: Two = TwoMore.new()
|
|
|
|
|
|
|
|
t = m
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-01-11 21:14:17 +00:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class One
|
|
|
|
this.one = 1
|
|
|
|
endclass
|
|
|
|
class Two
|
|
|
|
this.two = 2
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var o: One = Two.new()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected object<One> but got object<Two>')
|
2023-01-12 15:01:32 +00:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
interface One
|
|
|
|
def GetMember(): number
|
|
|
|
endinterface
|
|
|
|
class Two implements One
|
|
|
|
this.one = 1
|
|
|
|
def GetMember(): number
|
|
|
|
return this.one
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var o: One = Two.new(5)
|
|
|
|
assert_equal(5, o.GetMember())
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-01-16 16:39:37 +00:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class Num
|
|
|
|
this.n: number = 0
|
|
|
|
endclass
|
|
|
|
|
|
|
|
def Ref(name: string): func(Num): Num
|
|
|
|
return (arg: Num): Num => {
|
|
|
|
return eval(name)(arg)
|
|
|
|
}
|
|
|
|
enddef
|
|
|
|
|
|
|
|
const Fn = Ref('Double')
|
|
|
|
var Double = (m: Num): Num => Num.new(m.n * 2)
|
|
|
|
|
|
|
|
echo Fn(Num.new(4))
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-01-11 21:14:17 +00:00
|
|
|
enddef
|
|
|
|
|
2023-01-01 19:53:30 +00:00
|
|
|
def Test_class_member()
|
|
|
|
# check access rules
|
2022-12-18 21:42:55 +00:00
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class TextPos
|
|
|
|
this.lnum = 1
|
|
|
|
this.col = 1
|
|
|
|
static counter = 0
|
2022-12-31 19:01:02 +00:00
|
|
|
static _secret = 7
|
|
|
|
public static anybody = 42
|
2022-12-18 21:42:55 +00:00
|
|
|
|
2023-01-01 12:58:33 +00:00
|
|
|
static def AddToCounter(nr: number)
|
2022-12-18 21:42:55 +00:00
|
|
|
counter += nr
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
assert_equal(0, TextPos.counter)
|
|
|
|
TextPos.AddToCounter(3)
|
|
|
|
assert_equal(3, TextPos.counter)
|
2023-09-15 20:14:55 +02:00
|
|
|
assert_fails('echo TextPos.noSuchMember', 'E1337:')
|
2023-01-28 19:19:03 +00:00
|
|
|
|
2023-01-04 18:54:09 +00:00
|
|
|
def GetCounter(): number
|
|
|
|
return TextPos.counter
|
|
|
|
enddef
|
|
|
|
assert_equal(3, GetCounter())
|
2022-12-18 21:42:55 +00:00
|
|
|
|
2022-12-23 17:56:27 +00:00
|
|
|
assert_fails('TextPos.noSuchMember = 2', 'E1337:')
|
2022-12-31 19:01:02 +00:00
|
|
|
assert_fails('TextPos.counter = 5', 'E1335:')
|
|
|
|
assert_fails('TextPos.counter += 5', 'E1335:')
|
|
|
|
|
|
|
|
assert_fails('echo TextPos._secret', 'E1333:')
|
|
|
|
assert_fails('TextPos._secret = 8', 'E1333:')
|
|
|
|
|
|
|
|
assert_equal(42, TextPos.anybody)
|
|
|
|
TextPos.anybody = 12
|
|
|
|
assert_equal(12, TextPos.anybody)
|
|
|
|
TextPos.anybody += 5
|
|
|
|
assert_equal(17, TextPos.anybody)
|
2022-12-14 20:59:32 +00:00
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-01-01 19:53:30 +00:00
|
|
|
|
2023-01-15 15:51:48 +00:00
|
|
|
# example in the help
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class OtherThing
|
|
|
|
this.size: number
|
|
|
|
static totalSize: number
|
|
|
|
|
|
|
|
def new(this.size)
|
|
|
|
totalSize += this.size
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
assert_equal(0, OtherThing.totalSize)
|
|
|
|
var to3 = OtherThing.new(3)
|
|
|
|
assert_equal(3, OtherThing.totalSize)
|
|
|
|
var to7 = OtherThing.new(7)
|
|
|
|
assert_equal(10, OtherThing.totalSize)
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-01-15 15:51:48 +00:00
|
|
|
|
2023-06-24 19:22:21 +01:00
|
|
|
# using static class member twice
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class HTML
|
|
|
|
static author: string = 'John Doe'
|
|
|
|
|
|
|
|
static def MacroSubstitute(s: string): string
|
|
|
|
return substitute(s, '{{author}}', author, 'gi')
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
assert_equal('some text', HTML.MacroSubstitute('some text'))
|
|
|
|
assert_equal('some text', HTML.MacroSubstitute('some text'))
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-06-24 19:22:21 +01:00
|
|
|
|
2023-01-24 15:07:04 +00:00
|
|
|
# access private member in lambda
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class Foo
|
|
|
|
this._x: number = 0
|
|
|
|
|
|
|
|
def Add(n: number): number
|
|
|
|
const F = (): number => this._x + n
|
|
|
|
return F()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var foo = Foo.new()
|
|
|
|
assert_equal(5, foo.Add(5))
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-01-24 15:07:04 +00:00
|
|
|
|
2023-05-19 19:01:17 +01:00
|
|
|
# access private member in lambda body
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class Foo
|
|
|
|
this._x: number = 6
|
|
|
|
|
|
|
|
def Add(n: number): number
|
|
|
|
var Lam = () => {
|
|
|
|
this._x = this._x + n
|
|
|
|
}
|
|
|
|
Lam()
|
|
|
|
return this._x
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var foo = Foo.new()
|
|
|
|
assert_equal(13, foo.Add(7))
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-05-19 19:01:17 +01:00
|
|
|
|
2023-01-01 19:53:30 +00:00
|
|
|
# check shadowing
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class Some
|
|
|
|
static count = 0
|
|
|
|
def Method(count: number)
|
|
|
|
echo count
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var s = Some.new()
|
|
|
|
s.Method(7)
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1340: Argument already declared in the class: count')
|
2023-01-01 19:53:30 +00:00
|
|
|
|
2023-09-19 20:34:05 +02:00
|
|
|
# Use a local variable in a method with the same name as a class variable
|
2023-01-01 19:53:30 +00:00
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class Some
|
|
|
|
static count = 0
|
|
|
|
def Method(arg: number)
|
|
|
|
var count = 3
|
|
|
|
echo arg count
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var s = Some.new()
|
|
|
|
s.Method(7)
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1341: Variable already declared in the class: count')
|
2023-08-19 11:26:42 +02:00
|
|
|
|
|
|
|
# Test for using an invalid type for a member variable
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
this.val: xxx
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1010:')
|
2023-08-19 11:26:42 +02:00
|
|
|
|
2023-08-31 18:15:26 +02:00
|
|
|
# Test for setting a member on a null object
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
2023-08-31 20:55:35 +02:00
|
|
|
public this.val: string
|
2023-08-31 18:15:26 +02:00
|
|
|
endclass
|
|
|
|
|
|
|
|
def F()
|
|
|
|
var obj: A
|
|
|
|
obj.val = ""
|
|
|
|
enddef
|
|
|
|
F()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1360: Using a null object')
|
2023-08-31 18:15:26 +02:00
|
|
|
|
|
|
|
# Test for accessing a member on a null object
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
this.val: string
|
|
|
|
endclass
|
|
|
|
|
|
|
|
def F()
|
|
|
|
var obj: A
|
|
|
|
echo obj.val
|
|
|
|
enddef
|
|
|
|
F()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1360: Using a null object')
|
2023-08-31 18:15:26 +02:00
|
|
|
|
|
|
|
# Test for setting a member on a null object, at script level
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
2023-08-31 20:55:35 +02:00
|
|
|
public this.val: string
|
2023-08-31 18:15:26 +02:00
|
|
|
endclass
|
|
|
|
|
|
|
|
var obj: A
|
|
|
|
obj.val = ""
|
|
|
|
END
|
|
|
|
# FIXME(in source): this should give E1360 as well!
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected object<A> but got string')
|
2023-08-31 18:15:26 +02:00
|
|
|
|
|
|
|
# Test for accessing a member on a null object, at script level
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
this.val: string
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var obj: A
|
|
|
|
echo obj.val
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1360: Using a null object')
|
2023-08-31 18:15:26 +02:00
|
|
|
|
2023-08-19 11:26:42 +02:00
|
|
|
# Test for no space before or after the '=' when initializing a member
|
|
|
|
# variable
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
this.val: number= 10
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1004:')
|
2023-08-19 11:26:42 +02:00
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
this.val: number =10
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1004:')
|
2023-08-19 11:26:42 +02:00
|
|
|
|
|
|
|
# Access a non-existing member
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
endclass
|
|
|
|
var a = A.new()
|
|
|
|
var v = a.bar
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1326: Member not found on object "A": bar')
|
2022-12-14 20:59:32 +00:00
|
|
|
enddef
|
|
|
|
|
2023-01-05 13:16:04 +00:00
|
|
|
func Test_class_garbagecollect()
|
|
|
|
let lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class Point
|
|
|
|
this.p = [2, 3]
|
|
|
|
static pl = ['a', 'b']
|
|
|
|
static pd = {a: 'a', b: 'b'}
|
|
|
|
endclass
|
|
|
|
|
|
|
|
echo Point.pl Point.pd
|
|
|
|
call test_garbagecollect_now()
|
|
|
|
echo Point.pl Point.pd
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
call v9.CheckSourceSuccess(lines)
|
2023-06-05 16:53:25 +01:00
|
|
|
|
|
|
|
let lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
interface View
|
|
|
|
endinterface
|
|
|
|
|
|
|
|
class Widget
|
|
|
|
this.view: View
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class MyView implements View
|
|
|
|
this.widget: Widget
|
|
|
|
|
|
|
|
def new()
|
|
|
|
# this will result in a circular reference to this object
|
|
|
|
this.widget = Widget.new(this)
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var view = MyView.new()
|
|
|
|
|
|
|
|
# overwrite "view", will be garbage-collected next
|
|
|
|
view = MyView.new()
|
|
|
|
test_garbagecollect_now()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
call v9.CheckSourceSuccess(lines)
|
2023-01-05 13:16:04 +00:00
|
|
|
endfunc
|
|
|
|
|
2023-09-04 22:14:28 +02:00
|
|
|
" Test interface garbage collection
|
|
|
|
func Test_interface_garbagecollect()
|
|
|
|
let lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
interface I
|
|
|
|
this.ro_obj_var: number
|
|
|
|
public this.rw_obj_var: number
|
|
|
|
|
|
|
|
def ObjFoo(): number
|
|
|
|
endinterface
|
|
|
|
|
|
|
|
class A implements I
|
|
|
|
static ro_class_var: number = 10
|
|
|
|
public static rw_class_var: number = 20
|
|
|
|
static _priv_class_var: number = 30
|
|
|
|
this.ro_obj_var: number = 40
|
|
|
|
public this.rw_obj_var: number = 50
|
|
|
|
this._priv_obj_var: number = 60
|
|
|
|
|
|
|
|
static def _ClassBar(): number
|
|
|
|
return _priv_class_var
|
|
|
|
enddef
|
|
|
|
|
|
|
|
static def ClassFoo(): number
|
|
|
|
return ro_class_var + rw_class_var + A._ClassBar()
|
|
|
|
enddef
|
|
|
|
|
|
|
|
def _ObjBar(): number
|
|
|
|
return this._priv_obj_var
|
|
|
|
enddef
|
|
|
|
|
|
|
|
def ObjFoo(): number
|
|
|
|
return this.ro_obj_var + this.rw_obj_var + this._ObjBar()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
assert_equal(60, A.ClassFoo())
|
|
|
|
var o = A.new()
|
|
|
|
assert_equal(150, o.ObjFoo())
|
|
|
|
test_garbagecollect_now()
|
|
|
|
assert_equal(60, A.ClassFoo())
|
|
|
|
assert_equal(150, o.ObjFoo())
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
call v9.CheckSourceSuccess(lines)
|
2023-09-04 22:14:28 +02:00
|
|
|
endfunc
|
|
|
|
|
2023-09-18 19:56:49 +02:00
|
|
|
def Test_class_method()
|
2023-01-01 12:58:33 +00:00
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class Value
|
|
|
|
this.value = 0
|
|
|
|
static objects = 0
|
|
|
|
|
|
|
|
def new(v: number)
|
|
|
|
this.value = v
|
|
|
|
++objects
|
|
|
|
enddef
|
|
|
|
|
|
|
|
static def GetCount(): number
|
|
|
|
return objects
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
assert_equal(0, Value.GetCount())
|
|
|
|
var v1 = Value.new(2)
|
|
|
|
assert_equal(1, Value.GetCount())
|
|
|
|
var v2 = Value.new(7)
|
|
|
|
assert_equal(2, Value.GetCount())
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-08-19 11:26:42 +02:00
|
|
|
|
|
|
|
# Test for cleaning up after a class definition failure when using class
|
|
|
|
# functions.
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
static def Foo()
|
|
|
|
enddef
|
|
|
|
aaa
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1318:')
|
2023-09-18 19:56:49 +02:00
|
|
|
|
|
|
|
# Test for calling a class method from another class method without the class
|
|
|
|
# name prefix.
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
static myList: list<number> = [1]
|
|
|
|
static def Foo(n: number)
|
|
|
|
myList->add(n)
|
|
|
|
enddef
|
|
|
|
static def Bar()
|
|
|
|
Foo(2)
|
|
|
|
enddef
|
|
|
|
def Baz()
|
|
|
|
Foo(3)
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
A.Bar()
|
|
|
|
var a = A.new()
|
|
|
|
a.Baz()
|
|
|
|
assert_equal([1, 2, 3], A.myList)
|
|
|
|
END
|
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-01-01 12:58:33 +00:00
|
|
|
enddef
|
|
|
|
|
2023-02-21 19:55:14 +00:00
|
|
|
def Test_class_defcompile()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class C
|
|
|
|
def Fo(i: number): string
|
|
|
|
return i
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
defcompile C.Fo
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected string but got number')
|
2023-02-21 19:55:14 +00:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class C
|
|
|
|
static def Fc(): number
|
|
|
|
return 'x'
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
defcompile C.Fc
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected number but got string')
|
2023-08-19 11:26:42 +02:00
|
|
|
|
2023-08-29 22:26:30 +02:00
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class C
|
|
|
|
static def new()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
defcompile C.new
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1370: Cannot define a "new" function as static')
|
2023-08-29 22:26:30 +02:00
|
|
|
|
2023-08-19 11:26:42 +02:00
|
|
|
# Trying to compile a function using a non-existing class variable
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
defcompile x.Foo()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E475:')
|
2023-08-19 11:26:42 +02:00
|
|
|
|
|
|
|
# Trying to compile a function using a variable which is not a class
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
var x: number
|
|
|
|
defcompile x.Foo()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E475:')
|
2023-08-19 11:26:42 +02:00
|
|
|
|
|
|
|
# Trying to compile a function without specifying the name
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
endclass
|
|
|
|
defcompile A.
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E475:')
|
2023-08-19 11:26:42 +02:00
|
|
|
|
|
|
|
# Trying to compile a non-existing class object member function
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
endclass
|
|
|
|
var a = A.new()
|
|
|
|
defcompile a.Foo()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailureList(lines, ['E1326:', 'E475:'])
|
2023-02-21 19:55:14 +00:00
|
|
|
enddef
|
|
|
|
|
2022-12-14 17:30:37 +00:00
|
|
|
def Test_class_object_to_string()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class TextPosition
|
|
|
|
this.lnum = 1
|
|
|
|
this.col = 22
|
|
|
|
endclass
|
|
|
|
|
|
|
|
assert_equal("class TextPosition", string(TextPosition))
|
|
|
|
|
|
|
|
var pos = TextPosition.new()
|
|
|
|
assert_equal("object of TextPosition {lnum: 1, col: 22}", string(pos))
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2022-12-14 17:30:37 +00:00
|
|
|
enddef
|
2022-12-13 21:14:28 +00:00
|
|
|
|
2023-01-05 19:59:18 +00:00
|
|
|
def Test_interface_basics()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
interface Something
|
2023-09-17 17:03:19 +02:00
|
|
|
this.ro_var: string
|
|
|
|
public this.rw_var: list<number>
|
2023-01-05 19:59:18 +00:00
|
|
|
def GetCount(): number
|
|
|
|
endinterface
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-01-05 19:59:18 +00:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
interface SomethingWrong
|
|
|
|
static count = 7
|
|
|
|
endinterface
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1342:')
|
2023-01-05 19:59:18 +00:00
|
|
|
|
2023-01-13 17:36:49 +00:00
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
interface Some
|
|
|
|
this.value: number
|
|
|
|
def Method(value: number)
|
|
|
|
endinterface
|
|
|
|
END
|
2023-04-18 19:07:29 +01:00
|
|
|
# The argument name and the object member name are the same, but this is not a
|
|
|
|
# problem because object members are always accessed with the "this." prefix.
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-01-05 19:59:18 +00:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
interface somethingWrong
|
|
|
|
static count = 7
|
|
|
|
endinterface
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1343: Interface name must start with an uppercase letter: somethingWrong')
|
2023-01-05 19:59:18 +00:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
interface SomethingWrong
|
|
|
|
this.value: string
|
2023-09-17 17:03:19 +02:00
|
|
|
this.count = 7
|
2023-01-05 19:59:18 +00:00
|
|
|
def GetCount(): number
|
|
|
|
endinterface
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1344:')
|
2023-01-05 19:59:18 +00:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
interface SomethingWrong
|
|
|
|
this.value: string
|
2023-09-17 17:03:19 +02:00
|
|
|
this.count: number
|
2023-01-05 19:59:18 +00:00
|
|
|
def GetCount(): number
|
|
|
|
return 5
|
|
|
|
enddef
|
|
|
|
endinterface
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1345: Not a valid command in an interface: return 5')
|
2023-01-26 20:36:56 +00:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
export interface EnterExit
|
|
|
|
def Enter(): void
|
|
|
|
def Exit(): void
|
|
|
|
endinterface
|
|
|
|
END
|
|
|
|
writefile(lines, 'XdefIntf.vim', 'D')
|
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
import './XdefIntf.vim' as defIntf
|
|
|
|
export def With(ee: defIntf.EnterExit, F: func)
|
|
|
|
ee.Enter()
|
|
|
|
try
|
|
|
|
F()
|
|
|
|
finally
|
|
|
|
ee.Exit()
|
|
|
|
endtry
|
|
|
|
enddef
|
|
|
|
END
|
|
|
|
v9.CheckScriptSuccess(lines)
|
2023-01-27 13:16:19 +00:00
|
|
|
|
|
|
|
var imported =<< trim END
|
|
|
|
vim9script
|
|
|
|
export abstract class EnterExit
|
|
|
|
def Enter(): void
|
|
|
|
enddef
|
|
|
|
def Exit(): void
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
END
|
|
|
|
writefile(imported, 'XdefIntf2.vim', 'D')
|
|
|
|
|
|
|
|
lines[1] = " import './XdefIntf2.vim' as defIntf"
|
|
|
|
v9.CheckScriptSuccess(lines)
|
2023-01-05 19:59:18 +00:00
|
|
|
enddef
|
|
|
|
|
2023-01-06 18:42:20 +00:00
|
|
|
def Test_class_implements_interface()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
interface Some
|
2023-09-17 17:03:19 +02:00
|
|
|
this.count: number
|
2023-01-06 18:42:20 +00:00
|
|
|
def Method(nr: number)
|
|
|
|
endinterface
|
|
|
|
|
|
|
|
class SomeImpl implements Some
|
2023-09-17 17:03:19 +02:00
|
|
|
this.count: number
|
2023-01-06 18:42:20 +00:00
|
|
|
def Method(nr: number)
|
|
|
|
echo nr
|
|
|
|
enddef
|
|
|
|
endclass
|
2023-01-07 14:51:03 +00:00
|
|
|
|
|
|
|
interface Another
|
|
|
|
this.member: string
|
|
|
|
endinterface
|
|
|
|
|
2023-02-25 19:59:31 +00:00
|
|
|
class AnotherImpl implements Some, Another
|
2023-01-07 14:51:03 +00:00
|
|
|
this.member = 'abc'
|
2023-09-17 17:03:19 +02:00
|
|
|
this.count = 20
|
2023-01-07 14:51:03 +00:00
|
|
|
def Method(nr: number)
|
|
|
|
echo nr
|
|
|
|
enddef
|
|
|
|
endclass
|
2023-01-06 18:42:20 +00:00
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-01-06 18:42:20 +00:00
|
|
|
|
2023-01-07 14:51:03 +00:00
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
interface Some
|
2023-09-17 17:03:19 +02:00
|
|
|
this.count: number
|
2023-01-07 14:51:03 +00:00
|
|
|
endinterface
|
|
|
|
|
|
|
|
class SomeImpl implements Some implements Some
|
2023-09-17 17:03:19 +02:00
|
|
|
this.count: number
|
2023-01-07 14:51:03 +00:00
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1350:')
|
2023-01-07 14:51:03 +00:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
interface Some
|
2023-09-17 17:03:19 +02:00
|
|
|
this.count: number
|
2023-01-07 14:51:03 +00:00
|
|
|
endinterface
|
|
|
|
|
|
|
|
class SomeImpl implements Some, Some
|
2023-09-17 17:03:19 +02:00
|
|
|
this.count: number
|
2023-01-07 14:51:03 +00:00
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1351: Duplicate interface after "implements": Some')
|
2023-01-07 14:51:03 +00:00
|
|
|
|
2023-01-06 18:42:20 +00:00
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
interface Some
|
2023-09-17 17:03:19 +02:00
|
|
|
this.counter: number
|
2023-01-06 18:42:20 +00:00
|
|
|
def Method(nr: number)
|
|
|
|
endinterface
|
|
|
|
|
|
|
|
class SomeImpl implements Some
|
2023-09-17 17:03:19 +02:00
|
|
|
this.count: number
|
2023-01-06 18:42:20 +00:00
|
|
|
def Method(nr: number)
|
|
|
|
echo nr
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-17 17:03:19 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1348: Member "counter" of interface "Some" is not implemented')
|
2023-01-06 18:42:20 +00:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
interface Some
|
2023-09-17 17:03:19 +02:00
|
|
|
this.count: number
|
2023-01-06 18:42:20 +00:00
|
|
|
def Methods(nr: number)
|
|
|
|
endinterface
|
|
|
|
|
|
|
|
class SomeImpl implements Some
|
2023-09-17 17:03:19 +02:00
|
|
|
this.count: number
|
2023-01-06 18:42:20 +00:00
|
|
|
def Method(nr: number)
|
|
|
|
echo nr
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-17 17:03:19 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1349: Method "Methods" of interface "Some" is not implemented')
|
2023-01-16 19:43:47 +00:00
|
|
|
|
|
|
|
# Check different order of members in class and interface works.
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
interface Result
|
2023-01-16 20:47:57 +00:00
|
|
|
public this.label: string
|
2023-01-16 19:43:47 +00:00
|
|
|
this.errpos: number
|
|
|
|
endinterface
|
|
|
|
|
|
|
|
# order of members is opposite of interface
|
|
|
|
class Failure implements Result
|
|
|
|
this.errpos: number = 42
|
2023-01-16 20:47:57 +00:00
|
|
|
public this.label: string = 'label'
|
2023-01-16 19:43:47 +00:00
|
|
|
endclass
|
|
|
|
|
|
|
|
def Test()
|
|
|
|
var result: Result = Failure.new()
|
|
|
|
|
|
|
|
assert_equal('label', result.label)
|
|
|
|
assert_equal(42, result.errpos)
|
2023-01-16 20:47:57 +00:00
|
|
|
|
|
|
|
result.label = 'different'
|
|
|
|
assert_equal('different', result.label)
|
|
|
|
assert_equal(42, result.errpos)
|
2023-01-16 19:43:47 +00:00
|
|
|
enddef
|
|
|
|
|
|
|
|
Test()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-08-19 11:26:42 +02:00
|
|
|
|
|
|
|
# Interface name after "extends" doesn't end in a space or NUL character
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
interface A
|
|
|
|
endinterface
|
|
|
|
class B extends A"
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1315:')
|
2023-08-19 11:26:42 +02:00
|
|
|
|
|
|
|
# Trailing characters after a class name
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A bbb
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E488:')
|
2023-08-19 11:26:42 +02:00
|
|
|
|
|
|
|
# using "implements" with a non-existing class
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A implements B
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1346:')
|
2023-08-19 11:26:42 +02:00
|
|
|
|
|
|
|
# using "implements" with a regular class
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
endclass
|
|
|
|
class B implements A
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1347:')
|
2023-08-19 11:26:42 +02:00
|
|
|
|
|
|
|
# using "implements" with a variable
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
var T: number = 10
|
|
|
|
class A implements T
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1347:')
|
2023-08-19 11:26:42 +02:00
|
|
|
|
2023-08-20 18:20:17 +02:00
|
|
|
# implements should be followed by a white space
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
interface A
|
|
|
|
endinterface
|
|
|
|
class B implements A;
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1315:')
|
2023-08-20 18:20:17 +02:00
|
|
|
|
2023-08-19 13:02:35 +02:00
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
interface One
|
|
|
|
def IsEven(nr: number): bool
|
|
|
|
endinterface
|
|
|
|
class Two implements One
|
|
|
|
def IsEven(nr: number): string
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-17 17:03:19 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1383: Method "IsEven": type mismatch, expected func(number): bool but got func(number): string')
|
2023-08-19 13:02:35 +02:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
interface One
|
|
|
|
def IsEven(nr: number): bool
|
|
|
|
endinterface
|
|
|
|
class Two implements One
|
|
|
|
def IsEven(nr: bool): bool
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-17 17:03:19 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1383: Method "IsEven": type mismatch, expected func(number): bool but got func(bool): bool')
|
2023-08-19 13:02:35 +02:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
interface One
|
|
|
|
def IsEven(nr: number): bool
|
|
|
|
endinterface
|
|
|
|
class Two implements One
|
|
|
|
def IsEven(nr: number, ...extra: list<number>): bool
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-17 17:03:19 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1383: Method "IsEven": type mismatch, expected func(number): bool but got func(number, ...list<number>): bool')
|
2023-09-06 20:45:03 +02:00
|
|
|
|
|
|
|
# access superclass interface members from subclass, mix variable order
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
interface I1
|
|
|
|
public this.mvar1: number
|
|
|
|
public this.mvar2: number
|
|
|
|
endinterface
|
|
|
|
|
|
|
|
# NOTE: the order is swapped
|
|
|
|
class A implements I1
|
|
|
|
public this.mvar2: number
|
|
|
|
public this.mvar1: number
|
|
|
|
public static svar2: number
|
|
|
|
public static svar1: number
|
|
|
|
def new()
|
|
|
|
svar1 = 11
|
|
|
|
svar2 = 12
|
|
|
|
this.mvar1 = 111
|
|
|
|
this.mvar2 = 112
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class B extends A
|
|
|
|
def new()
|
|
|
|
this.mvar1 = 121
|
|
|
|
this.mvar2 = 122
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class C extends B
|
|
|
|
def new()
|
|
|
|
this.mvar1 = 131
|
|
|
|
this.mvar2 = 132
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
def F2(i: I1): list<number>
|
|
|
|
return [ i.mvar1, i.mvar2 ]
|
|
|
|
enddef
|
|
|
|
|
|
|
|
var oa = A.new()
|
|
|
|
var ob = B.new()
|
|
|
|
var oc = C.new()
|
|
|
|
|
|
|
|
assert_equal([111, 112], F2(oa))
|
|
|
|
assert_equal([121, 122], F2(ob))
|
|
|
|
assert_equal([131, 132], F2(oc))
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-09-06 20:45:03 +02:00
|
|
|
|
|
|
|
# Access superclass interface members from subclass, mix variable order.
|
|
|
|
# Two interfaces, one on A, one on B; each has both kinds of variables
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
interface I1
|
|
|
|
public this.mvar1: number
|
|
|
|
public this.mvar2: number
|
|
|
|
endinterface
|
|
|
|
|
|
|
|
interface I2
|
|
|
|
public this.mvar3: number
|
|
|
|
public this.mvar4: number
|
|
|
|
endinterface
|
|
|
|
|
|
|
|
class A implements I1
|
|
|
|
public static svar1: number
|
|
|
|
public static svar2: number
|
|
|
|
public this.mvar1: number
|
|
|
|
public this.mvar2: number
|
|
|
|
def new()
|
|
|
|
svar1 = 11
|
|
|
|
svar2 = 12
|
|
|
|
this.mvar1 = 111
|
|
|
|
this.mvar2 = 112
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class B extends A implements I2
|
|
|
|
public static svar3: number
|
|
|
|
public static svar4: number
|
|
|
|
public this.mvar3: number
|
|
|
|
public this.mvar4: number
|
|
|
|
def new()
|
|
|
|
svar3 = 23
|
|
|
|
svar4 = 24
|
|
|
|
this.mvar1 = 121
|
|
|
|
this.mvar2 = 122
|
|
|
|
this.mvar3 = 123
|
|
|
|
this.mvar4 = 124
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class C extends B
|
|
|
|
public static svar5: number
|
|
|
|
def new()
|
|
|
|
svar5 = 1001
|
|
|
|
this.mvar1 = 131
|
|
|
|
this.mvar2 = 132
|
|
|
|
this.mvar3 = 133
|
|
|
|
this.mvar4 = 134
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
def F2(i: I1): list<number>
|
|
|
|
return [ i.mvar1, i.mvar2 ]
|
|
|
|
enddef
|
|
|
|
|
|
|
|
def F4(i: I2): list<number>
|
|
|
|
return [ i.mvar3, i.mvar4 ]
|
|
|
|
enddef
|
|
|
|
|
|
|
|
var oa = A.new()
|
|
|
|
var ob = B.new()
|
|
|
|
var oc = C.new()
|
|
|
|
|
|
|
|
assert_equal([[111, 112]], [F2(oa)])
|
|
|
|
assert_equal([[121, 122], [123, 124]], [F2(ob), F4(ob)])
|
|
|
|
assert_equal([[131, 132], [133, 134]], [F2(oc), F4(oc)])
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-01-06 18:42:20 +00:00
|
|
|
enddef
|
|
|
|
|
2023-01-28 15:19:40 +00:00
|
|
|
def Test_call_interface_method()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
interface Base
|
|
|
|
def Enter(): void
|
|
|
|
endinterface
|
|
|
|
|
|
|
|
class Child implements Base
|
|
|
|
def Enter(): void
|
|
|
|
g:result ..= 'child'
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
def F(obj: Base)
|
|
|
|
obj.Enter()
|
|
|
|
enddef
|
|
|
|
|
|
|
|
g:result = ''
|
|
|
|
F(Child.new())
|
|
|
|
assert_equal('child', g:result)
|
|
|
|
unlet g:result
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-01-28 15:19:40 +00:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class Base
|
|
|
|
def Enter(): void
|
|
|
|
g:result ..= 'base'
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class Child extends Base
|
|
|
|
def Enter(): void
|
|
|
|
g:result ..= 'child'
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
def F(obj: Base)
|
|
|
|
obj.Enter()
|
|
|
|
enddef
|
|
|
|
|
|
|
|
g:result = ''
|
|
|
|
F(Child.new())
|
|
|
|
assert_equal('child', g:result)
|
|
|
|
unlet g:result
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-01-30 20:24:23 +00:00
|
|
|
|
2023-02-04 15:45:27 +00:00
|
|
|
# method of interface returns a value
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
interface Base
|
|
|
|
def Enter(): string
|
|
|
|
endinterface
|
|
|
|
|
|
|
|
class Child implements Base
|
|
|
|
def Enter(): string
|
|
|
|
g:result ..= 'child'
|
|
|
|
return "/resource"
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
def F(obj: Base)
|
|
|
|
var r = obj.Enter()
|
|
|
|
g:result ..= r
|
|
|
|
enddef
|
|
|
|
|
|
|
|
g:result = ''
|
|
|
|
F(Child.new())
|
|
|
|
assert_equal('child/resource', g:result)
|
|
|
|
unlet g:result
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-02-04 15:45:27 +00:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class Base
|
|
|
|
def Enter(): string
|
|
|
|
return null_string
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class Child extends Base
|
|
|
|
def Enter(): string
|
|
|
|
g:result ..= 'child'
|
|
|
|
return "/resource"
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
def F(obj: Base)
|
|
|
|
var r = obj.Enter()
|
|
|
|
g:result ..= r
|
|
|
|
enddef
|
|
|
|
|
|
|
|
g:result = ''
|
|
|
|
F(Child.new())
|
|
|
|
assert_equal('child/resource', g:result)
|
|
|
|
unlet g:result
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-02-04 15:45:27 +00:00
|
|
|
|
2023-01-30 20:24:23 +00:00
|
|
|
# No class that implements the interface.
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
interface IWithEE
|
|
|
|
def Enter(): any
|
|
|
|
def Exit(): void
|
|
|
|
endinterface
|
|
|
|
|
|
|
|
def With1(ee: IWithEE, F: func)
|
|
|
|
var r = ee.Enter()
|
|
|
|
enddef
|
|
|
|
|
|
|
|
defcompile
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-01-28 15:19:40 +00:00
|
|
|
enddef
|
|
|
|
|
2023-01-07 12:08:41 +00:00
|
|
|
def Test_class_used_as_type()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class Point
|
|
|
|
this.x = 0
|
|
|
|
this.y = 0
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var p: Point
|
|
|
|
p = Point.new(2, 33)
|
|
|
|
assert_equal(2, p.x)
|
|
|
|
assert_equal(33, p.y)
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-01-07 12:08:41 +00:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
interface HasX
|
|
|
|
this.x: number
|
|
|
|
endinterface
|
|
|
|
|
|
|
|
class Point implements HasX
|
|
|
|
this.x = 0
|
|
|
|
this.y = 0
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var p: Point
|
|
|
|
p = Point.new(2, 33)
|
|
|
|
var hx = p
|
|
|
|
assert_equal(2, hx.x)
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-01-07 12:08:41 +00:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class Point
|
|
|
|
this.x = 0
|
|
|
|
this.y = 0
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var p: Point
|
|
|
|
p = 'text'
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected object<Point> but got string')
|
2023-01-07 12:08:41 +00:00
|
|
|
enddef
|
|
|
|
|
2023-01-08 19:54:10 +00:00
|
|
|
def Test_class_extends()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class Base
|
|
|
|
this.one = 1
|
|
|
|
def GetOne(): number
|
|
|
|
return this.one
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
class Child extends Base
|
|
|
|
this.two = 2
|
|
|
|
def GetTotal(): number
|
|
|
|
return this.one + this.two
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
var o = Child.new()
|
|
|
|
assert_equal(1, o.one)
|
|
|
|
assert_equal(2, o.two)
|
|
|
|
assert_equal(1, o.GetOne())
|
|
|
|
assert_equal(3, o.GetTotal())
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-01-08 19:54:10 +00:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class Base
|
|
|
|
this.one = 1
|
|
|
|
endclass
|
|
|
|
class Child extends Base
|
|
|
|
this.two = 2
|
|
|
|
endclass
|
|
|
|
var o = Child.new(3, 44)
|
|
|
|
assert_equal(3, o.one)
|
|
|
|
assert_equal(44, o.two)
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-01-08 19:54:10 +00:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class Base
|
|
|
|
this.one = 1
|
|
|
|
endclass
|
|
|
|
class Child extends Base extends Base
|
|
|
|
this.two = 2
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1352: Duplicate "extends"')
|
2023-01-08 19:54:10 +00:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class Child extends BaseClass
|
|
|
|
this.two = 2
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1353: Class name not found: BaseClass')
|
2023-01-08 19:54:10 +00:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
var SomeVar = 99
|
|
|
|
class Child extends SomeVar
|
|
|
|
this.two = 2
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1354: Cannot extend SomeVar')
|
2023-01-11 15:59:05 +00:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class Base
|
|
|
|
this.name: string
|
|
|
|
def ToString(): string
|
|
|
|
return this.name
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class Child extends Base
|
|
|
|
this.age: number
|
|
|
|
def ToString(): string
|
|
|
|
return super.ToString() .. ': ' .. this.age
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var o = Child.new('John', 42)
|
|
|
|
assert_equal('John: 42', o.ToString())
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-01-11 17:59:38 +00:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class Child
|
|
|
|
this.age: number
|
|
|
|
def ToString(): number
|
|
|
|
return this.age
|
|
|
|
enddef
|
|
|
|
def ToString(): string
|
|
|
|
return this.age
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1355: Duplicate function: ToString')
|
2023-01-11 17:59:38 +00:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class Child
|
|
|
|
this.age: number
|
|
|
|
def ToString(): string
|
|
|
|
return super .ToString() .. ': ' .. this.age
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
var o = Child.new(42)
|
|
|
|
echo o.ToString()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1356:')
|
2023-01-11 17:59:38 +00:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class Base
|
|
|
|
this.name: string
|
|
|
|
def ToString(): string
|
|
|
|
return this.name
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var age = 42
|
|
|
|
def ToString(): string
|
|
|
|
return super.ToString() .. ': ' .. age
|
|
|
|
enddef
|
|
|
|
echo ToString()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1357:')
|
2023-01-11 17:59:38 +00:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class Child
|
|
|
|
this.age: number
|
|
|
|
def ToString(): string
|
|
|
|
return super.ToString() .. ': ' .. this.age
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
var o = Child.new(42)
|
|
|
|
echo o.ToString()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1358:')
|
2023-01-11 21:14:17 +00:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class Base
|
|
|
|
this.name: string
|
|
|
|
static def ToString(): string
|
|
|
|
return 'Base class'
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class Child extends Base
|
|
|
|
this.age: number
|
|
|
|
def ToString(): string
|
|
|
|
return Base.ToString() .. ': ' .. this.age
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var o = Child.new('John', 42)
|
|
|
|
assert_equal('Base class: 42', o.ToString())
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-01-15 15:51:48 +00:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class Base
|
|
|
|
this.value = 1
|
|
|
|
def new(init: number)
|
|
|
|
this.value = number + 1
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
class Child extends Base
|
|
|
|
def new()
|
|
|
|
this.new(3)
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
var c = Child.new()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1375: Class member "new" accessible only using class "Child"')
|
2023-01-15 20:49:00 +00:00
|
|
|
|
|
|
|
# base class with more than one object member
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class Result
|
|
|
|
this.success: bool
|
|
|
|
this.value: any = null
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class Success extends Result
|
|
|
|
def new(this.value = v:none)
|
|
|
|
this.success = true
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var v = Success.new('asdf')
|
|
|
|
assert_equal("object of Success {success: true, value: 'asdf'}", string(v))
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-08-19 11:26:42 +02:00
|
|
|
|
|
|
|
# class name after "extends" doesn't end in a space or NUL character
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
endclass
|
|
|
|
class B extends A"
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1315:')
|
2023-01-08 19:54:10 +00:00
|
|
|
enddef
|
|
|
|
|
2023-02-10 15:52:25 +00:00
|
|
|
def Test_using_base_class()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class BaseEE
|
|
|
|
def Enter(): any
|
|
|
|
return null
|
|
|
|
enddef
|
|
|
|
def Exit(resource: any): void
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class ChildEE extends BaseEE
|
|
|
|
def Enter(): any
|
|
|
|
return 42
|
|
|
|
enddef
|
|
|
|
|
|
|
|
def Exit(resource: number): void
|
|
|
|
g:result ..= '/exit'
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
def With(ee: BaseEE)
|
|
|
|
var r = ee.Enter()
|
|
|
|
try
|
|
|
|
g:result ..= r
|
|
|
|
finally
|
|
|
|
g:result ..= '/finally'
|
|
|
|
ee.Exit(r)
|
|
|
|
endtry
|
|
|
|
enddef
|
|
|
|
|
|
|
|
g:result = ''
|
|
|
|
With(ChildEE.new())
|
|
|
|
assert_equal('42/finally/exit', g:result)
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-02-10 15:52:25 +00:00
|
|
|
unlet g:result
|
2023-06-04 18:11:35 +01:00
|
|
|
|
|
|
|
# Using super, Child invokes Base method which has optional arg. #12471
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class Base
|
|
|
|
this.success: bool = false
|
|
|
|
def Method(arg = 0)
|
|
|
|
this.success = true
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class Child extends Base
|
|
|
|
def new()
|
|
|
|
super.Method()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var obj = Child.new()
|
|
|
|
assert_equal(true, obj.success)
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-02-10 15:52:25 +00:00
|
|
|
enddef
|
|
|
|
|
2023-01-12 17:06:27 +00:00
|
|
|
def Test_class_import()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
export class Animal
|
|
|
|
this.kind: string
|
|
|
|
this.name: string
|
|
|
|
endclass
|
|
|
|
END
|
|
|
|
writefile(lines, 'Xanimal.vim', 'D')
|
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
import './Xanimal.vim' as animal
|
|
|
|
|
|
|
|
var a: animal.Animal
|
|
|
|
a = animal.Animal.new('fish', 'Eric')
|
|
|
|
assert_equal('fish', a.kind)
|
|
|
|
assert_equal('Eric', a.name)
|
2023-01-12 20:04:51 +00:00
|
|
|
|
|
|
|
var b: animal.Animal = animal.Animal.new('cat', 'Garfield')
|
|
|
|
assert_equal('cat', b.kind)
|
|
|
|
assert_equal('Garfield', b.name)
|
2023-01-12 17:06:27 +00:00
|
|
|
END
|
|
|
|
v9.CheckScriptSuccess(lines)
|
|
|
|
enddef
|
|
|
|
|
2023-01-14 13:12:06 +00:00
|
|
|
def Test_abstract_class()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
abstract class Base
|
|
|
|
this.name: string
|
|
|
|
endclass
|
|
|
|
class Person extends Base
|
|
|
|
this.age: number
|
|
|
|
endclass
|
|
|
|
var p: Base = Person.new('Peter', 42)
|
|
|
|
assert_equal('Peter', p.name)
|
|
|
|
assert_equal(42, p.age)
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-01-14 13:12:06 +00:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
abstract class Base
|
|
|
|
this.name: string
|
|
|
|
endclass
|
|
|
|
class Person extends Base
|
|
|
|
this.age: number
|
|
|
|
endclass
|
|
|
|
var p = Base.new('Peter')
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1325: Method not found on class "Base": new')
|
2023-01-14 13:12:06 +00:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
abstract class Base
|
|
|
|
this.name: string
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1316:')
|
2023-08-19 11:26:42 +02:00
|
|
|
|
|
|
|
# Abstract class cannot have a "new" function
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
abstract class Base
|
|
|
|
def new()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1359:')
|
2023-01-14 13:12:06 +00:00
|
|
|
enddef
|
|
|
|
|
2023-01-18 14:51:07 +00:00
|
|
|
def Test_closure_in_class()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class Foo
|
|
|
|
this.y: list<string> = ['B']
|
|
|
|
|
|
|
|
def new()
|
|
|
|
g:result = filter(['A', 'B'], (_, v) => index(this.y, v) == -1)
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
Foo.new()
|
|
|
|
assert_equal(['A'], g:result)
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-01-18 14:51:07 +00:00
|
|
|
enddef
|
|
|
|
|
2023-06-10 16:45:13 +01:00
|
|
|
def Test_call_constructor_from_legacy()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
var newCalled = 'false'
|
|
|
|
|
|
|
|
class A
|
|
|
|
def new()
|
|
|
|
newCalled = 'true'
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
export def F(options = {}): any
|
|
|
|
return A
|
|
|
|
enddef
|
|
|
|
|
|
|
|
g:p = F()
|
|
|
|
legacy call p.new()
|
|
|
|
assert_equal('true', newCalled)
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-06-10 16:45:13 +01:00
|
|
|
enddef
|
|
|
|
|
2023-01-27 20:14:02 +00:00
|
|
|
def Test_defer_with_object()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class CWithEE
|
|
|
|
def Enter()
|
|
|
|
g:result ..= "entered/"
|
|
|
|
enddef
|
|
|
|
def Exit()
|
|
|
|
g:result ..= "exited"
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
def With(ee: CWithEE, F: func)
|
|
|
|
ee.Enter()
|
|
|
|
defer ee.Exit()
|
|
|
|
F()
|
|
|
|
enddef
|
|
|
|
|
|
|
|
g:result = ''
|
|
|
|
var obj = CWithEE.new()
|
|
|
|
obj->With(() => {
|
|
|
|
g:result ..= "called/"
|
|
|
|
})
|
|
|
|
assert_equal('entered/called/exited', g:result)
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-01-27 20:14:02 +00:00
|
|
|
unlet g:result
|
2023-02-08 20:55:27 +00:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class BaseWithEE
|
|
|
|
def Enter()
|
|
|
|
g:result ..= "entered-base/"
|
|
|
|
enddef
|
|
|
|
def Exit()
|
|
|
|
g:result ..= "exited-base"
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class CWithEE extends BaseWithEE
|
|
|
|
def Enter()
|
|
|
|
g:result ..= "entered-child/"
|
|
|
|
enddef
|
|
|
|
def Exit()
|
|
|
|
g:result ..= "exited-child"
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
def With(ee: BaseWithEE, F: func)
|
|
|
|
ee.Enter()
|
|
|
|
defer ee.Exit()
|
|
|
|
F()
|
|
|
|
enddef
|
|
|
|
|
|
|
|
g:result = ''
|
|
|
|
var obj = CWithEE.new()
|
|
|
|
obj->With(() => {
|
|
|
|
g:result ..= "called/"
|
|
|
|
})
|
|
|
|
assert_equal('entered-child/called/exited-child', g:result)
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-02-08 20:55:27 +00:00
|
|
|
unlet g:result
|
2023-01-27 20:14:02 +00:00
|
|
|
enddef
|
|
|
|
|
2023-08-13 10:19:38 +02:00
|
|
|
" The following test used to crash Vim (Github issue #12676)
|
|
|
|
def Test_extends_method_crashes_vim()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class Observer
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class Property
|
|
|
|
this.value: any
|
|
|
|
|
|
|
|
def Set(v: any)
|
|
|
|
if v != this.value
|
|
|
|
this.value = v
|
|
|
|
endif
|
|
|
|
enddef
|
|
|
|
|
|
|
|
def Register(observer: Observer)
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class Bool extends Property
|
2023-08-29 22:32:02 +02:00
|
|
|
this.value2: bool
|
2023-08-13 10:19:38 +02:00
|
|
|
endclass
|
|
|
|
|
|
|
|
def Observe(obj: Property, who: Observer)
|
|
|
|
obj.Register(who)
|
|
|
|
enddef
|
|
|
|
|
|
|
|
var p = Bool.new(false)
|
|
|
|
var myObserver = Observer.new()
|
|
|
|
|
|
|
|
Observe(p, myObserver)
|
|
|
|
|
|
|
|
p.Set(true)
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-08-13 10:19:38 +02:00
|
|
|
enddef
|
2022-12-08 15:32:33 +00:00
|
|
|
|
2023-08-13 17:41:26 +02:00
|
|
|
" Test for calling a method in a class that is extended
|
|
|
|
def Test_call_method_in_extended_class()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
var prop_init_called = false
|
|
|
|
var prop_register_called = false
|
|
|
|
|
|
|
|
class Property
|
|
|
|
def Init()
|
|
|
|
prop_init_called = true
|
|
|
|
enddef
|
|
|
|
|
|
|
|
def Register()
|
|
|
|
prop_register_called = true
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class Bool extends Property
|
|
|
|
endclass
|
|
|
|
|
|
|
|
def Observe(obj: Property)
|
|
|
|
obj.Register()
|
|
|
|
enddef
|
|
|
|
|
|
|
|
var p = Property.new()
|
|
|
|
Observe(p)
|
|
|
|
|
|
|
|
p.Init()
|
|
|
|
assert_true(prop_init_called)
|
|
|
|
assert_true(prop_register_called)
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-08-13 17:41:26 +02:00
|
|
|
enddef
|
|
|
|
|
2023-08-23 21:08:11 +02:00
|
|
|
def Test_instanceof()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class Base1
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class Base2 extends Base1
|
|
|
|
endclass
|
|
|
|
|
|
|
|
interface Intf1
|
|
|
|
endinterface
|
|
|
|
|
|
|
|
class Mix1 implements Intf1
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class Base3 extends Mix1
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var b1 = Base1.new()
|
|
|
|
var b2 = Base2.new()
|
|
|
|
var b3 = Base3.new()
|
|
|
|
|
|
|
|
assert_true(instanceof(b1, Base1))
|
|
|
|
assert_true(instanceof(b2, Base1))
|
|
|
|
assert_false(instanceof(b1, Base2))
|
|
|
|
assert_true(instanceof(b3, Mix1))
|
|
|
|
assert_false(instanceof(b3, []))
|
|
|
|
assert_true(instanceof(b3, [Base1, Base2, Intf1]))
|
2023-08-27 19:08:40 +02:00
|
|
|
|
|
|
|
def Foo()
|
|
|
|
var a1 = Base1.new()
|
|
|
|
var a2 = Base2.new()
|
|
|
|
var a3 = Base3.new()
|
|
|
|
|
|
|
|
assert_true(instanceof(a1, Base1))
|
|
|
|
assert_true(instanceof(a2, Base1))
|
|
|
|
assert_false(instanceof(a1, Base2))
|
|
|
|
assert_true(instanceof(a3, Mix1))
|
|
|
|
assert_false(instanceof(a3, []))
|
|
|
|
assert_true(instanceof(a3, [Base1, Base2, Intf1]))
|
|
|
|
enddef
|
|
|
|
Foo()
|
2023-09-19 20:14:18 +02:00
|
|
|
|
|
|
|
var o_null: Base1
|
|
|
|
assert_false(instanceof(o_null, Base1))
|
|
|
|
|
2023-08-23 21:08:11 +02:00
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-08-23 21:08:11 +02:00
|
|
|
enddef
|
|
|
|
|
2023-08-16 20:14:37 +02:00
|
|
|
" Test for calling a method in the parent class that is extended partially.
|
|
|
|
" This used to fail with the 'E118: Too many arguments for function: Text' error
|
|
|
|
" message (Github issue #12524).
|
|
|
|
def Test_call_method_in_parent_class()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class Widget
|
|
|
|
this._lnum: number = 1
|
|
|
|
|
|
|
|
def SetY(lnum: number)
|
|
|
|
this._lnum = lnum
|
|
|
|
enddef
|
|
|
|
|
|
|
|
def Text(): string
|
|
|
|
return ''
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class Foo extends Widget
|
|
|
|
def Text(): string
|
|
|
|
return '<Foo>'
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
def Stack(w1: Widget, w2: Widget): list<Widget>
|
|
|
|
w1.SetY(1)
|
|
|
|
w2.SetY(2)
|
|
|
|
return [w1, w2]
|
|
|
|
enddef
|
|
|
|
|
|
|
|
var foo1 = Foo.new()
|
|
|
|
var foo2 = Foo.new()
|
|
|
|
var l = Stack(foo1, foo2)
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-08-16 20:14:37 +02:00
|
|
|
enddef
|
|
|
|
|
2023-08-19 11:26:42 +02:00
|
|
|
" Test for calling methods from three levels of classes
|
|
|
|
def Test_multi_level_method_call()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
var A_func1: number = 0
|
|
|
|
var A_func2: number = 0
|
|
|
|
var A_func3: number = 0
|
|
|
|
var B_func2: number = 0
|
|
|
|
var B_func3: number = 0
|
|
|
|
var C_func3: number = 0
|
|
|
|
|
|
|
|
class A
|
|
|
|
def Func1()
|
|
|
|
A_func1 += 1
|
|
|
|
enddef
|
|
|
|
|
|
|
|
def Func2()
|
|
|
|
A_func2 += 1
|
|
|
|
enddef
|
|
|
|
|
|
|
|
def Func3()
|
|
|
|
A_func3 += 1
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class B extends A
|
|
|
|
def Func2()
|
|
|
|
B_func2 += 1
|
|
|
|
enddef
|
|
|
|
|
|
|
|
def Func3()
|
|
|
|
B_func3 += 1
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class C extends B
|
|
|
|
def Func3()
|
|
|
|
C_func3 += 1
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
def A_CallFuncs(a: A)
|
|
|
|
a.Func1()
|
|
|
|
a.Func2()
|
|
|
|
a.Func3()
|
|
|
|
enddef
|
|
|
|
|
|
|
|
def B_CallFuncs(b: B)
|
|
|
|
b.Func1()
|
|
|
|
b.Func2()
|
|
|
|
b.Func3()
|
|
|
|
enddef
|
|
|
|
|
|
|
|
def C_CallFuncs(c: C)
|
|
|
|
c.Func1()
|
|
|
|
c.Func2()
|
|
|
|
c.Func3()
|
|
|
|
enddef
|
|
|
|
|
|
|
|
var cobj = C.new()
|
|
|
|
A_CallFuncs(cobj)
|
|
|
|
B_CallFuncs(cobj)
|
|
|
|
C_CallFuncs(cobj)
|
|
|
|
assert_equal(3, A_func1)
|
|
|
|
assert_equal(0, A_func2)
|
|
|
|
assert_equal(0, A_func3)
|
|
|
|
assert_equal(3, B_func2)
|
|
|
|
assert_equal(0, B_func3)
|
|
|
|
assert_equal(3, C_func3)
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-08-19 11:26:42 +02:00
|
|
|
enddef
|
|
|
|
|
|
|
|
" Test for using members from three levels of classes
|
|
|
|
def Test_multi_level_member_access()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class A
|
2023-08-31 18:10:46 +02:00
|
|
|
public this.val1: number = 0
|
2023-08-19 11:26:42 +02:00
|
|
|
endclass
|
|
|
|
|
|
|
|
class B extends A
|
2023-08-31 18:10:46 +02:00
|
|
|
public this.val2: number = 0
|
2023-08-19 11:26:42 +02:00
|
|
|
endclass
|
|
|
|
|
|
|
|
class C extends B
|
2023-08-31 18:10:46 +02:00
|
|
|
public this.val3: number = 0
|
2023-08-19 11:26:42 +02:00
|
|
|
endclass
|
|
|
|
|
|
|
|
def A_members(a: A)
|
|
|
|
a.val1 += 1
|
|
|
|
enddef
|
|
|
|
|
|
|
|
def B_members(b: B)
|
|
|
|
b.val1 += 1
|
|
|
|
b.val2 += 1
|
|
|
|
enddef
|
|
|
|
|
|
|
|
def C_members(c: C)
|
|
|
|
c.val1 += 1
|
|
|
|
c.val2 += 1
|
|
|
|
c.val3 += 1
|
|
|
|
enddef
|
|
|
|
|
|
|
|
var cobj = C.new()
|
|
|
|
A_members(cobj)
|
|
|
|
B_members(cobj)
|
|
|
|
C_members(cobj)
|
|
|
|
assert_equal(3, cobj.val1)
|
2023-08-29 22:32:02 +02:00
|
|
|
assert_equal(2, cobj.val2)
|
|
|
|
assert_equal(1, cobj.val3)
|
2023-08-19 11:26:42 +02:00
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-08-19 11:26:42 +02:00
|
|
|
enddef
|
|
|
|
|
2023-08-20 18:09:11 +02:00
|
|
|
" Test expansion of <stack> with class methods.
|
|
|
|
def Test_stack_expansion_with_methods()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class C
|
|
|
|
def M1()
|
|
|
|
F0()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
def F0()
|
|
|
|
assert_match('<SNR>\d\+_F\[1\]\.\.C\.M1\[1\]\.\.<SNR>\d\+_F0\[1\]$', expand('<stack>'))
|
|
|
|
enddef
|
|
|
|
|
|
|
|
def F()
|
|
|
|
C.new().M1()
|
|
|
|
enddef
|
|
|
|
|
|
|
|
F()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-08-20 18:09:11 +02:00
|
|
|
enddef
|
2023-08-20 18:20:17 +02:00
|
|
|
|
|
|
|
" Test the return type of the new() constructor
|
|
|
|
def Test_new_return_type()
|
|
|
|
# new() uses the default return type and there is no return statement
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class C
|
|
|
|
this._bufnr: number
|
|
|
|
|
|
|
|
def new(this._bufnr)
|
|
|
|
if !bufexists(this._bufnr)
|
|
|
|
this._bufnr = -1
|
|
|
|
endif
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var c = C.new(12345)
|
|
|
|
assert_equal('object<C>', typename(c))
|
|
|
|
|
|
|
|
var v1: C
|
|
|
|
v1 = C.new(12345)
|
|
|
|
assert_equal('object<C>', typename(v1))
|
|
|
|
|
|
|
|
def F()
|
|
|
|
var v2: C
|
|
|
|
v2 = C.new(12345)
|
|
|
|
assert_equal('object<C>', typename(v2))
|
|
|
|
enddef
|
|
|
|
F()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-08-20 18:20:17 +02:00
|
|
|
|
|
|
|
# new() uses the default return type and an empty 'return' statement
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class C
|
|
|
|
this._bufnr: number
|
|
|
|
|
|
|
|
def new(this._bufnr)
|
|
|
|
if !bufexists(this._bufnr)
|
|
|
|
this._bufnr = -1
|
|
|
|
return
|
|
|
|
endif
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var c = C.new(12345)
|
|
|
|
assert_equal('object<C>', typename(c))
|
|
|
|
|
|
|
|
var v1: C
|
|
|
|
v1 = C.new(12345)
|
|
|
|
assert_equal('object<C>', typename(v1))
|
|
|
|
|
|
|
|
def F()
|
|
|
|
var v2: C
|
|
|
|
v2 = C.new(12345)
|
|
|
|
assert_equal('object<C>', typename(v2))
|
|
|
|
enddef
|
|
|
|
F()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-08-20 18:20:17 +02:00
|
|
|
|
|
|
|
# new() uses "any" return type and returns "this"
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class C
|
|
|
|
this._bufnr: number
|
|
|
|
|
|
|
|
def new(this._bufnr): any
|
|
|
|
if !bufexists(this._bufnr)
|
|
|
|
this._bufnr = -1
|
|
|
|
return this
|
|
|
|
endif
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1365:')
|
2023-08-20 18:20:17 +02:00
|
|
|
|
|
|
|
# new() uses 'Dict' return type and returns a Dict
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class C
|
|
|
|
this._state: dict<any>
|
|
|
|
|
|
|
|
def new(): dict<any>
|
|
|
|
this._state = {}
|
|
|
|
return this._state
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var c = C.new()
|
|
|
|
assert_equal('object<C>', typename(c))
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1365:')
|
2023-08-20 18:20:17 +02:00
|
|
|
enddef
|
|
|
|
|
2023-08-22 21:29:28 +02:00
|
|
|
" Test for checking a member initialization type at run time.
|
|
|
|
def Test_runtime_type_check_for_member_init()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
var retnum: bool = false
|
|
|
|
|
|
|
|
def F(): any
|
|
|
|
retnum = !retnum
|
|
|
|
if retnum
|
|
|
|
return 1
|
|
|
|
else
|
|
|
|
return "hello"
|
|
|
|
endif
|
|
|
|
enddef
|
|
|
|
|
|
|
|
class C
|
|
|
|
this._foo: bool = F()
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var c1 = C.new()
|
|
|
|
var c2 = C.new()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1012:')
|
2023-08-22 21:29:28 +02:00
|
|
|
enddef
|
|
|
|
|
|
|
|
" Test for locking a variable referring to an object and reassigning to another
|
|
|
|
" object.
|
|
|
|
def Test_object_lockvar()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class C
|
|
|
|
this.val: number
|
|
|
|
def new(this.val)
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var some_dict: dict<C> = { a: C.new(1), b: C.new(2), c: C.new(3), }
|
|
|
|
lockvar 2 some_dict
|
|
|
|
|
|
|
|
var current: C
|
|
|
|
current = some_dict['c']
|
|
|
|
assert_equal(3, current.val)
|
|
|
|
current = some_dict['b']
|
|
|
|
assert_equal(2, current.val)
|
|
|
|
|
|
|
|
def F()
|
|
|
|
current = some_dict['c']
|
|
|
|
enddef
|
|
|
|
|
|
|
|
def G()
|
|
|
|
current = some_dict['b']
|
|
|
|
enddef
|
|
|
|
|
|
|
|
F()
|
|
|
|
assert_equal(3, current.val)
|
|
|
|
G()
|
|
|
|
assert_equal(2, current.val)
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-08-22 21:29:28 +02:00
|
|
|
enddef
|
|
|
|
|
2023-08-27 19:18:23 +02:00
|
|
|
" Test for a private object method
|
|
|
|
def Test_private_object_method()
|
|
|
|
# Try calling a private method using an object (at the script level)
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class A
|
|
|
|
def _Foo(): number
|
|
|
|
return 1234
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
var a = A.new()
|
|
|
|
a._Foo()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
|
2023-08-27 19:18:23 +02:00
|
|
|
|
|
|
|
# Try calling a private method using an object (from a def function)
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class A
|
|
|
|
def _Foo(): number
|
|
|
|
return 1234
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
def T()
|
|
|
|
var a = A.new()
|
|
|
|
a._Foo()
|
|
|
|
enddef
|
|
|
|
T()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
|
2023-08-27 19:18:23 +02:00
|
|
|
|
|
|
|
# Use a private method from another object method (in script context)
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class A
|
|
|
|
def _Foo(): number
|
|
|
|
return 1234
|
|
|
|
enddef
|
|
|
|
def Bar(): number
|
|
|
|
return this._Foo()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
var a = A.new()
|
|
|
|
assert_equal(1234, a.Bar())
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-08-27 19:18:23 +02:00
|
|
|
|
|
|
|
# Use a private method from another object method (def function context)
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class A
|
|
|
|
def _Foo(): number
|
|
|
|
return 1234
|
|
|
|
enddef
|
|
|
|
def Bar(): number
|
|
|
|
return this._Foo()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
def T()
|
|
|
|
var a = A.new()
|
|
|
|
assert_equal(1234, a.Bar())
|
|
|
|
enddef
|
|
|
|
T()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-08-27 19:18:23 +02:00
|
|
|
|
|
|
|
# Try calling a private method without the "this" prefix
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class A
|
|
|
|
def _Foo(): number
|
|
|
|
return 1234
|
|
|
|
enddef
|
|
|
|
def Bar(): number
|
|
|
|
return _Foo()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
var a = A.new()
|
|
|
|
a.Bar()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E117: Unknown function: _Foo')
|
2023-08-27 19:18:23 +02:00
|
|
|
|
|
|
|
# Try calling a private method using the class name
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class A
|
|
|
|
def _Foo(): number
|
|
|
|
return 1234
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
A._Foo()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo')
|
2023-08-27 19:18:23 +02:00
|
|
|
|
|
|
|
# Try to use "public" keyword when defining a private method
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class A
|
|
|
|
public def _Foo()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
var a = A.new()
|
|
|
|
a._Foo()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1331: Public must be followed by "this" or "static"')
|
2023-08-27 19:18:23 +02:00
|
|
|
|
|
|
|
# Define two private methods with the same name
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class A
|
|
|
|
def _Foo()
|
|
|
|
enddef
|
|
|
|
def _Foo()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
var a = A.new()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo')
|
2023-08-27 19:18:23 +02:00
|
|
|
|
|
|
|
# Define a private method and a object method with the same name
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class A
|
|
|
|
def _Foo()
|
|
|
|
enddef
|
|
|
|
def Foo()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
var a = A.new()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo')
|
2023-08-27 19:18:23 +02:00
|
|
|
|
|
|
|
# Define an object method and a private method with the same name
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class A
|
|
|
|
def Foo()
|
|
|
|
enddef
|
|
|
|
def _Foo()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
var a = A.new()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo')
|
2023-08-27 19:18:23 +02:00
|
|
|
|
|
|
|
# Call a public method and a private method from a private method
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class A
|
|
|
|
def Foo(): number
|
|
|
|
return 100
|
|
|
|
enddef
|
|
|
|
def _Bar(): number
|
|
|
|
return 200
|
|
|
|
enddef
|
|
|
|
def _Baz()
|
|
|
|
assert_equal(100, this.Foo())
|
|
|
|
assert_equal(200, this._Bar())
|
|
|
|
enddef
|
|
|
|
def T()
|
|
|
|
this._Baz()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
var a = A.new()
|
|
|
|
a.T()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-08-27 19:18:23 +02:00
|
|
|
|
|
|
|
# Try calling a private method from another class
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class A
|
|
|
|
def _Foo(): number
|
|
|
|
return 100
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
class B
|
|
|
|
def Foo(): number
|
|
|
|
var a = A.new()
|
|
|
|
a._Foo()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
var b = B.new()
|
|
|
|
b.Foo()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
|
2023-08-27 19:18:23 +02:00
|
|
|
|
|
|
|
# Call a private object method from a child class object method
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
def _Foo(): number
|
|
|
|
return 1234
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
class B extends A
|
|
|
|
def Bar()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
class C extends B
|
|
|
|
def Baz(): number
|
|
|
|
return this._Foo()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
var c = C.new()
|
|
|
|
assert_equal(1234, c.Baz())
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-08-27 19:18:23 +02:00
|
|
|
|
|
|
|
# Call a private object method from a child class object
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
def _Foo(): number
|
|
|
|
return 1234
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
class B extends A
|
|
|
|
def Bar()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
class C extends B
|
|
|
|
def Baz(): number
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
var c = C.new()
|
|
|
|
assert_equal(1234, c._Foo())
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
|
2023-08-27 19:18:23 +02:00
|
|
|
|
|
|
|
# Using "_" prefix in a method name should fail outside of a class
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
def _Foo(): number
|
|
|
|
return 1234
|
|
|
|
enddef
|
|
|
|
var a = _Foo()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1267: Function name must start with a capital: _Foo(): number')
|
2023-08-27 19:18:23 +02:00
|
|
|
enddef
|
|
|
|
|
|
|
|
" Test for an private class method
|
|
|
|
def Test_private_class_method()
|
|
|
|
# Try calling a class private method (at the script level)
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class A
|
|
|
|
static def _Foo(): number
|
|
|
|
return 1234
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
A._Foo()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
|
2023-08-27 19:18:23 +02:00
|
|
|
|
|
|
|
# Try calling a class private method (from a def function)
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class A
|
|
|
|
static def _Foo(): number
|
|
|
|
return 1234
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
def T()
|
|
|
|
A._Foo()
|
|
|
|
enddef
|
|
|
|
T()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
|
2023-08-27 19:18:23 +02:00
|
|
|
|
|
|
|
# Try calling a class private method using an object (at the script level)
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class A
|
|
|
|
static def _Foo(): number
|
|
|
|
return 1234
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
var a = A.new()
|
|
|
|
a._Foo()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo')
|
2023-08-27 19:18:23 +02:00
|
|
|
|
|
|
|
# Try calling a class private method using an object (from a def function)
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class A
|
|
|
|
static def _Foo(): number
|
|
|
|
return 1234
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
def T()
|
|
|
|
var a = A.new()
|
|
|
|
a._Foo()
|
|
|
|
enddef
|
|
|
|
T()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo')
|
2023-08-27 19:18:23 +02:00
|
|
|
|
|
|
|
# Use a class private method from an object method
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class A
|
|
|
|
static def _Foo(): number
|
|
|
|
return 1234
|
|
|
|
enddef
|
|
|
|
def Bar()
|
2023-09-18 19:56:49 +02:00
|
|
|
assert_equal(1234, _Foo())
|
2023-08-27 19:18:23 +02:00
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
var a = A.new()
|
|
|
|
a.Bar()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-08-27 19:18:23 +02:00
|
|
|
|
2023-09-18 19:56:49 +02:00
|
|
|
# Use a class private method from another class private method without the
|
|
|
|
# class name prefix.
|
2023-08-27 19:18:23 +02:00
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class A
|
|
|
|
static def _Foo1(): number
|
|
|
|
return 1234
|
|
|
|
enddef
|
|
|
|
static def _Foo2()
|
2023-09-18 19:56:49 +02:00
|
|
|
assert_equal(1234, _Foo1())
|
2023-08-27 19:18:23 +02:00
|
|
|
enddef
|
|
|
|
def Bar()
|
2023-09-18 19:56:49 +02:00
|
|
|
_Foo2()
|
2023-08-27 19:18:23 +02:00
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
var a = A.new()
|
|
|
|
a.Bar()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-08-27 19:18:23 +02:00
|
|
|
|
|
|
|
# Declare a class method and a class private method with the same name
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class A
|
|
|
|
static def _Foo()
|
|
|
|
enddef
|
|
|
|
static def Foo()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
var a = A.new()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo')
|
2023-08-27 19:18:23 +02:00
|
|
|
|
|
|
|
# Try calling a class private method from another class
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class A
|
|
|
|
static def _Foo(): number
|
|
|
|
return 1234
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
class B
|
|
|
|
def Foo(): number
|
|
|
|
return A._Foo()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
var b = B.new()
|
|
|
|
assert_equal(1234, b.Foo())
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
|
2023-08-27 19:18:23 +02:00
|
|
|
|
|
|
|
# Call a private class method from a child class object method
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
static def _Foo(): number
|
|
|
|
return 1234
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
class B extends A
|
|
|
|
def Bar()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
class C extends B
|
|
|
|
def Baz(): number
|
|
|
|
return A._Foo()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
var c = C.new()
|
|
|
|
assert_equal(1234, c.Baz())
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
|
2023-08-27 19:18:23 +02:00
|
|
|
|
|
|
|
# Call a private class method from a child class private class method
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
static def _Foo(): number
|
|
|
|
return 1234
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
class B extends A
|
|
|
|
def Bar()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
class C extends B
|
|
|
|
static def Baz(): number
|
|
|
|
return A._Foo()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
assert_equal(1234, C.Baz())
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1366: Cannot access private method: _Foo()')
|
2023-08-27 19:18:23 +02:00
|
|
|
|
|
|
|
# Call a private class method from a child class object
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
static def _Foo(): number
|
|
|
|
return 1234
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
class B extends A
|
|
|
|
def Bar()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
class C extends B
|
|
|
|
def Baz(): number
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
var c = C.new()
|
|
|
|
assert_equal(1234, C._Foo())
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1325: Method not found on class "C": _Foo')
|
2023-08-27 19:18:23 +02:00
|
|
|
enddef
|
|
|
|
|
2023-08-27 19:23:37 +02:00
|
|
|
" Test for using the return value of a class/object method as a function
|
|
|
|
" argument.
|
|
|
|
def Test_objmethod_funcarg()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class C
|
|
|
|
def Foo(): string
|
|
|
|
return 'foo'
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
def Bar(a: number, s: string): string
|
|
|
|
return s
|
|
|
|
enddef
|
|
|
|
|
|
|
|
def Baz(c: C)
|
|
|
|
assert_equal('foo', Bar(10, c.Foo()))
|
|
|
|
enddef
|
|
|
|
|
|
|
|
var t = C.new()
|
|
|
|
Baz(t)
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-08-27 19:23:37 +02:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class C
|
|
|
|
static def Foo(): string
|
|
|
|
return 'foo'
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
def Bar(a: number, s: string): string
|
|
|
|
return s
|
|
|
|
enddef
|
|
|
|
|
|
|
|
def Baz()
|
|
|
|
assert_equal('foo', Bar(10, C.Foo()))
|
|
|
|
enddef
|
|
|
|
|
|
|
|
Baz()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-08-27 19:23:37 +02:00
|
|
|
enddef
|
|
|
|
|
2023-09-06 20:45:03 +02:00
|
|
|
def Test_static_inheritence()
|
|
|
|
# subclasses get their own static copy
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class A
|
|
|
|
static _svar: number
|
|
|
|
this._mvar: number
|
|
|
|
def new()
|
|
|
|
_svar = 1
|
|
|
|
this._mvar = 101
|
|
|
|
enddef
|
|
|
|
def AccessObject(): number
|
|
|
|
return this._mvar
|
|
|
|
enddef
|
|
|
|
def AccessStaticThroughObject(): number
|
|
|
|
return _svar
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class B extends A
|
|
|
|
def new()
|
|
|
|
this._mvar = 102
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class C extends B
|
|
|
|
def new()
|
|
|
|
this._mvar = 103
|
|
|
|
enddef
|
|
|
|
|
|
|
|
def AccessPrivateStaticThroughClassName(): number
|
|
|
|
assert_equal(1, A._svar)
|
|
|
|
return 444
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var oa = A.new()
|
|
|
|
var ob = B.new()
|
|
|
|
var oc = C.new()
|
|
|
|
assert_equal(101, oa.AccessObject())
|
|
|
|
assert_equal(102, ob.AccessObject())
|
|
|
|
assert_equal(103, oc.AccessObject())
|
|
|
|
|
2023-09-15 20:14:55 +02:00
|
|
|
assert_fails('echo oc.AccessPrivateStaticThroughClassName()', 'E1333: Cannot access private member: _svar')
|
2023-09-06 20:45:03 +02:00
|
|
|
|
|
|
|
# verify object properly resolves to correct static
|
|
|
|
assert_equal(1, oa.AccessStaticThroughObject())
|
2023-09-15 20:14:55 +02:00
|
|
|
assert_equal(1, ob.AccessStaticThroughObject())
|
|
|
|
assert_equal(1, oc.AccessStaticThroughObject())
|
2023-09-06 20:45:03 +02:00
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-09-06 20:45:03 +02:00
|
|
|
enddef
|
|
|
|
|
2023-08-28 21:26:23 +02:00
|
|
|
" Test for declaring duplicate object and class members
|
|
|
|
def Test_dup_member_variable()
|
|
|
|
# Duplicate member variable
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class C
|
|
|
|
this.val = 10
|
|
|
|
this.val = 20
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1369: Duplicate member: val')
|
2023-08-28 21:26:23 +02:00
|
|
|
|
|
|
|
# Duplicate private member variable
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class C
|
|
|
|
this._val = 10
|
|
|
|
this._val = 20
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1369: Duplicate member: _val')
|
2023-08-28 21:26:23 +02:00
|
|
|
|
|
|
|
# Duplicate public member variable
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class C
|
|
|
|
public this.val = 10
|
|
|
|
public this.val = 20
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1369: Duplicate member: val')
|
2023-08-28 21:26:23 +02:00
|
|
|
|
|
|
|
# Duplicate private member variable
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class C
|
|
|
|
this.val = 10
|
|
|
|
this._val = 20
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1369: Duplicate member: _val')
|
2023-08-28 21:26:23 +02:00
|
|
|
|
|
|
|
# Duplicate public and private member variable
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class C
|
|
|
|
this._val = 20
|
|
|
|
public this.val = 10
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1369: Duplicate member: val')
|
2023-08-28 21:26:23 +02:00
|
|
|
|
|
|
|
# Duplicate class member variable
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class C
|
|
|
|
static s: string = "abc"
|
|
|
|
static _s: string = "def"
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1369: Duplicate member: _s')
|
2023-08-28 21:26:23 +02:00
|
|
|
|
|
|
|
# Duplicate public and private class member variable
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class C
|
|
|
|
public static s: string = "abc"
|
|
|
|
static _s: string = "def"
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1369: Duplicate member: _s')
|
2023-08-28 21:26:23 +02:00
|
|
|
|
|
|
|
# Duplicate class and object member variable
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class C
|
|
|
|
static val = 10
|
|
|
|
this.val = 20
|
|
|
|
def new()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
var c = C.new()
|
|
|
|
assert_equal(10, C.val)
|
|
|
|
assert_equal(20, c.val)
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-08-29 22:32:02 +02:00
|
|
|
|
|
|
|
# Duplicate object member variable in a derived class
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
this.val = 10
|
|
|
|
endclass
|
|
|
|
class B extends A
|
|
|
|
endclass
|
|
|
|
class C extends B
|
|
|
|
this.val = 20
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1369: Duplicate member: val')
|
2023-08-29 22:32:02 +02:00
|
|
|
|
|
|
|
# Duplicate object private member variable in a derived class
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
this._val = 10
|
|
|
|
endclass
|
|
|
|
class B extends A
|
|
|
|
endclass
|
|
|
|
class C extends B
|
|
|
|
this._val = 20
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1369: Duplicate member: _val')
|
2023-08-29 22:32:02 +02:00
|
|
|
|
|
|
|
# Duplicate object private member variable in a derived class
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
this.val = 10
|
|
|
|
endclass
|
|
|
|
class B extends A
|
|
|
|
endclass
|
|
|
|
class C extends B
|
|
|
|
this._val = 20
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1369: Duplicate member: _val')
|
2023-08-29 22:32:02 +02:00
|
|
|
|
|
|
|
# Duplicate object member variable in a derived class
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
this._val = 10
|
|
|
|
endclass
|
|
|
|
class B extends A
|
|
|
|
endclass
|
|
|
|
class C extends B
|
|
|
|
this.val = 20
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1369: Duplicate member: val')
|
2023-08-29 22:32:02 +02:00
|
|
|
|
2023-09-15 20:14:55 +02:00
|
|
|
# Two member variables with a common prefix
|
2023-08-29 22:32:02 +02:00
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
2023-09-15 20:14:55 +02:00
|
|
|
public static svar2: number
|
|
|
|
public static svar: number
|
2023-08-29 22:32:02 +02:00
|
|
|
endclass
|
2023-09-15 20:14:55 +02:00
|
|
|
END
|
|
|
|
v9.CheckSourceSuccess(lines)
|
|
|
|
enddef
|
|
|
|
|
2023-09-17 17:03:19 +02:00
|
|
|
" Test for accessing a private member outside a class in a def function
|
|
|
|
def Test_private_member_access_outside_class()
|
|
|
|
# private object member variable
|
2023-09-15 20:14:55 +02:00
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
2023-09-17 17:03:19 +02:00
|
|
|
class A
|
|
|
|
this._val = 10
|
|
|
|
def GetVal(): number
|
|
|
|
return this._val
|
|
|
|
enddef
|
2023-08-29 22:32:02 +02:00
|
|
|
endclass
|
2023-09-17 17:03:19 +02:00
|
|
|
def T()
|
|
|
|
var a = A.new()
|
|
|
|
a._val = 20
|
|
|
|
enddef
|
|
|
|
T()
|
2023-08-29 22:32:02 +02:00
|
|
|
END
|
2023-09-17 17:03:19 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1333: Cannot access private member: _val')
|
2023-08-29 22:32:02 +02:00
|
|
|
|
2023-09-17 17:03:19 +02:00
|
|
|
# access a non-existing private object member variable
|
2023-08-29 22:32:02 +02:00
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
2023-09-17 17:03:19 +02:00
|
|
|
class A
|
|
|
|
this._val = 10
|
2023-08-29 22:32:02 +02:00
|
|
|
endclass
|
2023-09-17 17:03:19 +02:00
|
|
|
def T()
|
|
|
|
var a = A.new()
|
|
|
|
a._a = 1
|
|
|
|
enddef
|
|
|
|
T()
|
2023-08-29 22:32:02 +02:00
|
|
|
END
|
2023-09-18 19:56:49 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1326: Member not found on object "A": _a')
|
2023-08-29 22:32:02 +02:00
|
|
|
|
2023-09-17 17:03:19 +02:00
|
|
|
# private static member variable
|
2023-09-04 22:30:41 +02:00
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
2023-09-17 17:03:19 +02:00
|
|
|
class A
|
|
|
|
static _val = 10
|
|
|
|
endclass
|
|
|
|
def T()
|
|
|
|
var a = A.new()
|
|
|
|
var x = a._val
|
2023-09-04 22:30:41 +02:00
|
|
|
enddef
|
2023-09-17 17:03:19 +02:00
|
|
|
T()
|
2023-09-04 22:30:41 +02:00
|
|
|
END
|
2023-09-17 17:03:19 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1375: Class member "_val" accessible only using class "A"')
|
2023-09-04 22:30:41 +02:00
|
|
|
|
2023-09-17 17:03:19 +02:00
|
|
|
# private static member variable
|
2023-09-04 22:30:41 +02:00
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
static _val = 10
|
|
|
|
endclass
|
|
|
|
def T()
|
|
|
|
var a = A.new()
|
|
|
|
a._val = 3
|
|
|
|
enddef
|
|
|
|
T()
|
|
|
|
END
|
2023-09-18 19:56:49 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1375: Class member "_val" accessible only using class "A"')
|
2023-09-04 22:30:41 +02:00
|
|
|
|
|
|
|
# private static class variable
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
static _val = 10
|
|
|
|
endclass
|
|
|
|
def T()
|
|
|
|
var x = A._val
|
|
|
|
enddef
|
|
|
|
T()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1333: Cannot access private member: _val')
|
2023-09-04 22:30:41 +02:00
|
|
|
|
|
|
|
# private static class variable
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
static _val = 10
|
|
|
|
endclass
|
|
|
|
def T()
|
|
|
|
A._val = 3
|
|
|
|
enddef
|
|
|
|
T()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1333: Cannot access private member: _val')
|
2023-08-31 18:10:46 +02:00
|
|
|
enddef
|
|
|
|
|
|
|
|
" Test for changing the member access of an interface in a implementation class
|
|
|
|
def Test_change_interface_member_access()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
interface A
|
|
|
|
public this.val: number
|
|
|
|
endinterface
|
|
|
|
class B implements A
|
|
|
|
this.val = 10
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1367: Access level of member "val" of interface "A" is different')
|
2023-08-31 18:10:46 +02:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
interface A
|
|
|
|
this.val: number
|
|
|
|
endinterface
|
|
|
|
class B implements A
|
|
|
|
public this.val = 10
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1367: Access level of member "val" of interface "A" is different')
|
2023-08-31 18:10:46 +02:00
|
|
|
enddef
|
|
|
|
|
|
|
|
" Test for trying to change a readonly member from a def function
|
|
|
|
def Test_readonly_member_change_in_def_func()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
this.val: number
|
|
|
|
endclass
|
|
|
|
def T()
|
|
|
|
var a = A.new()
|
|
|
|
a.val = 20
|
|
|
|
enddef
|
|
|
|
T()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E46: Cannot change read-only variable "val"')
|
2023-08-30 16:38:26 +02:00
|
|
|
enddef
|
|
|
|
|
2023-09-01 22:05:45 +02:00
|
|
|
" Test for reading and writing a class member from a def function
|
|
|
|
def Test_modify_class_member_from_def_function()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
this.var1: number = 10
|
2023-09-04 07:51:01 +02:00
|
|
|
public static var2: list<number> = [1, 2]
|
|
|
|
public static var3: dict<number> = {a: 1, b: 2}
|
2023-09-01 22:05:45 +02:00
|
|
|
static _priv_var4: number = 40
|
|
|
|
endclass
|
|
|
|
def T()
|
2023-09-04 07:51:01 +02:00
|
|
|
assert_equal([1, 2], A.var2)
|
|
|
|
assert_equal({a: 1, b: 2}, A.var3)
|
|
|
|
A.var2 = [3, 4]
|
|
|
|
A.var3 = {c: 3, d: 4}
|
|
|
|
assert_equal([3, 4], A.var2)
|
|
|
|
assert_equal({c: 3, d: 4}, A.var3)
|
2023-09-01 22:05:45 +02:00
|
|
|
assert_fails('echo A._priv_var4', 'E1333: Cannot access private member: _priv_var4')
|
|
|
|
enddef
|
|
|
|
T()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-09-01 22:05:45 +02:00
|
|
|
enddef
|
|
|
|
|
2023-09-06 20:23:23 +02:00
|
|
|
" Test for accessing a class member variable using an object
|
2023-09-09 11:33:29 +02:00
|
|
|
def Test_class_variable_access_using_object()
|
2023-09-06 20:23:23 +02:00
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
public static svar1: list<number> = [1]
|
|
|
|
public static svar2: list<number> = [2]
|
|
|
|
endclass
|
|
|
|
|
|
|
|
A.svar1->add(3)
|
|
|
|
A.svar2->add(4)
|
|
|
|
assert_equal([1, 3], A.svar1)
|
|
|
|
assert_equal([2, 4], A.svar2)
|
|
|
|
|
|
|
|
def Foo()
|
|
|
|
A.svar1->add(7)
|
|
|
|
A.svar2->add(8)
|
2023-09-09 11:33:29 +02:00
|
|
|
assert_equal([1, 3, 7], A.svar1)
|
|
|
|
assert_equal([2, 4, 8], A.svar2)
|
2023-09-06 20:23:23 +02:00
|
|
|
enddef
|
|
|
|
Foo()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-09-09 11:33:29 +02:00
|
|
|
|
|
|
|
# Cannot read from a class variable using an object in script context
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
public this.var1: number
|
|
|
|
public static svar2: list<number> = [1]
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var a = A.new()
|
|
|
|
echo a.svar2
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1375: Class member "svar2" accessible only using class "A"')
|
2023-09-09 11:33:29 +02:00
|
|
|
|
|
|
|
# Cannot write to a class variable using an object in script context
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
public this.var1: number
|
|
|
|
public static svar2: list<number> = [1]
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var a = A.new()
|
|
|
|
a.svar2 = [2]
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1375: Class member "svar2" accessible only using class "A"')
|
2023-09-09 11:33:29 +02:00
|
|
|
|
|
|
|
# Cannot read from a class variable using an object in def method context
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
public this.var1: number
|
|
|
|
public static svar2: list<number> = [1]
|
|
|
|
endclass
|
|
|
|
|
|
|
|
def T()
|
|
|
|
var a = A.new()
|
|
|
|
echo a.svar2
|
|
|
|
enddef
|
|
|
|
T()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1375: Class member "svar2" accessible only using class "A"')
|
2023-09-09 11:33:29 +02:00
|
|
|
|
|
|
|
# Cannot write to a class variable using an object in def method context
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
public this.var1: number
|
|
|
|
public static svar2: list<number> = [1]
|
|
|
|
endclass
|
|
|
|
|
|
|
|
def T()
|
|
|
|
var a = A.new()
|
|
|
|
a.svar2 = [2]
|
|
|
|
enddef
|
|
|
|
T()
|
|
|
|
END
|
2023-09-18 19:56:49 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1375: Class member "svar2" accessible only using class "A"')
|
2023-09-06 20:23:23 +02:00
|
|
|
enddef
|
|
|
|
|
2023-09-08 19:12:03 +02:00
|
|
|
" Test for using a interface method using a child object
|
|
|
|
def Test_interface_method_from_child()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
interface A
|
|
|
|
def Foo(): string
|
|
|
|
endinterface
|
|
|
|
|
|
|
|
class B implements A
|
|
|
|
def Foo(): string
|
|
|
|
return 'foo'
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class C extends B
|
|
|
|
def Bar(): string
|
|
|
|
return 'bar'
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
def T1(a: A)
|
|
|
|
assert_equal('foo', a.Foo())
|
|
|
|
enddef
|
|
|
|
|
|
|
|
def T2(b: B)
|
|
|
|
assert_equal('foo', b.Foo())
|
|
|
|
enddef
|
|
|
|
|
|
|
|
var c = C.new()
|
|
|
|
T1(c)
|
|
|
|
T2(c)
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-09-08 19:12:03 +02:00
|
|
|
enddef
|
|
|
|
|
|
|
|
" Test for using an interface method using a child object when it is overridden
|
|
|
|
" by the child class.
|
|
|
|
" FIXME: This test fails.
|
|
|
|
" def Test_interface_overridden_method_from_child()
|
|
|
|
" var lines =<< trim END
|
|
|
|
" vim9script
|
|
|
|
"
|
|
|
|
" interface A
|
|
|
|
" def Foo(): string
|
|
|
|
" endinterface
|
|
|
|
"
|
|
|
|
" class B implements A
|
|
|
|
" def Foo(): string
|
|
|
|
" return 'b-foo'
|
|
|
|
" enddef
|
|
|
|
" endclass
|
|
|
|
"
|
|
|
|
" class C extends B
|
|
|
|
" def Bar(): string
|
|
|
|
" return 'bar'
|
|
|
|
" enddef
|
|
|
|
" def Foo(): string
|
|
|
|
" return 'c-foo'
|
|
|
|
" enddef
|
|
|
|
" endclass
|
|
|
|
"
|
|
|
|
" def T1(a: A)
|
|
|
|
" assert_equal('c-foo', a.Foo())
|
|
|
|
" enddef
|
|
|
|
"
|
|
|
|
" def T2(b: B)
|
|
|
|
" assert_equal('c-foo', b.Foo())
|
|
|
|
" enddef
|
|
|
|
"
|
|
|
|
" var c = C.new()
|
|
|
|
" T1(c)
|
|
|
|
" T2(c)
|
|
|
|
" END
|
2023-09-15 20:14:55 +02:00
|
|
|
" v9.CheckSourceSuccess(lines)
|
2023-09-08 19:12:03 +02:00
|
|
|
" enddef
|
|
|
|
|
2023-09-08 19:27:51 +02:00
|
|
|
" Test for abstract methods
|
|
|
|
def Test_abstract_method()
|
|
|
|
# Use two abstract methods
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
abstract class A
|
|
|
|
def M1(): number
|
|
|
|
return 10
|
|
|
|
enddef
|
|
|
|
abstract def M2(): number
|
|
|
|
abstract def M3(): number
|
|
|
|
endclass
|
|
|
|
class B extends A
|
|
|
|
def M2(): number
|
|
|
|
return 20
|
|
|
|
enddef
|
|
|
|
def M3(): number
|
|
|
|
return 30
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
var b = B.new()
|
|
|
|
assert_equal([10, 20, 30], [b.M1(), b.M2(), b.M3()])
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-09-08 19:27:51 +02:00
|
|
|
|
|
|
|
# Don't define an abstract method
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
abstract class A
|
|
|
|
abstract def Foo()
|
|
|
|
endclass
|
|
|
|
class B extends A
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1373: Abstract method "Foo" is not implemented')
|
2023-09-08 19:27:51 +02:00
|
|
|
|
|
|
|
# Use abstract method in a concrete class
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
abstract def Foo()
|
|
|
|
endclass
|
|
|
|
class B extends A
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1372: Abstract method "abstract def Foo()" cannot be defined in a concrete class')
|
2023-09-08 19:27:51 +02:00
|
|
|
|
|
|
|
# Use abstract method in an interface
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
interface A
|
|
|
|
abstract def Foo()
|
|
|
|
endinterface
|
|
|
|
class B implements A
|
2023-09-17 17:03:19 +02:00
|
|
|
def Foo()
|
|
|
|
enddef
|
2023-09-08 19:27:51 +02:00
|
|
|
endclass
|
|
|
|
END
|
2023-09-17 17:03:19 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-09-08 19:27:51 +02:00
|
|
|
|
|
|
|
# Abbreviate the "abstract" keyword
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
abs def Foo()
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: abs def Foo()')
|
2023-09-08 19:27:51 +02:00
|
|
|
|
|
|
|
# Use "abstract" with a member variable
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
abstract class A
|
|
|
|
abstract this.val = 10
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1371: Abstract must be followed by "def" or "static"')
|
2023-09-08 19:27:51 +02:00
|
|
|
|
|
|
|
# Use a static abstract method
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
abstract class A
|
|
|
|
abstract static def Foo(): number
|
|
|
|
endclass
|
|
|
|
class B extends A
|
|
|
|
static def Foo(): number
|
|
|
|
return 4
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
assert_equal(4, B.Foo())
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-09-08 19:27:51 +02:00
|
|
|
|
|
|
|
# Type mismatch between abstract method and concrete method
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
abstract class A
|
|
|
|
abstract def Foo(a: string, b: number): list<number>
|
|
|
|
endclass
|
|
|
|
class B extends A
|
|
|
|
def Foo(a: number, b: string): list<string>
|
|
|
|
return []
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-17 17:03:19 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1383: Method "Foo": type mismatch, expected func(string, number): list<number> but got func(number, string): list<string>')
|
2023-09-08 19:27:51 +02:00
|
|
|
|
|
|
|
# Use an abstract class to invoke an abstract method
|
|
|
|
# FIXME: This should fail
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
abstract class A
|
|
|
|
abstract static def Foo()
|
|
|
|
endclass
|
|
|
|
A.Foo()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-09-08 19:27:51 +02:00
|
|
|
|
|
|
|
# Invoke an abstract method from a def function
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
abstract class A
|
|
|
|
abstract def Foo(): list<number>
|
|
|
|
endclass
|
|
|
|
class B extends A
|
|
|
|
def Foo(): list<number>
|
|
|
|
return [3, 5]
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
def Bar(c: B)
|
|
|
|
assert_equal([3, 5], c.Foo())
|
|
|
|
enddef
|
|
|
|
var b = B.new()
|
|
|
|
Bar(b)
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
|
|
|
enddef
|
|
|
|
|
|
|
|
" Test for calling a class method from a subclass
|
|
|
|
def Test_class_method_call_from_subclass()
|
|
|
|
# class method call from a subclass
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class A
|
|
|
|
static def Foo()
|
|
|
|
echo "foo"
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class B extends A
|
|
|
|
def Bar()
|
|
|
|
Foo()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var b = B.new()
|
|
|
|
b.Bar()
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1374: Class member "Foo" accessible only inside class "A"')
|
2023-09-08 19:27:51 +02:00
|
|
|
enddef
|
|
|
|
|
2023-09-09 11:37:23 +02:00
|
|
|
" Test for calling a class method using an object in a def function context and
|
|
|
|
" script context.
|
|
|
|
def Test_class_method_call_using_object()
|
|
|
|
# script context
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
static def Foo(): list<string>
|
|
|
|
return ['a', 'b']
|
|
|
|
enddef
|
|
|
|
def Bar()
|
|
|
|
assert_equal(['a', 'b'], A.Foo())
|
|
|
|
assert_equal(['a', 'b'], Foo())
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
def T()
|
|
|
|
assert_equal(['a', 'b'], A.Foo())
|
|
|
|
var t_a = A.new()
|
|
|
|
t_a.Bar()
|
|
|
|
enddef
|
|
|
|
|
|
|
|
assert_equal(['a', 'b'], A.Foo())
|
|
|
|
var a = A.new()
|
|
|
|
a.Bar()
|
|
|
|
T()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-09-09 11:37:23 +02:00
|
|
|
|
|
|
|
# script context
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
static def Foo(): string
|
|
|
|
return 'foo'
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var a = A.new()
|
|
|
|
assert_equal('foo', a.Foo())
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1375: Class member "Foo" accessible only using class "A"')
|
2023-09-09 11:37:23 +02:00
|
|
|
|
|
|
|
# def function context
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
static def Foo(): string
|
|
|
|
return 'foo'
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
def T()
|
|
|
|
var a = A.new()
|
|
|
|
assert_equal('foo', a.Foo())
|
|
|
|
enddef
|
|
|
|
T()
|
|
|
|
END
|
2023-09-15 20:14:55 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1375: Class member "Foo" accessible only using class "A"')
|
|
|
|
enddef
|
|
|
|
|
|
|
|
def Test_class_variable()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class A
|
|
|
|
public static val: number = 10
|
|
|
|
static def ClassFunc()
|
|
|
|
assert_equal(10, val)
|
|
|
|
enddef
|
|
|
|
def ObjFunc()
|
|
|
|
assert_equal(10, val)
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class B extends A
|
|
|
|
endclass
|
|
|
|
|
|
|
|
assert_equal(10, A.val)
|
|
|
|
A.ClassFunc()
|
|
|
|
var a = A.new()
|
|
|
|
a.ObjFunc()
|
|
|
|
var b = B.new()
|
|
|
|
b.ObjFunc()
|
|
|
|
|
|
|
|
def T1(a1: A)
|
|
|
|
a1.ObjFunc()
|
|
|
|
A.ClassFunc()
|
|
|
|
enddef
|
|
|
|
T1(b)
|
|
|
|
|
|
|
|
A.val = 20
|
|
|
|
assert_equal(20, A.val)
|
|
|
|
END
|
|
|
|
v9.CheckSourceSuccess(lines)
|
|
|
|
|
|
|
|
# Modifying a parent class variable from a child class method
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class A
|
|
|
|
static val: number = 10
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class B extends A
|
|
|
|
static def ClassFunc()
|
|
|
|
val = 20
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
B.ClassFunc()
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1374: Class member "val" accessible only inside class "A"')
|
|
|
|
|
|
|
|
# Reading a parent class variable from a child class method
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class A
|
|
|
|
static val: number = 10
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class B extends A
|
|
|
|
static def ClassFunc()
|
|
|
|
var i = val
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
B.ClassFunc()
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1374: Class member "val" accessible only inside class "A"')
|
|
|
|
|
|
|
|
# Modifying a parent class variable from a child object method
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class A
|
|
|
|
static val: number = 10
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class B extends A
|
|
|
|
def ObjFunc()
|
|
|
|
val = 20
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
var b = B.new()
|
|
|
|
b.ObjFunc()
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1374: Class member "val" accessible only inside class "A"')
|
|
|
|
|
|
|
|
# Reading a parent class variable from a child object method
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class A
|
|
|
|
static val: number = 10
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class B extends A
|
|
|
|
def ObjFunc()
|
|
|
|
var i = val
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
var b = B.new()
|
|
|
|
b.ObjFunc()
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1374: Class member "val" accessible only inside class "A"')
|
|
|
|
|
|
|
|
# Modifying a class variable using an object at script level
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class A
|
|
|
|
static val: number = 10
|
|
|
|
endclass
|
|
|
|
var a = A.new()
|
|
|
|
a.val = 20
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1375: Class member "val" accessible only using class "A"')
|
|
|
|
|
|
|
|
# Reading a class variable using an object at script level
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class A
|
|
|
|
static val: number = 10
|
|
|
|
endclass
|
|
|
|
var a = A.new()
|
|
|
|
var i = a.val
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1375: Class member "val" accessible only using class "A"')
|
|
|
|
|
|
|
|
# Modifying a class variable using an object at function level
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class A
|
|
|
|
static val: number = 10
|
|
|
|
endclass
|
|
|
|
|
|
|
|
def T()
|
|
|
|
var a = A.new()
|
|
|
|
a.val = 20
|
|
|
|
enddef
|
|
|
|
T()
|
|
|
|
END
|
2023-09-18 19:56:49 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1375: Class member "val" accessible only using class "A"')
|
2023-09-15 20:14:55 +02:00
|
|
|
|
|
|
|
# Reading a class variable using an object at function level
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class A
|
|
|
|
static val: number = 10
|
|
|
|
endclass
|
|
|
|
def T()
|
|
|
|
var a = A.new()
|
|
|
|
var i = a.val
|
|
|
|
enddef
|
|
|
|
T()
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1375: Class member "val" accessible only using class "A"')
|
|
|
|
enddef
|
|
|
|
|
|
|
|
" Test for using a duplicate class method and class variable in a child class
|
|
|
|
def Test_dup_class_member()
|
|
|
|
# duplicate class variable, class method and overridden object method
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
static sval = 100
|
|
|
|
static def Check()
|
|
|
|
assert_equal(100, sval)
|
|
|
|
enddef
|
|
|
|
def GetVal(): number
|
|
|
|
return sval
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class B extends A
|
|
|
|
static sval = 200
|
|
|
|
static def Check()
|
|
|
|
assert_equal(200, sval)
|
|
|
|
enddef
|
|
|
|
def GetVal(): number
|
|
|
|
return sval
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
def T1(aa: A): number
|
|
|
|
return aa.GetVal()
|
|
|
|
enddef
|
|
|
|
|
|
|
|
def T2(bb: B): number
|
|
|
|
return bb.GetVal()
|
|
|
|
enddef
|
|
|
|
|
|
|
|
assert_equal(100, A.sval)
|
|
|
|
assert_equal(200, B.sval)
|
|
|
|
var a = A.new()
|
|
|
|
assert_equal(100, a.GetVal())
|
|
|
|
var b = B.new()
|
|
|
|
assert_equal(200, b.GetVal())
|
|
|
|
assert_equal(200, T1(b))
|
|
|
|
assert_equal(200, T2(b))
|
|
|
|
END
|
|
|
|
v9.CheckSourceSuccess(lines)
|
|
|
|
|
|
|
|
# duplicate class variable and class method
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
static sval = 100
|
|
|
|
static def Check()
|
|
|
|
assert_equal(100, sval)
|
|
|
|
enddef
|
|
|
|
def GetVal(): number
|
|
|
|
return sval
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class B extends A
|
|
|
|
static sval = 200
|
|
|
|
static def Check()
|
|
|
|
assert_equal(200, sval)
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
def T1(aa: A): number
|
|
|
|
return aa.GetVal()
|
|
|
|
enddef
|
|
|
|
|
|
|
|
def T2(bb: B): number
|
|
|
|
return bb.GetVal()
|
|
|
|
enddef
|
|
|
|
|
|
|
|
assert_equal(100, A.sval)
|
|
|
|
assert_equal(200, B.sval)
|
|
|
|
var a = A.new()
|
|
|
|
assert_equal(100, a.GetVal())
|
|
|
|
var b = B.new()
|
|
|
|
assert_equal(100, b.GetVal())
|
|
|
|
assert_equal(100, T1(b))
|
|
|
|
assert_equal(100, T2(b))
|
|
|
|
END
|
|
|
|
v9.CheckSourceSuccess(lines)
|
|
|
|
enddef
|
|
|
|
|
|
|
|
" Test for calling an instance method using the class
|
|
|
|
def Test_instance_method_call_using_class()
|
|
|
|
# Invoke an object method using a class in script context
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
def Foo()
|
|
|
|
echo "foo"
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
A.Foo()
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1376: Object member "Foo" accessible only using class "A" object')
|
|
|
|
|
|
|
|
# Invoke an object method using a class in def function context
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
def Foo()
|
|
|
|
echo "foo"
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
def T()
|
|
|
|
A.Foo()
|
|
|
|
enddef
|
|
|
|
T()
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1376: Object member "Foo" accessible only using class "A" object')
|
|
|
|
enddef
|
|
|
|
|
|
|
|
" Test for duplicate class method and instance method
|
|
|
|
def Test_dup_classmethod_objmethod()
|
|
|
|
# Duplicate instance method
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
static def Foo()
|
|
|
|
enddef
|
|
|
|
def Foo()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo')
|
|
|
|
|
|
|
|
# Duplicate private instance method
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
static def Foo()
|
|
|
|
enddef
|
|
|
|
def _Foo()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo')
|
|
|
|
|
|
|
|
# Duplicate class method
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
def Foo()
|
|
|
|
enddef
|
|
|
|
static def Foo()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1355: Duplicate function: Foo')
|
|
|
|
|
|
|
|
# Duplicate private class method
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
def Foo()
|
|
|
|
enddef
|
|
|
|
static def _Foo()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo')
|
|
|
|
|
|
|
|
# Duplicate private class and object method
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
def _Foo()
|
|
|
|
enddef
|
|
|
|
static def _Foo()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1355: Duplicate function: _Foo')
|
|
|
|
enddef
|
|
|
|
|
|
|
|
" Test for an instance method access level comparison with parent instance
|
|
|
|
" methods.
|
|
|
|
def Test_instance_method_access_level()
|
|
|
|
# Private method in subclass
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
def Foo()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
class B extends A
|
|
|
|
endclass
|
|
|
|
class C extends B
|
|
|
|
def _Foo()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-17 17:03:19 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1377: Access level of method "_Foo" is different in class "A"')
|
2023-09-15 20:14:55 +02:00
|
|
|
|
|
|
|
# Public method in subclass
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
def _Foo()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
class B extends A
|
|
|
|
endclass
|
|
|
|
class C extends B
|
|
|
|
def Foo()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
END
|
2023-09-17 17:03:19 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1377: Access level of method "Foo" is different in class "A"')
|
2023-09-15 20:14:55 +02:00
|
|
|
enddef
|
|
|
|
|
|
|
|
def Test_extend_empty_class()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
endclass
|
|
|
|
class B extends A
|
|
|
|
endclass
|
|
|
|
class C extends B
|
|
|
|
public static rw_class_var = 1
|
|
|
|
public this.rw_obj_var = 2
|
|
|
|
static def ClassMethod(): number
|
|
|
|
return 3
|
|
|
|
enddef
|
|
|
|
def ObjMethod(): number
|
|
|
|
return 4
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
assert_equal(1, C.rw_class_var)
|
|
|
|
assert_equal(3, C.ClassMethod())
|
|
|
|
var c = C.new()
|
|
|
|
assert_equal(2, c.rw_obj_var)
|
|
|
|
assert_equal(4, c.ObjMethod())
|
|
|
|
END
|
|
|
|
v9.CheckSourceSuccess(lines)
|
2023-09-09 11:37:23 +02:00
|
|
|
enddef
|
|
|
|
|
2023-09-17 17:03:19 +02:00
|
|
|
" A interface cannot have a static variable or a static method or a private
|
|
|
|
" variable or a private method
|
|
|
|
def Test_interface_with_unsupported_members()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
interface A
|
|
|
|
static num: number
|
|
|
|
endinterface
|
|
|
|
END
|
2023-09-18 19:56:49 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface')
|
2023-09-17 17:03:19 +02:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
interface A
|
|
|
|
static _num: number
|
|
|
|
endinterface
|
|
|
|
END
|
2023-09-18 19:56:49 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface')
|
2023-09-17 17:03:19 +02:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
interface A
|
|
|
|
public static num: number
|
|
|
|
endinterface
|
|
|
|
END
|
2023-09-18 19:56:49 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface')
|
2023-09-17 17:03:19 +02:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
interface A
|
|
|
|
public static _num: number
|
|
|
|
endinterface
|
|
|
|
END
|
2023-09-18 19:56:49 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface')
|
2023-09-17 17:03:19 +02:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
interface A
|
|
|
|
static def Foo(d: dict<any>): list<string>
|
|
|
|
endinterface
|
|
|
|
END
|
2023-09-18 19:56:49 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface')
|
2023-09-17 17:03:19 +02:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
interface A
|
|
|
|
static def _Foo(d: dict<any>): list<string>
|
|
|
|
endinterface
|
|
|
|
END
|
2023-09-18 19:56:49 +02:00
|
|
|
v9.CheckSourceFailure(lines, 'E1378: Static member not supported in an interface')
|
2023-09-17 17:03:19 +02:00
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
interface A
|
|
|
|
this._Foo: list<string>
|
|
|
|
endinterface
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1379: Private variable not supported in an interface')
|
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
interface A
|
|
|
|
def _Foo(d: dict<any>): list<string>
|
|
|
|
endinterface
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1380: Private method not supported in an interface')
|
|
|
|
enddef
|
|
|
|
|
|
|
|
" Test for extending an interface
|
|
|
|
def Test_extend_interface()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
interface A
|
|
|
|
this.var1: list<string>
|
|
|
|
def Foo()
|
|
|
|
endinterface
|
|
|
|
interface B extends A
|
|
|
|
public this.var2: dict<string>
|
|
|
|
def Bar()
|
|
|
|
endinterface
|
|
|
|
class C implements A, B
|
|
|
|
this.var1 = [1, 2]
|
|
|
|
def Foo()
|
|
|
|
enddef
|
|
|
|
public this.var2 = {a: '1'}
|
|
|
|
def Bar()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
END
|
|
|
|
v9.CheckSourceSuccess(lines)
|
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
interface A
|
|
|
|
def Foo()
|
|
|
|
endinterface
|
|
|
|
interface B extends A
|
|
|
|
public this.var2: dict<string>
|
|
|
|
endinterface
|
|
|
|
class C implements A, B
|
|
|
|
public this.var2 = {a: '1'}
|
|
|
|
endclass
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1349: Method "Foo" of interface "A" is not implemented')
|
|
|
|
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
interface A
|
|
|
|
def Foo()
|
|
|
|
endinterface
|
|
|
|
interface B extends A
|
|
|
|
public this.var2: dict<string>
|
|
|
|
endinterface
|
|
|
|
class C implements A, B
|
|
|
|
def Foo()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1348: Member "var2" of interface "B" is not implemented')
|
|
|
|
|
|
|
|
# interface cannot extend a class
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
class A
|
|
|
|
endclass
|
|
|
|
interface B extends A
|
|
|
|
endinterface
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1354: Cannot extend A')
|
|
|
|
|
|
|
|
# class cannot extend an interface
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
interface A
|
|
|
|
endinterface
|
|
|
|
class B extends A
|
|
|
|
endclass
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1354: Cannot extend A')
|
|
|
|
|
|
|
|
# interface cannot implement another interface
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
interface A
|
|
|
|
endinterface
|
|
|
|
interface B implements A
|
|
|
|
endinterface
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1381: Interface cannot use "implements"')
|
|
|
|
|
|
|
|
# interface cannot extend multiple interfaces
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
interface A
|
|
|
|
endinterface
|
|
|
|
interface B
|
|
|
|
endinterface
|
|
|
|
interface C extends A, B
|
|
|
|
endinterface
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1315: White space required after name: A, B')
|
|
|
|
|
|
|
|
# Variable type in an extended interface is of different type
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
interface A
|
|
|
|
this.val1: number
|
|
|
|
endinterface
|
|
|
|
interface B extends A
|
|
|
|
this.val2: string
|
|
|
|
endinterface
|
|
|
|
interface C extends B
|
|
|
|
this.val1: string
|
|
|
|
this.val2: number
|
|
|
|
endinterface
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1382: Member "val1": type mismatch, expected number but got string')
|
|
|
|
enddef
|
|
|
|
|
|
|
|
" Test for a child class implementing an interface when some of the methods are
|
|
|
|
" defined in the parent class.
|
|
|
|
def Test_child_class_implements_interface()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
interface Intf
|
|
|
|
def F1(): list<list<number>>
|
|
|
|
def F2(): list<list<number>>
|
|
|
|
def F3(): list<list<number>>
|
|
|
|
this.var1: list<dict<number>>
|
|
|
|
this.var2: list<dict<number>>
|
|
|
|
this.var3: list<dict<number>>
|
|
|
|
endinterface
|
|
|
|
|
|
|
|
class A
|
|
|
|
def A1()
|
|
|
|
enddef
|
|
|
|
def F3(): list<list<number>>
|
|
|
|
return [[3]]
|
|
|
|
enddef
|
|
|
|
this.v1: list<list<number>> = [[0]]
|
|
|
|
this.var3 = [{c: 30}]
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class B extends A
|
|
|
|
def B1()
|
|
|
|
enddef
|
|
|
|
def F2(): list<list<number>>
|
|
|
|
return [[2]]
|
|
|
|
enddef
|
|
|
|
this.v2: list<list<number>> = [[0]]
|
|
|
|
this.var2 = [{b: 20}]
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class C extends B implements Intf
|
|
|
|
def C1()
|
|
|
|
enddef
|
|
|
|
def F1(): list<list<number>>
|
|
|
|
return [[1]]
|
|
|
|
enddef
|
|
|
|
this.v3: list<list<number>> = [[0]]
|
|
|
|
this.var1 = [{a: 10}]
|
|
|
|
endclass
|
|
|
|
|
|
|
|
def T(if: Intf)
|
|
|
|
assert_equal([[1]], if.F1())
|
|
|
|
assert_equal([[2]], if.F2())
|
|
|
|
assert_equal([[3]], if.F3())
|
|
|
|
assert_equal([{a: 10}], if.var1)
|
|
|
|
assert_equal([{b: 20}], if.var2)
|
|
|
|
assert_equal([{c: 30}], if.var3)
|
|
|
|
enddef
|
|
|
|
|
|
|
|
var c = C.new()
|
|
|
|
T(c)
|
|
|
|
assert_equal([[1]], c.F1())
|
|
|
|
assert_equal([[2]], c.F2())
|
|
|
|
assert_equal([[3]], c.F3())
|
|
|
|
assert_equal([{a: 10}], c.var1)
|
|
|
|
assert_equal([{b: 20}], c.var2)
|
|
|
|
assert_equal([{c: 30}], c.var3)
|
|
|
|
END
|
|
|
|
v9.CheckSourceSuccess(lines)
|
|
|
|
|
|
|
|
# One of the interface methods is not found
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
interface Intf
|
|
|
|
def F1()
|
|
|
|
def F2()
|
|
|
|
def F3()
|
|
|
|
endinterface
|
|
|
|
|
|
|
|
class A
|
|
|
|
def A1()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class B extends A
|
|
|
|
def B1()
|
|
|
|
enddef
|
|
|
|
def F2()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class C extends B implements Intf
|
|
|
|
def C1()
|
|
|
|
enddef
|
|
|
|
def F1()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1349: Method "F3" of interface "Intf" is not implemented')
|
|
|
|
|
|
|
|
# One of the interface methods is of different type
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
interface Intf
|
|
|
|
def F1()
|
|
|
|
def F2()
|
|
|
|
def F3()
|
|
|
|
endinterface
|
|
|
|
|
|
|
|
class A
|
|
|
|
def F3(): number
|
|
|
|
return 0
|
|
|
|
enddef
|
|
|
|
def A1()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class B extends A
|
|
|
|
def B1()
|
|
|
|
enddef
|
|
|
|
def F2()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class C extends B implements Intf
|
|
|
|
def C1()
|
|
|
|
enddef
|
|
|
|
def F1()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1383: Method "F3": type mismatch, expected func() but got func(): number')
|
|
|
|
|
|
|
|
# One of the interface variables is not present
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
interface Intf
|
|
|
|
this.var1: list<dict<number>>
|
|
|
|
this.var2: list<dict<number>>
|
|
|
|
this.var3: list<dict<number>>
|
|
|
|
endinterface
|
|
|
|
|
|
|
|
class A
|
|
|
|
this.v1: list<list<number>> = [[0]]
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class B extends A
|
|
|
|
this.v2: list<list<number>> = [[0]]
|
|
|
|
this.var2 = [{b: 20}]
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class C extends B implements Intf
|
|
|
|
this.v3: list<list<number>> = [[0]]
|
|
|
|
this.var1 = [{a: 10}]
|
|
|
|
endclass
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1348: Member "var3" of interface "Intf" is not implemented')
|
|
|
|
|
|
|
|
# One of the interface variables is of different type
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
interface Intf
|
|
|
|
this.var1: list<dict<number>>
|
|
|
|
this.var2: list<dict<number>>
|
|
|
|
this.var3: list<dict<number>>
|
|
|
|
endinterface
|
|
|
|
|
|
|
|
class A
|
|
|
|
this.v1: list<list<number>> = [[0]]
|
|
|
|
this.var3: list<dict<string>>
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class B extends A
|
|
|
|
this.v2: list<list<number>> = [[0]]
|
|
|
|
this.var2 = [{b: 20}]
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class C extends B implements Intf
|
|
|
|
this.v3: list<list<number>> = [[0]]
|
|
|
|
this.var1 = [{a: 10}]
|
|
|
|
endclass
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1382: Member "var3": type mismatch, expected list<dict<number>> but got list<dict<string>>')
|
|
|
|
enddef
|
|
|
|
|
|
|
|
" Test for extending an interface with duplicate variables and methods
|
|
|
|
def Test_interface_extends_with_dup_members()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
interface A
|
|
|
|
this.n1: number
|
|
|
|
def Foo1(): number
|
|
|
|
endinterface
|
|
|
|
interface B extends A
|
|
|
|
this.n2: number
|
|
|
|
this.n1: number
|
|
|
|
def Foo2(): number
|
|
|
|
def Foo1(): number
|
|
|
|
endinterface
|
|
|
|
class C implements B
|
|
|
|
this.n1 = 10
|
|
|
|
this.n2 = 20
|
|
|
|
def Foo1(): number
|
|
|
|
return 30
|
|
|
|
enddef
|
|
|
|
def Foo2(): number
|
|
|
|
return 40
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
def T1(a: A)
|
|
|
|
assert_equal(10, a.n1)
|
|
|
|
assert_equal(30, a.Foo1())
|
|
|
|
enddef
|
|
|
|
def T2(b: B)
|
|
|
|
assert_equal(10, b.n1)
|
|
|
|
assert_equal(20, b.n2)
|
|
|
|
assert_equal(30, b.Foo1())
|
|
|
|
assert_equal(40, b.Foo2())
|
|
|
|
enddef
|
|
|
|
var c = C.new()
|
|
|
|
T1(c)
|
|
|
|
T2(c)
|
|
|
|
END
|
|
|
|
v9.CheckSourceSuccess(lines)
|
|
|
|
enddef
|
|
|
|
|
|
|
|
" Test for using "any" type for a variable in a sub-class while it has a
|
|
|
|
" concrete type in the interface
|
|
|
|
def Test_implements_using_var_type_any()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
interface A
|
|
|
|
this.val: list<dict<string>>
|
|
|
|
endinterface
|
|
|
|
class B implements A
|
|
|
|
this.val = [{a: '1'}, {b: '2'}]
|
|
|
|
endclass
|
|
|
|
var b = B.new()
|
|
|
|
assert_equal([{a: '1'}, {b: '2'}], b.val)
|
|
|
|
END
|
|
|
|
v9.CheckSourceSuccess(lines)
|
|
|
|
|
|
|
|
# initialize instance variable using a different type
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
interface A
|
|
|
|
this.val: list<dict<string>>
|
|
|
|
endinterface
|
|
|
|
class B implements A
|
|
|
|
this.val = {a: 1, b: 2}
|
|
|
|
endclass
|
|
|
|
var b = B.new()
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1382: Member "val": type mismatch, expected list<dict<string>> but got dict<number>')
|
|
|
|
enddef
|
|
|
|
|
2023-09-18 19:56:49 +02:00
|
|
|
" Test for assigning to a member variable in a nested class
|
|
|
|
def Test_nested_object_assignment()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class A
|
|
|
|
this.value: number
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class B
|
|
|
|
this.a: A = A.new()
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class C
|
|
|
|
this.b: B = B.new()
|
|
|
|
endclass
|
|
|
|
|
|
|
|
class D
|
|
|
|
this.c: C = C.new()
|
|
|
|
endclass
|
|
|
|
|
|
|
|
def T(da: D)
|
|
|
|
da.c.b.a.value = 10
|
|
|
|
enddef
|
|
|
|
|
|
|
|
var d = D.new()
|
|
|
|
T(d)
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E46: Cannot change read-only variable "value"')
|
|
|
|
enddef
|
|
|
|
|
2023-09-19 20:34:05 +02:00
|
|
|
" Test for calling methods using a null object
|
|
|
|
def Test_null_object_method_call()
|
|
|
|
# Calling a object method using a null object in script context
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class C
|
|
|
|
def Foo()
|
|
|
|
assert_report('This method should not be executed')
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var o: C
|
|
|
|
o.Foo()
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1360: Using a null object', 10)
|
|
|
|
|
|
|
|
# Calling a object method using a null object in def function context
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class C
|
|
|
|
def Foo()
|
|
|
|
assert_report('This method should not be executed')
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
def T()
|
|
|
|
var o: C
|
|
|
|
o.Foo()
|
|
|
|
enddef
|
|
|
|
T()
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
|
|
|
|
|
|
|
|
# Calling a object method through another class method using a null object in
|
|
|
|
# script context
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class C
|
|
|
|
def Foo()
|
|
|
|
assert_report('This method should not be executed')
|
|
|
|
enddef
|
|
|
|
|
|
|
|
static def Bar(o_any: any)
|
|
|
|
var o_typed: C = o_any
|
|
|
|
o_typed.Foo()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var o: C
|
|
|
|
C.Bar(o)
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
|
|
|
|
|
|
|
|
# Calling a object method through another class method using a null object in
|
|
|
|
# def function context
|
|
|
|
lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class C
|
|
|
|
def Foo()
|
|
|
|
assert_report('This method should not be executed')
|
|
|
|
enddef
|
|
|
|
|
|
|
|
static def Bar(o_any: any)
|
|
|
|
var o_typed: C = o_any
|
|
|
|
o_typed.Foo()
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
def T()
|
|
|
|
var o: C
|
|
|
|
C.Bar(o)
|
|
|
|
enddef
|
|
|
|
T()
|
|
|
|
END
|
|
|
|
v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2)
|
|
|
|
enddef
|
|
|
|
|
|
|
|
" Test for using a dict as an object member
|
|
|
|
def Test_dict_object_member()
|
|
|
|
var lines =<< trim END
|
|
|
|
vim9script
|
|
|
|
|
|
|
|
class Context
|
|
|
|
public this.state: dict<number> = {}
|
|
|
|
def GetState(): dict<number>
|
|
|
|
return this.state
|
|
|
|
enddef
|
|
|
|
endclass
|
|
|
|
|
|
|
|
var ctx = Context.new()
|
|
|
|
ctx.state->extend({a: 1})
|
|
|
|
ctx.state['b'] = 2
|
|
|
|
assert_equal({a: 1, b: 2}, ctx.GetState())
|
|
|
|
|
|
|
|
def F()
|
|
|
|
ctx.state['c'] = 3
|
|
|
|
assert_equal({a: 1, b: 2, c: 3}, ctx.GetState())
|
|
|
|
enddef
|
|
|
|
F()
|
|
|
|
assert_equal(3, ctx.state.c)
|
|
|
|
ctx.state.c = 4
|
|
|
|
assert_equal(4, ctx.state.c)
|
|
|
|
END
|
|
|
|
v9.CheckSourceSuccess(lines)
|
|
|
|
enddef
|
|
|
|
|
2022-12-08 15:32:33 +00:00
|
|
|
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
|