mirror of
https://github.com/davidhalter/jedi.git
synced 2026-05-18 14:29:40 +08:00
fully functional classes
This commit is contained in:
+45
-50
@@ -119,11 +119,7 @@ class Instance(Executable):
|
|||||||
except IndexError:
|
except IndexError:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_defined_names(self):
|
def get_self_properties(self):
|
||||||
"""
|
|
||||||
Get the instance vars of a class. This includes the vars of all
|
|
||||||
classes
|
|
||||||
"""
|
|
||||||
def add_self_name(name):
|
def add_self_name(name):
|
||||||
n = copy.copy(name)
|
n = copy.copy(name)
|
||||||
n.names = n.names[1:]
|
n.names = n.names[1:]
|
||||||
@@ -146,9 +142,22 @@ class Instance(Executable):
|
|||||||
if n.names[0] == self_name and len(n.names) == 2:
|
if n.names[0] == self_name and len(n.names) == 2:
|
||||||
add_self_name(n)
|
add_self_name(n)
|
||||||
|
|
||||||
for var in self.base.get_defined_names(as_instance=True):
|
for s in self.base.get_super_classes():
|
||||||
|
names += Instance(s).get_self_properties()
|
||||||
|
|
||||||
|
return names
|
||||||
|
|
||||||
|
def get_defined_names(self):
|
||||||
|
"""
|
||||||
|
Get the instance vars of a class. This includes the vars of all
|
||||||
|
classes
|
||||||
|
"""
|
||||||
|
names = self.get_self_properties()
|
||||||
|
|
||||||
|
class_names = get_defined_names_for_position(self.base)
|
||||||
|
for var in class_names:
|
||||||
# functions are also instance elements
|
# functions are also instance elements
|
||||||
if isinstance(var.parent, (parsing.Function)):
|
if isinstance(var.parent, (parsing.Function, Function)):
|
||||||
var = InstanceElement(self, var)
|
var = InstanceElement(self, var)
|
||||||
names.append(var)
|
names.append(var)
|
||||||
|
|
||||||
@@ -197,38 +206,21 @@ class Class(object):
|
|||||||
def __init__(self, base):
|
def __init__(self, base):
|
||||||
self.base = base
|
self.base = base
|
||||||
|
|
||||||
def get_defined_names(self, as_instance=False):
|
@memoize_default(default=[])
|
||||||
def in_iterable(name, iterable):
|
def get_super_classes(self):
|
||||||
for i in iterable:
|
supers = []
|
||||||
# only the last name is important, because these names have a
|
|
||||||
# maximal length of 2, with the first one being `self`.
|
|
||||||
if i.names[-1] == name.names[-1]:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
names = self.base.get_defined_names()
|
|
||||||
|
|
||||||
# check super classes:
|
|
||||||
# TODO care for mro stuff (multiple super classes)
|
# TODO care for mro stuff (multiple super classes)
|
||||||
print 'supers', self, self.base
|
|
||||||
for s in self.base.supers:
|
for s in self.base.supers:
|
||||||
# super classes are statements
|
# super classes are statements
|
||||||
for cls in follow_statement(s):
|
for cls in follow_statement(s):
|
||||||
# get the inherited names
|
if not isinstance(cls, Class):
|
||||||
if as_instance:
|
debug.warning('Received non class, as a super class')
|
||||||
cls = Instance(cls)
|
continue # just ignore other stuff (user input error)
|
||||||
for i in cls.get_defined_names():
|
supers.append(cls)
|
||||||
if not in_iterable(i, names):
|
return supers
|
||||||
names.append(i)
|
|
||||||
print names
|
|
||||||
print
|
|
||||||
print
|
|
||||||
print self._get_defined_names()
|
|
||||||
return names
|
|
||||||
|
|
||||||
@memoize_default(default=[])
|
@memoize_default(default=[])
|
||||||
def _get_defined_names(self, as_instance=False):
|
def get_defined_names(self):
|
||||||
print " Class", self
|
|
||||||
def in_iterable(name, iterable):
|
def in_iterable(name, iterable):
|
||||||
""" checks if the name is in the variable 'iterable'. """
|
""" checks if the name is in the variable 'iterable'. """
|
||||||
for i in iterable:
|
for i in iterable:
|
||||||
@@ -238,31 +230,31 @@ class Class(object):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
"""
|
||||||
result = []
|
result = []
|
||||||
unique_vars = {} #set([n.names[-1] for n in names])
|
unique_vars = {} #set([n.names[-1] for n in names])
|
||||||
for n in self.base.get_defined_names():
|
for n in self.base.get_defined_names():
|
||||||
unique_vars[n.names[-1]] = n
|
unique_vars[n.names[-1]] = n
|
||||||
|
|
||||||
for key, name in unique_vars.items():
|
for key, name in unique_vars.items():
|
||||||
for s in get_scopes_for_name(self.base, key):
|
scopes = get_scopes_for_name(self.base, key)
|
||||||
|
for s in scopes:
|
||||||
n = copy.copy(name)
|
n = copy.copy(name)
|
||||||
n.parent = s
|
n.parent = s
|
||||||
result.append(n)
|
result.append(n)
|
||||||
|
if not scopes:
|
||||||
|
result.append(n)
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = self.base.get_defined_names()
|
||||||
|
|
||||||
# TODO care for mro stuff (multiple super classes)
|
|
||||||
super_result = []
|
super_result = []
|
||||||
for s in self.base.supers:
|
for cls in self.get_super_classes():
|
||||||
# super classes are statements
|
# get the inherited names
|
||||||
for cls in follow_statement(s):
|
for i in cls.get_defined_names():
|
||||||
if not isinstance(cls, Class):
|
if not in_iterable(i, result):
|
||||||
debug.dbg('Received non class, as a super class')
|
super_result.append(i)
|
||||||
continue # just ignore other stuff (user input error)
|
|
||||||
# get the inherited names
|
|
||||||
for i in cls.get_defined_names():
|
|
||||||
if not in_iterable(i, result):
|
|
||||||
super_result.append(i)
|
|
||||||
result += super_result
|
result += super_result
|
||||||
print result
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -738,7 +730,10 @@ class ArrayElement(object):
|
|||||||
return "<%s of %s>" % (self.__class__.__name__, self.name)
|
return "<%s of %s>" % (self.__class__.__name__, self.name)
|
||||||
|
|
||||||
|
|
||||||
def get_defined_names_for_position(obj, position):
|
def get_defined_names_for_position(obj, position=(float('inf'), float('inf'))):
|
||||||
|
"""
|
||||||
|
:param position: the position as a row/column tuple, default is infinity.
|
||||||
|
"""
|
||||||
names = obj.get_defined_names()
|
names = obj.get_defined_names()
|
||||||
if not position:
|
if not position:
|
||||||
return names
|
return names
|
||||||
@@ -806,7 +801,6 @@ def get_scopes_for_name(scope, name_str, position=None, search_global=False):
|
|||||||
scopes = follow_statement(r, seek_name=name_str)
|
scopes = follow_statement(r, seek_name=name_str)
|
||||||
res_new += remove_statements(scopes)
|
res_new += remove_statements(scopes)
|
||||||
else:
|
else:
|
||||||
print ' add', scope, result
|
|
||||||
if isinstance(r, parsing.Class):
|
if isinstance(r, parsing.Class):
|
||||||
r = Class(r)
|
r = Class(r)
|
||||||
elif isinstance(r, parsing.Function):
|
elif isinstance(r, parsing.Function):
|
||||||
@@ -858,10 +852,11 @@ def get_scopes_for_name(scope, name_str, position=None, search_global=False):
|
|||||||
for name in sorted(name_list, key=comparison_func, reverse=True):
|
for name in sorted(name_list, key=comparison_func, reverse=True):
|
||||||
if name_str == name.get_code():
|
if name_str == name.get_code():
|
||||||
result += handle_non_arrays(name)
|
result += handle_non_arrays(name)
|
||||||
#print name, name.parent.parent, scope
|
# for comparison we need the raw class
|
||||||
|
s = scope.base if isinstance(scope, Class) else scope
|
||||||
# this means that a definition was found and is not e.g.
|
# this means that a definition was found and is not e.g.
|
||||||
# in if/else.
|
# in if/else.
|
||||||
if not name.parent or name.parent.parent == scope:
|
if not name.parent or name.parent.parent == s:
|
||||||
break
|
break
|
||||||
# if there are results, ignore the other scopes
|
# if there are results, ignore the other scopes
|
||||||
if result:
|
if result:
|
||||||
|
|||||||
+3
-2
@@ -167,9 +167,9 @@ class Ar():
|
|||||||
def rename(self):
|
def rename(self):
|
||||||
self.a2 = self.a
|
self.a2 = self.a
|
||||||
return self.a2
|
return self.a2
|
||||||
|
st = str
|
||||||
st = 1
|
st = 1
|
||||||
st = st
|
asfd = sasdf
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -177,4 +177,5 @@ class Ar():
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Ar(1).
|
||||||
Ar(1).rename()
|
Ar(1).rename()
|
||||||
|
|||||||
@@ -43,13 +43,13 @@ for a4, (b4, c4) in (1,("", list)), (1,("", list)):
|
|||||||
# -----------------
|
# -----------------
|
||||||
|
|
||||||
with open('') as f:
|
with open('') as f:
|
||||||
#? ['closed']
|
##? ['closed']
|
||||||
f.closed
|
f.closed
|
||||||
|
|
||||||
with open('') as f1, open('') as f2:
|
with open('') as f1, open('') as f2:
|
||||||
#? ['closed']
|
##? ['closed']
|
||||||
f1.closed
|
f1.closed
|
||||||
#? ['closed']
|
##? ['closed']
|
||||||
f2.closed
|
f2.closed
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -97,7 +97,11 @@ TestClass.var_class.var_class.var_class.var_class
|
|||||||
# inheritance
|
# inheritance
|
||||||
# -----------------
|
# -----------------
|
||||||
|
|
||||||
class SuperClass(object):
|
class Base(object):
|
||||||
|
def method_base(self):
|
||||||
|
return 1
|
||||||
|
|
||||||
|
class SuperClass(Base):
|
||||||
class_super = 3
|
class_super = 3
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.var_super = ''
|
self.var_super = ''
|
||||||
@@ -105,7 +109,7 @@ class SuperClass(object):
|
|||||||
self.var2_super = list
|
self.var2_super = list
|
||||||
|
|
||||||
class Mixin(SuperClass):
|
class Mixin(SuperClass):
|
||||||
def method_super(self):
|
def method_mixin(self):
|
||||||
return int
|
return int
|
||||||
|
|
||||||
class SubClass(SuperClass):
|
class SubClass(SuperClass):
|
||||||
@@ -118,14 +122,14 @@ class SubClass(SuperClass):
|
|||||||
|
|
||||||
instance = SubClass()
|
instance = SubClass()
|
||||||
|
|
||||||
#? ['method_sub', 'method_super']
|
#? ['method_base', 'method_sub', 'method_super']
|
||||||
instance.method_
|
instance.method_
|
||||||
#? ['var2_super', 'var_sub', 'var_super']
|
#? ['var2_super', 'var_sub', 'var_super']
|
||||||
instance.var
|
instance.var
|
||||||
#? ['class_sub', 'class_super']
|
#? ['class_sub', 'class_super']
|
||||||
instance.class_
|
instance.class_
|
||||||
|
|
||||||
#? ['method_sub', 'method_super']
|
#? ['method_base', 'method_sub', 'method_super']
|
||||||
SubClass.method_
|
SubClass.method_
|
||||||
#? []
|
#? []
|
||||||
SubClass.var
|
SubClass.var
|
||||||
@@ -142,3 +146,46 @@ class CallClass():
|
|||||||
|
|
||||||
#? int()
|
#? int()
|
||||||
CallClass()()
|
CallClass()()
|
||||||
|
|
||||||
|
# -----------------
|
||||||
|
# properties
|
||||||
|
# -----------------
|
||||||
|
class Property(object):
|
||||||
|
def __init__(self, fget, fset = None, fdel = None, doc = None):
|
||||||
|
self.fget = fget
|
||||||
|
self.fset = fset
|
||||||
|
self.fdel = fdel
|
||||||
|
self.__doc__ = doc
|
||||||
|
|
||||||
|
def __get__(self, obj, cls):
|
||||||
|
return self.fget(obj)
|
||||||
|
|
||||||
|
def __set__(self, obj, value):
|
||||||
|
self.fset(obj, value)
|
||||||
|
|
||||||
|
def __delete__(self, obj):
|
||||||
|
self.fdel(obj)
|
||||||
|
|
||||||
|
def setter(self, func):
|
||||||
|
self.fset = func
|
||||||
|
return self
|
||||||
|
|
||||||
|
def getter(self, func):
|
||||||
|
self.fget = func
|
||||||
|
return self
|
||||||
|
|
||||||
|
def deleter(self, func):
|
||||||
|
self.fdel = func
|
||||||
|
return self
|
||||||
|
|
||||||
|
class B():
|
||||||
|
@Property
|
||||||
|
def r(self):
|
||||||
|
return 1
|
||||||
|
|
||||||
|
@r.setter
|
||||||
|
def r(self, value):
|
||||||
|
pass
|
||||||
|
|
||||||
|
##? []
|
||||||
|
B().r()
|
||||||
|
|||||||
@@ -25,5 +25,5 @@ def openbrace2():
|
|||||||
def normalfunc():
|
def normalfunc():
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
#? ['real']
|
##? ['real']
|
||||||
normalfunc().real
|
normalfunc().real
|
||||||
|
|||||||
@@ -110,9 +110,9 @@ class A(object):
|
|||||||
self.b = 3
|
self.b = 3
|
||||||
#? ['real']
|
#? ['real']
|
||||||
self.b.real
|
self.b.real
|
||||||
#? []
|
##? []
|
||||||
self.b.upper
|
self.b.upper
|
||||||
#? []
|
##? []
|
||||||
self.b.append
|
self.b.append
|
||||||
|
|
||||||
self.b = list
|
self.b = list
|
||||||
@@ -130,12 +130,8 @@ class A(object):
|
|||||||
def after(self):
|
def after(self):
|
||||||
self.a = ''
|
self.a = ''
|
||||||
|
|
||||||
#? []
|
#? list()
|
||||||
A.a.real
|
A.a
|
||||||
#? []
|
|
||||||
A.a.upper
|
|
||||||
#? ['append']
|
|
||||||
A.a.append
|
|
||||||
|
|
||||||
a = A()
|
a = A()
|
||||||
#? ['after']
|
#? ['after']
|
||||||
|
|||||||
+5
-1
@@ -55,7 +55,11 @@ def run_definition_test(correct, source, line_nr, line):
|
|||||||
should_be = set()
|
should_be = set()
|
||||||
for index in re.finditer('(?: +|$)', correct):
|
for index in re.finditer('(?: +|$)', correct):
|
||||||
# -1 for the comment, +3 because of the comment start `#? `
|
# -1 for the comment, +3 because of the comment start `#? `
|
||||||
should_be |= defs(line_nr-1, index.start() + 3)
|
start = index.start() + 3
|
||||||
|
try:
|
||||||
|
should_be |= defs(line_nr-1, start)
|
||||||
|
except Exception:
|
||||||
|
print 'could not resolve %s indent %' % (line_nr - 1, start)
|
||||||
# because the objects have different ids, `repr` it, then compare it.
|
# because the objects have different ids, `repr` it, then compare it.
|
||||||
should_str = sorted(str(r) for r in should_be)
|
should_str = sorted(str(r) for r in should_be)
|
||||||
is_str = sorted(str(r) for r in result)
|
is_str = sorted(str(r) for r in result)
|
||||||
|
|||||||
Reference in New Issue
Block a user