def call_signatures(self): """ Return the function object of the call you're currently in. E.g. if the cursor is here:: abs(# <-- cursor is here This would return the ``abs`` function. On the other hand:: abs()# <-- cursor is here This would return ``None``. :rtype: list of :class:`api_classes.CallDef` """ call, index = self._func_call_and_param_index() if call is None: return [] user_stmt = self._user_stmt() with common.scale_speed_settings(settings.scale_call_signatures): _callable = lambda: evaluate.follow_call(call) origins = cache.cache_call_signatures(_callable, user_stmt) debug.speed('func_call followed') return [ api_classes.CallDef(o, index, call) for o in origins if o.isinstance(er.Function, er.Instance, er.Class) ]
def function_definition(self): """ Return the function object of the call you're currently in. E.g. if the cursor is here:: abs(# <-- cursor is here This would return the ``abs`` function. On the other hand:: abs()# <-- cursor is here This would return ``None``. :rtype: :class:`api_classes.CallDef` """ (call, index) = self._func_call_and_param_index() if call is None: return None user_stmt = self._parser.user_stmt with common.scale_speed_settings(settings.scale_function_definition): _callable = lambda: evaluate.follow_call(call) origins = cache.cache_function_definition(_callable, user_stmt) debug.speed('func_call followed') if len(origins) == 0: return None # just take entry zero, because we need just one. executable = origins[0] return api_classes.CallDef(executable, index, call)
def check_statement_information(stmt, search_name): try: ass = stmt.get_assignment_calls() try: call = ass.get_only_subelement() except AttributeError: assert False assert type(call) == parsing.Call and str(call.name) == 'isinstance' assert bool(call.execution) # isinstance check isinst = call.execution.values assert len(isinst) == 2 # has two params assert len(isinst[0]) == 1 assert len(isinst[1]) == 1 assert isinstance(isinst[0][0], parsing.Call) # names fit? assert str(isinst[0][0].name) == search_name classes_call = isinst[1][0] # class_or_type_or_tuple assert isinstance(classes_call, parsing.Call) result = [] for c in evaluate.follow_call(classes_call): if isinstance(c, evaluate.Array): result += c.get_index_types() else: result.append(c) for i, c in enumerate(result): result[i] = evaluate.Instance(c) return result except AssertionError: return []
def call_signatures(self): """ Return the function object of the call you're currently in. E.g. if the cursor is here:: abs(# <-- cursor is here This would return the ``abs`` function. On the other hand:: abs()# <-- cursor is here This would return ``None``. :rtype: list of :class:`api_classes.CallDef` """ call, index = self._func_call_and_param_index() if call is None: return [] user_stmt = self._user_stmt() with common.scale_speed_settings(settings.scale_call_signatures): _callable = lambda: evaluate.follow_call(call) origins = cache.cache_call_signatures(_callable, user_stmt) debug.speed('func_call followed') return [api_classes.CallDef(o, index, call) for o in origins if o.isinstance(er.Function, er.Instance, er.Class)]
def _check_isinstance_type(stmt, search_name): try: commands = stmt.get_commands() # this might be removed if we analyze and, etc assert len(commands) == 1 call = commands[0] assert type(call) is pr.Call and str(call.name) == "isinstance" assert bool(call.execution) # isinstance check isinst = call.execution.values assert len(isinst) == 2 # has two params obj, classes = [statement.get_commands() for statement in isinst] assert len(obj) == 1 assert len(classes) == 1 assert isinstance(obj[0], pr.Call) # names fit? assert str(obj[0].name) == search_name assert isinstance(classes[0], pr.Call) # can be type or tuple except AssertionError: return [] result = [] for c in evaluate.follow_call(classes[0]): if isinstance(c, er.Array): result += c.get_index_types() else: result.append(c) for i, c in enumerate(result): result[i] = er.Instance(c) return result
def check_statement_information(stmt, search_name): try: commands = stmt.get_commands() # this might be removed if we analyze and, etc assert len(commands) == 1 call = commands[0] assert type(call) == pr.Call and str(call.name) == 'isinstance' assert bool(call.execution) # isinstance check isinst = call.execution.values assert len(isinst) == 2 # has two params obj, classes = [statement.get_commands() for statement in isinst] assert len(obj) == 1 assert len(classes) == 1 assert isinstance(obj[0], pr.Call) # names fit? assert str(obj[0].name) == search_name assert isinstance(classes[0], pr.Call) # can be type or tuple except AssertionError: return [] result = [] for c in evaluate.follow_call(classes[0]): if isinstance(c, er.Array): result += c.get_index_types() else: result.append(c) for i, c in enumerate(result): result[i] = er.Instance(c) return result
def get_in_function_call(self): """ Return the function, that the cursor is in, e.g.: >>> isinstance(| # | <-- cursor is here This would return the `isinstance` function. In contrary: >>> isinstance()| # | <-- cursor is here This would return `None`. """ def check_user_stmt(user_stmt): if user_stmt is None \ or not isinstance(user_stmt, parsing.Statement): return None, 0 ass = helpers.fast_parent_copy(user_stmt.get_assignment_calls()) call, index, stop = helpers.scan_array_for_pos(ass, self.pos) return call, index def check_cache(): """ Do the parsing with a part parser, therefore reduce ressource costs. TODO this is not working with multi-line docstrings, improve. """ if self.source_path is None: return None, 0 try: timestamp, parser = builtin.CachedModule.cache[ self.source_path] except KeyError: return None, 0 part_parser = self.module.get_part_parser() user_stmt = part_parser.user_stmt call, index = check_user_stmt(user_stmt) if call: old_stmt = parser.module.get_statement_for_position(self.pos) if old_stmt is None: return None, 0 old_call, old_index = check_user_stmt(old_stmt) if old_call: # compare repr because that should definitely be the same. # Otherwise the whole thing is out of sync. if repr(old_call) == repr(call): # return the index of the part_parser return old_call, index return None, 0 else: raise NotFoundError() debug.speed('func_call start') try: call, index = check_cache() except NotFoundError: return None debug.speed('func_call parsed') if call is None: # This is a backup, if the above is not successful. user_stmt = self.parser.user_stmt call, index = check_user_stmt(user_stmt) if call is None: return None debug.speed('func_call user_stmt') with common.scale_speed_settings(settings.scale_get_in_function_call): origins = evaluate.follow_call(call) debug.speed('func_call followed') if len(origins) == 0: return None # just take entry zero, because we need just one. executable = origins[0] return api_classes.CallDef(executable, index, call)
def get_in_function_call(self): """ Return the function, that the cursor is in, e.g.: >>> isinstance(| # | <-- cursor is here This would return the `isinstance` function. In contrary: >>> isinstance()| # | <-- cursor is here This would return `None`. """ def scan_array_for_pos(arr, pos): """ Returns the function Call that match search_name in an Array. """ index = 0 call = None stop = False for index, sub in enumerate(arr.values): call = None for s in sub: if isinstance(s, parsing.Array): new = scan_array_for_pos(s, pos) if new[0] is not None: call, index, stop = new if stop: return call, index, stop elif isinstance(s, parsing.Call): start_s = s while s is not None: if s.start_pos >= pos: return call, index, stop elif s.execution is not None: end = s.execution.end_pos if s.execution.start_pos < pos and \ (end is None or pos < end): c, index, stop = scan_array_for_pos( s.execution, pos) if stop: return c, index, stop # call should return without execution and # next reset = c or s if reset.execution.type not in \ [parsing.Array.TUPLE, parsing.Array.NOARRAY]: return start_s, index, False reset.execution = None reset.next = None return c or start_s, index, True s = s.next # The third return is just necessary for recursion inside, because # it needs to know when to stop iterating. return call, index, stop user_stmt = self.parser.user_stmt if user_stmt is None or not isinstance(user_stmt, parsing.Statement): return None ass = helpers.fast_parent_copy(user_stmt.get_assignment_calls()) call, index, stop = scan_array_for_pos(ass, self.pos) if call is None: return None origins = evaluate.follow_call(call) if len(origins) == 0: return None # just take entry zero, because we need just one. executable = origins[0] after = self.module.get_line(self.pos[0])[self.pos[1]:] index -= re.search('^[ ,]*', after).group(0).count(',') return CallDef(executable, index, call)
def get_in_function_call(self): """ Return the function, that the cursor is in, e.g.: >>> isinstance(| # | <-- cursor is here This would return the `isinstance` function. In contrary: >>> isinstance()| # | <-- cursor is here This would return `None`. """ def check_user_stmt(user_stmt): if user_stmt is None \ or not isinstance(user_stmt, parsing.Statement): return None, 0 ass = helpers.fast_parent_copy(user_stmt.get_assignment_calls()) call, index, stop = helpers.scan_array_for_pos(ass, self.pos) return call, index def check_cache(): """ Do the parsing with a part parser, therefore reduce ressource costs. TODO this is not working with multi-line docstrings, improve. """ if self.source_path is None: return None, 0 try: timestamp, parser = builtin.CachedModule.cache[ self.source_path] except KeyError: return None, 0 part_parser = self.module.get_part_parser() user_stmt = part_parser.user_stmt call, index = check_user_stmt(user_stmt) if call: old_stmt = parser.module.get_statement_for_position(self.pos) if old_stmt is None: return None, 0 old_call, old_index = check_user_stmt(old_stmt) if old_call: # compare repr because that should definitely be the same. # Otherwise the whole thing is out of sync. if repr(old_call) == repr(call): # return the index of the part_parser return old_call, index return None, 0 else: raise NotFoundError() debug.speed('func_call start') try: call, index = check_cache() except NotFoundError: return None debug.speed('func_call parsed') if call is None: # This is a backup, if the above is not successful. user_stmt = self.parser.user_stmt call, index = check_user_stmt(user_stmt) if call is None: return None debug.speed('func_call user_stmt') with helpers.scale_speed_settings(settings.scale_get_in_function_call): origins = evaluate.follow_call(call) debug.speed('func_call followed') if len(origins) == 0: return None # just take entry zero, because we need just one. executable = origins[0] return api_classes.CallDef(executable, index, call)
def get_in_function_call(self): """ Return the function object of the call you're currently in. E.g. if the cursor is here:: >>> abs(# <-- cursor is here This would return the ``abs`` function. On the other hand:: >>> abs()# <-- cursor is here This would return ``None``. :rtype: :class:`api_classes.CallDef` """ def check_user_stmt(user_stmt): if user_stmt is None \ or not isinstance(user_stmt, parsing.Statement): return None, 0 ass = helpers.fast_parent_copy(user_stmt.get_assignment_calls()) call, index, stop = helpers.search_function_call(ass, self.pos) return call, index def check_cache(): """ Do the parsing with a part parser, therefore reduce ressource costs. TODO this is not working with multi-line docstrings, improve. """ if self.source_path is None: return None, 0 try: parser = cache.parser_cache[self.source_path].parser except KeyError: return None, 0 part_parser = self._module.get_part_parser() user_stmt = part_parser.user_stmt call, index = check_user_stmt(user_stmt) if call: old_stmt = parser.module.get_statement_for_position(self.pos) if old_stmt is None: return None, 0 old_call, old_index = check_user_stmt(old_stmt) if old_call: # compare repr because that should definitely be the same. # Otherwise the whole thing is out of sync. if repr(old_call) == repr(call): # return the index of the part_parser return old_call, index return None, 0 else: raise NotFoundError() debug.speed('func_call start') call = None if settings.use_get_in_function_call_cache: try: call, index = check_cache() except NotFoundError: return None user_stmt = self._parser.user_stmt if call is None: # This is a backup, if the above is not successful. call, index = check_user_stmt(user_stmt) if call is None: return None debug.speed('func_call parsed') with common.scale_speed_settings(settings.scale_get_in_function_call): _callable = lambda: evaluate.follow_call(call) origins = cache.cache_get_in_function_call(_callable, user_stmt) debug.speed('func_call followed') if len(origins) == 0: return None # just take entry zero, because we need just one. executable = origins[0] return api_classes.CallDef(executable, index, call)