1
0
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:
Yegappan Lakshmanan
2024-11-11 19:58:55 +01:00
committed by Christian Brabandt
parent 622f6f5b9a
commit 56d45f1b66
7 changed files with 523 additions and 46 deletions

View File

@@ -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