def get_extended_class(start_line=None): # Figure out if we're in an inner class and return its extended type if so. if not start_line: start_line = util.get_cursor_line_num() start_indent = util.get_indent(start_line) if start_indent > 0: for decl in iter_decls(start_line, -1, FUNC_DECLS | CLASS_DECLS): indent = util.get_indent(decl.line) if indent == start_indent: continue decl_type = type(decl) if decl_type is FuncDecl: start_indent = indent elif decl_type is ClassDecl: if decl.extends: return decl.extends else: return None if indent == 0: break # Search for 'extends' at the top of the file. for lnum in range(1, util.get_line_count()): line = util.get_line(lnum) m = re.match("extends\s+(\w+)", line) if m: return m.group(1) # Only 'tool' can appear before 'extends', so stop searching if any other # text is encountered. elif not re.match("tool\s+$", line): return None
def _iter_decls_down(start_line, flags): # Check whether the starting line is a class decl. # If so, the indent of the next line is used as a baseline to determine # which items are direct children of the inner class. in_class = False class_decl = _get_decl(start_line, CLASS_DECLS) if class_decl: in_class = True class_indent = util.get_indent(start_line) inner_indent = None if flags & CLASS_DECLS: yield class_decl for lnum in range(start_line + 1, util.get_line_count()): if not util.get_line(lnum): continue indent = util.get_indent(lnum) if in_class: if indent <= class_indent: return if not inner_indent: inner_indent = indent elif indent > inner_indent: continue else: if indent > 0: continue decl = _get_decl(lnum, flags) if decl: yield decl
def _iter_decls_up(start_line, flags): # Remove consts and enums from flags, since they can't exist inside functions. flags &= ~CONST_DECLS flags &= ~ENUM_DECLS # Gather decls, but don't yield them until we're sure that the start line # was inside a function. If it wasn't, only the class decl is yielded, or # nothing if the start line wasn't inside an inner class either. decls = [] start_indent = util.get_indent(start_line) if start_indent == 0: return # Upon reaching a func decl, the search continues until a class decl is found. # This only happens if the func decl is indented. found_func = False for lnum in range(start_line - 1, 0, -1): indent = util.get_indent(lnum) if indent > start_indent: continue if found_func: # After finding a function, we only care finding the inner class. decl = _get_decl(lnum, CLASS_DECLS) else: # We need to know when a func or class is encountered, even if they # aren't part of the search flags. Funcs and classes are still only # yielded if part of the original search flags. decl = _get_decl(lnum, flags | FUNC_DECLS | CLASS_DECLS) if not decl: continue if indent < start_indent: decl_type = type(decl) if decl_type is FuncDecl: found_func = True start_indent = indent if flags & VAR_DECLS: # Yield function args if len(decl.args) > 0: mapped_args = _args_to_vars(decl) for arg in mapped_args: yield arg # Yield var decls gathered up until now. for stored_decl in reversed(decls): yield stored_decl if flags & FUNC_DECLS: yield decl if indent == 0: break elif decl_type is ClassDecl: if flags & CLASS_DECLS: yield decl break else: decls.append(decl)