def usages_add_import_modules(definitions, search_name): """ Adds the modules of the imports """ new = set() for d in definitions: if isinstance(d.parent, pr.Import): s = imports.ImportPath(d.parent, direct_resolve=True) with common.ignored(IndexError): new.add(s.follow(is_goto=True)[0]) return set(definitions) | new
def related_name_add_import_modules(definitions, search_name): """ Adds the modules of the imports """ new = set() for d in definitions: if isinstance(d.parent, parsing.Import): s = imports.ImportPath(d.parent, direct_resolve=True) try: new.add(s.follow(is_goto=True)[0]) except IndexError: pass return set(definitions) | new
def follow_inexistent_imports(defs): """ Imports can be generated, e.g. following `multiprocessing.dummy` generates an import dummy in the multiprocessing module. The Import doesn't exist -> follow. """ definitions = set(defs) for d in defs: if isinstance(d.parent, pr.Import) \ and d.start_pos == (0, 0): i = imports.ImportPath(d.parent).follow(is_goto=True) definitions.remove(d) definitions |= follow_inexistent_imports(i) return definitions
def follow_imports_if_possible(name): # TODO remove this, or move to another place (not used) par = name.parent if isinstance(par, parsing.Import) and not \ isinstance(self.parser.user_stmt, parsing.Import): new = imports.ImportPath(par).follow(is_goto=True) # Only remove the old entry if a new one has been found. #print par, new, par.parent if new: try: return new except AttributeError: # .name undefined pass return [name]
def _get_on_import_stmt(self, is_like_search=False): """ Resolve the user statement, if it is an import. Only resolve the parts until the user position. """ user_stmt = self._parser.user_stmt import_names = user_stmt.get_all_import_names() kill_count = -1 cur_name_part = None for i in import_names: if user_stmt.alias == i: continue for name_part in i.names: if name_part.end_pos >= self.pos: if not cur_name_part: cur_name_part = name_part kill_count += 1 i = imports.ImportPath(user_stmt, is_like_search, kill_count=kill_count, direct_resolve=True) return i, cur_name_part
def _get_on_import_stmt(self, user_stmt, is_like_search=False): """ Resolve the user statement, if it is an import. Only resolve the parts until the user position. """ import_names = user_stmt.get_all_import_names() kill_count = -1 cur_name_part = None for i in import_names: if user_stmt.alias == i: continue for name_part in i.names: if name_part.end_pos >= self._pos: if not cur_name_part: cur_name_part = name_part kill_count += 1 context = self._module.get_context() just_from = next(context) == 'from' i = imports.ImportPath(user_stmt, is_like_search, kill_count=kill_count, direct_resolve=True, is_just_from=just_from) return i, cur_name_part
def related_names(definitions, search_name, mods): def check_call(call): result = [] follow = [] # There might be multiple search_name's in one call_path call_path = list(call.generate_call_path()) for i, name in enumerate(call_path): # name is `parsing.NamePart`. if name == search_name: follow.append(call_path[:i + 1]) for f in follow: follow_res, search = evaluate.goto(call.parent_stmt, f) follow_res = related_name_add_import_modules(follow_res, search) #print follow_res, [d.parent for d in follow_res] # compare to see if they match if any(r in definitions for r in follow_res): scope = call.parent_stmt result.append(api_classes.RelatedName(search, scope)) return result if not definitions: return set() def is_definition(arr): try: for a in arr: assert len(a) == 1 a = a[0] if a.isinstance(parsing.Array): assert is_definition(a) elif a.isinstance(parsing.Call): assert a.execution is None return True except AssertionError: return False mods |= set([d.get_parent_until() for d in definitions]) names = [] for m in get_directory_modules_for_name(mods, search_name): try: stmts = m.used_names[search_name] except KeyError: continue for stmt in stmts: if isinstance(stmt, parsing.Import): count = 0 imps = [] for i in stmt.get_all_import_names(): for name_part in i.names: count += 1 if name_part == search_name: imps.append((count, name_part)) for used_count, name_part in imps: i = imports.ImportPath(stmt, kill_count=count - used_count, direct_resolve=True) f = i.follow(is_goto=True) if set(f) & set(definitions): names.append(api_classes.RelatedName(name_part, stmt)) else: calls = _scan_array(stmt.get_assignment_calls(), search_name) for d in stmt.assignment_details: if not is_definition(d[1]): calls += _scan_array(d[1], search_name) for call in calls: names += check_call(call) return names
def usages(definitions, search_name, mods): def compare_array(definitions): """ `definitions` are being compared by module/start_pos, because sometimes the id's of the objects change (e.g. executions). """ result = [] for d in definitions: module = d.get_parent_until() result.append((module, d.start_pos)) return result def check_call(call): result = [] follow = [] # There might be multiple search_name's in one call_path call_path = list(call.generate_call_path()) for i, name in enumerate(call_path): # name is `pr.NamePart`. if name == search_name: follow.append(call_path[:i + 1]) for f in follow: follow_res, search = evaluate.goto(call.parent, f) follow_res = usages_add_import_modules(follow_res, search) compare_follow_res = compare_array(follow_res) # compare to see if they match if any(r in compare_definitions for r in compare_follow_res): scope = call.parent result.append(api_classes.Usage(search, scope)) return result if not definitions: return set() compare_definitions = compare_array(definitions) mods |= set([d.get_parent_until() for d in definitions]) names = [] for m in get_directory_modules_for_name(mods, search_name): try: stmts = m.used_names[search_name] except KeyError: continue for stmt in stmts: if isinstance(stmt, pr.Import): count = 0 imps = [] for i in stmt.get_all_import_names(): for name_part in i.names: count += 1 if name_part == search_name: imps.append((count, name_part)) for used_count, name_part in imps: i = imports.ImportPath(stmt, kill_count=count - used_count, direct_resolve=True) f = i.follow(is_goto=True) if set(f) & set(definitions): names.append(api_classes.Usage(name_part, stmt)) else: for call in _scan_statement(stmt, search_name, assignment_details=True): names += check_call(call) return names