def _get_vectors_for_cursor(self, cursor, filename): """ Maps all functions in/under the given cursor to their count vectors if they are defined in the given file. :param cursor: The cursor to traverse. :param filename: Absolute path to the file. :return: The dictionary holding CountVectors for all variables in all functions. """ assert isinstance(cursor, Cursor) file = cursor.location.file if file is not None: file = file.name if str(file) == str(filename) and is_function_declaration(cursor): self._get_vector_for_function(cursor) result = {(cursor.extent.start.line, get_identifier_name(cursor)): self.count_vectors} # Reset local states self.count_vectors = {} self.stack = [] else: result = {} for child in cursor.get_children(): result.update(self._get_vectors_for_cursor(child, filename)) return result
def _get_vector_for_function(self, cursor, child_num=0): """ Creates a CountVector object for the given cursor. Note: this function uses self.count_vectors for storing its results. This is done knowingly because passing back and forth mutable objects is not nice and yields in bigger complexity IMHO. This function creates a CountVector object for all variables found in self.local_vars and in the tree elements below the given one, stores it in self.count_vectors. :param cursor: Clang cursor to iterate over. """ assert isinstance(cursor, Cursor) self.stack.append((cursor, child_num)) if is_reference(cursor): self.count_identifier(get_identifier_name(cursor)) if is_literal(cursor): tokens = list(cursor.get_tokens()) if tokens: # Mangle constants with $ (-> no valid C identifier), first # token is the constant, semicolon and similar things may # follow, don't want them self.count_identifier("#" + tokens[0].spelling) for i, child in enumerate(cursor.get_children()): self._get_vector_for_function(child, i) self.stack.pop()
def _get_vector_for_function(self, cursor, child_num=0): """ Creates a CountVector object for the given cursor. Note: this function uses self.count_vectors for storing its results. This is done knowingly because passing back and forth mutable objects is not nice and yields in bigger complexity IMHO. This function creates a CountVector object for all variables found in self.local_vars and in the tree elements below the given one, stores it in self.count_vectors. :param cursor: Clang cursor to iterate over. """ assert isinstance(cursor, Cursor) self.stack.append((cursor, child_num)) if is_reference(cursor): self.count_identifier(get_identifier_name(cursor), CountVector.Category.reference) if is_literal(cursor): tokens = list(cursor.get_tokens()) if tokens: self.count_identifier(tokens[0].spelling, CountVector.Category.literal) for i, child in enumerate(cursor.get_children()): self._get_vector_for_function(child, i) self.stack.pop()