forked from aniani/vim
patch 9.1.0850: Vim9: cannot access nested object inside objects
Problem: Vim9: cannot access nested object inside objects
(lifepillar, 91khr, mawkish)
Solution: Add support for accessing an object member using a "any"
variable type (Yegappan Lakshmanan)
fixes: #11822
fixes: #12024
fixes: #12196
fixes: #12198
closes: #16029
Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
committed by
Christian Brabandt
parent
622f6f5b9a
commit
56d45f1b66
@@ -784,7 +784,7 @@ def Test_member_any_used_as_object()
|
||||
vim9script
|
||||
|
||||
class Inner
|
||||
var value: number = 0
|
||||
public var value: number = 0
|
||||
endclass
|
||||
|
||||
class Outer
|
||||
@@ -11213,4 +11213,339 @@ def Test_class_cast()
|
||||
v9.CheckScriptSuccess(lines)
|
||||
enddef
|
||||
|
||||
" Test for using a variable of type "any" with an object
|
||||
def Test_any_obj_var_type()
|
||||
var lines =<< trim END
|
||||
vim9script
|
||||
class A
|
||||
var name: string = "foobar"
|
||||
def Foo(): string
|
||||
return "func foo"
|
||||
enddef
|
||||
endclass
|
||||
|
||||
def CheckVals(x: any)
|
||||
assert_equal("foobar", x.name)
|
||||
assert_equal("func foo", x.Foo())
|
||||
enddef
|
||||
|
||||
var a = A.new()
|
||||
CheckVals(a)
|
||||
END
|
||||
v9.CheckScriptSuccess(lines)
|
||||
|
||||
# Try to set a non-existing variable
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
class A
|
||||
var name: string = "foobar"
|
||||
endclass
|
||||
|
||||
def SetNonExistingVar(x: any)
|
||||
x.bar = [1, 2, 3]
|
||||
enddef
|
||||
|
||||
var a = A.new()
|
||||
SetNonExistingVar(a)
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1326: Variable "bar" not found in object "A"', 1)
|
||||
|
||||
# Try to read a non-existing variable
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
class A
|
||||
var name: string = "foobar"
|
||||
endclass
|
||||
|
||||
def GetNonExistingVar(x: any)
|
||||
var i: dict<any> = x.bar
|
||||
enddef
|
||||
|
||||
var a = A.new()
|
||||
GetNonExistingVar(a)
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1326: Variable "bar" not found in object "A"', 1)
|
||||
|
||||
# Try to invoke a non-existing method
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
class A
|
||||
def Foo(): number
|
||||
return 10
|
||||
enddef
|
||||
endclass
|
||||
|
||||
def CallNonExistingMethod(x: any)
|
||||
var i: number = x.Bar()
|
||||
enddef
|
||||
|
||||
var a = A.new()
|
||||
CallNonExistingMethod(a)
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1326: Variable "Bar" not found in object "A"', 1)
|
||||
|
||||
# Use an object which is a Dict value
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
class Foo
|
||||
def Bar(): number
|
||||
return 369
|
||||
enddef
|
||||
endclass
|
||||
|
||||
def GetValue(FooDict: dict<any>): number
|
||||
var n: number = 0
|
||||
for foo in values(FooDict)
|
||||
n += foo.Bar()
|
||||
endfor
|
||||
return n
|
||||
enddef
|
||||
|
||||
var d = {'x': Foo.new()}
|
||||
assert_equal(369, GetValue(d))
|
||||
END
|
||||
v9.CheckScriptSuccess(lines)
|
||||
|
||||
# Nested data. Object containg a Dict containing another Object.
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
class Context
|
||||
public var state: dict<any> = {}
|
||||
endclass
|
||||
|
||||
class Metadata
|
||||
public var value = 0
|
||||
endclass
|
||||
|
||||
var ctx = Context.new()
|
||||
ctx.state["meta"] = Metadata.new(2468)
|
||||
|
||||
const foo = ctx.state.meta.value
|
||||
|
||||
def F(): number
|
||||
const bar = ctx.state.meta.value
|
||||
return bar
|
||||
enddef
|
||||
|
||||
assert_equal(2468, F())
|
||||
END
|
||||
v9.CheckScriptSuccess(lines)
|
||||
|
||||
# Accessing an object from a method inside the class using any type
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
class C
|
||||
def _G(): string
|
||||
return '_G'
|
||||
enddef
|
||||
static def S(o_any: any): string
|
||||
return o_any._G()
|
||||
enddef
|
||||
endclass
|
||||
|
||||
var o1 = C.new()
|
||||
assert_equal('_G', C.S(o1))
|
||||
END
|
||||
v9.CheckScriptSuccess(lines)
|
||||
|
||||
# Modifying an object private variable from a method in another class using
|
||||
# any type
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
|
||||
class A
|
||||
var num = 10
|
||||
endclass
|
||||
|
||||
class B
|
||||
def SetVal(x: any)
|
||||
x.num = 20
|
||||
enddef
|
||||
endclass
|
||||
|
||||
var a = A.new()
|
||||
var b = B.new()
|
||||
b.SetVal(a)
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1335: Variable "num" in class "A" is not writable', 1)
|
||||
|
||||
# Accessing a object protected variable from a method in another class using
|
||||
# any type
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
|
||||
class A
|
||||
var _num = 10
|
||||
endclass
|
||||
|
||||
class B
|
||||
def GetVal(x: any): number
|
||||
return x._num
|
||||
enddef
|
||||
endclass
|
||||
|
||||
var a = A.new()
|
||||
var b = B.new()
|
||||
var i = b.GetVal(a)
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1333: Cannot access protected variable "_num" in class "A"', 1)
|
||||
|
||||
# Accessing an object returned from an imported function and class
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
export class Foo
|
||||
public var name: string
|
||||
endclass
|
||||
|
||||
export def ReturnFooObject(): Foo
|
||||
var r = Foo.new('star')
|
||||
return r
|
||||
enddef
|
||||
END
|
||||
writefile(lines, 'Xanyvar1.vim', 'D')
|
||||
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
|
||||
import './Xanyvar1.vim'
|
||||
|
||||
def GetName(): string
|
||||
var whatever = Xanyvar1.ReturnFooObject()
|
||||
return whatever.name
|
||||
enddef
|
||||
|
||||
assert_equal('star', GetName())
|
||||
END
|
||||
v9.CheckScriptSuccess(lines)
|
||||
|
||||
# Try to modify a private object variable using a variable of type "any"
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
|
||||
class Foo
|
||||
var n: number = 10
|
||||
endclass
|
||||
def Fn(x: any)
|
||||
x.n = 20
|
||||
enddef
|
||||
var a = Foo.new()
|
||||
Fn(a)
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1335: Variable "n" in class "Foo" is not writable', 1)
|
||||
|
||||
# Try to read a protected object variable using a variable of type "any"
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
|
||||
class Foo
|
||||
var _n: number = 10
|
||||
endclass
|
||||
def Fn(x: any): number
|
||||
return x._n
|
||||
enddef
|
||||
|
||||
var a = Foo.new()
|
||||
Fn(a)
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1333: Cannot access protected variable "_n" in class "Foo"', 1)
|
||||
|
||||
# Read a protected object variable using a variable of type "any" in an object
|
||||
# method
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
|
||||
class Foo
|
||||
var _n: number = 10
|
||||
def Fn(x: any): number
|
||||
return x._n
|
||||
enddef
|
||||
endclass
|
||||
|
||||
var a = Foo.new()
|
||||
assert_equal(10, a.Fn(a))
|
||||
END
|
||||
v9.CheckScriptSuccess(lines)
|
||||
|
||||
# Try to call a protected object method using a "any" type variable
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
|
||||
class Foo
|
||||
def _GetVal(): number
|
||||
return 234
|
||||
enddef
|
||||
endclass
|
||||
def Fn(x: any): number
|
||||
return x._GetVal()
|
||||
enddef
|
||||
|
||||
var a = Foo.new()
|
||||
Fn(a)
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1366: Cannot access protected method: _GetVal', 1)
|
||||
|
||||
# Call a protected object method using a "any" type variable from another
|
||||
# object method
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
|
||||
class Foo
|
||||
def _GetVal(): number
|
||||
return 234
|
||||
enddef
|
||||
def FooVal(x: any): number
|
||||
return x._GetVal()
|
||||
enddef
|
||||
endclass
|
||||
|
||||
var a = Foo.new()
|
||||
assert_equal(234, a.FooVal(a))
|
||||
END
|
||||
v9.CheckScriptSuccess(lines)
|
||||
|
||||
# Method chaining
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
|
||||
export class T
|
||||
var id: number = 268
|
||||
def F(): any
|
||||
return this
|
||||
enddef
|
||||
endclass
|
||||
|
||||
def H()
|
||||
var a = T.new().F().F()
|
||||
assert_equal(268, a.id)
|
||||
enddef
|
||||
H()
|
||||
|
||||
var b: T = T.new().F().F()
|
||||
assert_equal(268, b.id)
|
||||
END
|
||||
v9.CheckScriptSuccess(lines)
|
||||
|
||||
# Using a null object to access a member variable
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
def Fn(x: any): number
|
||||
return x.num
|
||||
enddef
|
||||
|
||||
Fn(null_object)
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1360: Using a null object', 1)
|
||||
|
||||
# Using a null object to invoke a method
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
def Fn(x: any)
|
||||
x.Foo()
|
||||
enddef
|
||||
|
||||
Fn(null_object)
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1360: Using a null object', 1)
|
||||
enddef
|
||||
|
||||
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
|
||||
|
||||
Reference in New Issue
Block a user