def visit_cursor(path, cursor): # Skip symbols from other files. if cursor.location.file is None or cursor.location.file.name != path: return None kind = cursor.kind.name if kind not in ALL_KINDS: return None # Names of function parameters. params = None # Names of template parameters. tparams = None children = None name = cursor.spelling # Display types for variables and typedefs. cursor_type = cursor.type.spelling if kind in VAR_KINDS else None if kind in FUNCTION_KINDS: # We can't use displayname as it also includes the arguments. params = [] tparams = [] for child in cursor.get_children(): if child.kind == CursorKind.PARM_DECL: # Use the param name, but fall back to the raw type if unnamed. params.append(child.spelling or child.type.spelling) elif child.kind == CursorKind.TEMPLATE_TYPE_PARAMETER: tparams.append(child.spelling) # TODO(hansonw): non-type and "template template" params? if kind in MEMBER_KINDS: # Name should be fully qualified if outside the parent. if cursor.semantic_parent != cursor.lexical_parent: name = cursor.semantic_parent.spelling + "::" + name elif kind in CLASS_KINDS: # Include template information. name = cursor.displayname children = [] for child in cursor.get_children(): child_outline = visit_cursor(path, child) if child_outline is not None: children.append(child_outline) ret = { "name": name, "cursor_kind": kind, "cursor_type": cursor_type, "extent": range_dict_relative(cursor.extent), "params": params, "tparams": tparams, "children": children, } return {k: v for k, v in ret.items() if v is not None}
def visit_cursor(path, cursor): # Skip symbols from other files. if cursor.location.file is None or cursor.location.file.name != path: return None kind = cursor.kind.name if kind not in ALL_KINDS: return None # Names of function parameters. params = None # Names of template parameters. tparams = None children = None name = cursor.spelling # Display types for variables and typedefs. cursor_type = cursor.type.spelling if kind in VAR_KINDS else None if kind in FUNCTION_KINDS: # We can't use displayname as it also includes the arguments. params = [] tparams = [] for child in cursor.get_children(): if child.kind == CursorKind.PARM_DECL: # Use the param name, but fall back to the raw type if unnamed. params.append(child.spelling or child.type.spelling) elif child.kind == CursorKind.TEMPLATE_TYPE_PARAMETER: tparams.append(child.spelling) # TODO(hansonw): non-type and "template template" params? if kind in MEMBER_KINDS: # Name should be fully qualified if outside the parent. if cursor.semantic_parent != cursor.lexical_parent: name = cursor.semantic_parent.spelling + '::' + name elif kind in CLASS_KINDS: # Include template information. name = cursor.displayname children = [] for child in cursor.get_children(): child_outline = visit_cursor(path, child) if child_outline is not None: children.append(child_outline) ret = { 'name': name, 'cursor_kind': kind, 'cursor_type': cursor_type, 'extent': range_dict_relative(cursor.extent), 'params': params, 'tparams': tparams, 'children': children, } return {k: v for k, v in ret.items() if v is not None}
def get_declaration_info_for_cursor(self, cursor): '''Returns string id in clang-callgraph-service format for entity under the cursor. Currently works only for definitions of class methods, instance methods and functions. Returns None for everything else. ''' result = [] while cursor is not None and not cursor.kind.is_translation_unit(): file = cursor.location.file result.append({ 'name': self.get_name_for_cursor(cursor), 'type': cursor.kind.name, 'cursor_usr': cursor.get_usr(), 'file': resolve_file(file), 'extent': range_dict_relative(cursor.extent), }) cursor = cursor.semantic_parent return result
def visit_cursor(libclang, cursor): kind = cursor.kind.name if kind not in ALL_KINDS: return None # Skip symbols from other files. if not libclang.clang_Location_isFromMainFile(cursor.location): return None # Names of function parameters. params = None # Names of template parameters. tparams = None children = None name = cursor.spelling # Display types for variables and typedefs. cursor_type = cursor.type.spelling if kind in VAR_KINDS else None if kind in FUNCTION_KINDS: # We can't use displayname as it also includes the arguments. params = [] tparams = [] for child in cursor.get_children(): if child.kind == CursorKind.PARM_DECL: # Use the param name, but fall back to the raw type if unnamed. params.append(child.spelling or child.type.spelling) elif child.kind == CursorKind.TEMPLATE_TYPE_PARAMETER: tparams.append(child.spelling) # TODO(hansonw): non-type and "template template" params? if kind in MEMBER_KINDS: # Name should be fully qualified if outside the parent. if cursor.semantic_parent != cursor.lexical_parent: name = cursor.semantic_parent.spelling + '::' + name elif kind in CLASS_KINDS: # Include template information. name = cursor.displayname children = [] for child in cursor.get_children(): child_outline = visit_cursor(libclang, child) if child_outline is not None: children.append(child_outline) if kind == MACRO_INSTANTIATION: params = [] if name in GTEST_MACROS: # Should look like TEST(id, id). tokens = list(itertools.islice(cursor.get_tokens(), 1, 6)) if len(tokens) == 5 and ( tokens[0].kind == TokenKind.PUNCTUATION and tokens[1].kind == TokenKind.IDENTIFIER and tokens[2].kind == TokenKind.PUNCTUATION and tokens[3].kind == TokenKind.IDENTIFIER and tokens[4].kind == TokenKind.PUNCTUATION ): params = [tokens[1].spelling, tokens[3].spelling] else: return None else: # TODO(hansonw): Handle other special macros like DEFINE_ params. return None ret = { 'name': name, 'cursor_kind': kind, 'cursor_type': cursor_type, 'extent': range_dict_relative(cursor.extent), 'params': params, 'tparams': tparams, 'children': children, } return {k: v for k, v in ret.items() if v is not None}
def visit_cursor(libclang, cursor): kind = cursor.kind.name if kind not in ALL_KINDS: return None # Skip symbols from other files. if not libclang.clang_Location_isFromMainFile(cursor.location): return None # Names of function parameters. params = None # Names of template parameters. tparams = None children = None name = cursor.spelling # Display types for variables and typedefs. cursor_type = cursor.type.spelling if kind in VAR_KINDS else None if kind in FUNCTION_KINDS: # We can't use displayname as it also includes the arguments. params = [] tparams = [] for child in cursor.get_children(): if child.kind == CursorKind.PARM_DECL: # Use the param name, but fall back to the raw type if unnamed. params.append(child.spelling or child.type.spelling) elif child.kind == CursorKind.TEMPLATE_TYPE_PARAMETER: tparams.append(child.spelling) # TODO(hansonw): non-type and "template template" params? if kind in MEMBER_KINDS: # Name should be fully qualified if outside the parent. if cursor.semantic_parent != cursor.lexical_parent: name = cursor.semantic_parent.spelling + '::' + name elif kind in CLASS_KINDS: # Include template information. name = cursor.displayname children = [] for child in cursor.get_children(): child_outline = visit_cursor(libclang, child) if child_outline is not None: children.append(child_outline) if kind == MACRO_INSTANTIATION: params = [] if name in GTEST_MACROS: # Should look like TEST(id, id). tokens = list(itertools.islice(cursor.get_tokens(), 1, 6)) if len(tokens) == 5 and ( tokens[0].kind == TokenKind.PUNCTUATION and tokens[1].kind == TokenKind.IDENTIFIER and tokens[2].kind == TokenKind.PUNCTUATION and tokens[3].kind == TokenKind.IDENTIFIER and tokens[4].kind == TokenKind.PUNCTUATION): params = [tokens[1].spelling, tokens[3].spelling] else: return None else: # TODO(hansonw): Handle other special macros like DEFINE_ params. return None ret = { 'name': name, 'cursor_kind': kind, 'cursor_type': cursor_type, 'extent': range_dict_relative(cursor.extent), 'params': params, 'tparams': tparams, 'children': children, } return {k: v for k, v in ret.items() if v is not None}
def visitor(_context, cursor, source_range): references.append(range_dict_relative(source_range)) return 1 # continue
def visitor(_context, cursor, source_range): range_dict = range_dict_relative(source_range) # The end location is non-inclusive. range_dict['end']['column'] -= 1 references.append(range_dict) return 1 # continue
def get_declaration_location_and_spelling(translation_unit, contents, flags, absolute_path, line, column): def log(s): logger.info('%s:%d:%d - %s', os.path.basename(absolute_path), line, column, s) source_location = translation_unit.get_location( absolute_path, (line, column)) cursor = Cursor.from_location(translation_unit, source_location) if cursor is None: log('No cursor') return None # Don't allow clicks/tooltips on most declarations, as their content is usually obvious. # Make an exception for variable declarations, as these can often have auto types. if cursor.kind != CursorKind.VAR_DECL and cursor.kind.is_declaration(): log('Ignoring declaration') return None referenced = cursor.referenced if referenced is None or referenced.location is None or referenced.location.file is None: # If cursor is over an include statement, attempt to resolve the location # of the included file. line_text = get_line(contents, line) bounds = get_include_path_extent(line_text) if bounds is not None: start_col, end_col = bounds # Don't allow hyperclick if cursor is not over the include name, i.e.: # #include "header.h" # ^^^^^^^^ if column < start_col or column > end_col: return None filename = resolve_include(absolute_path, line_text, flags) if filename is None: return None # Point location to beginning of the found included file (line 0, column 0) location = { 'file': filename, 'point': { 'row': 0, 'column': 0, }, # Show destination file of hyperclick in hover popover 'type': filename, 'spelling': None, 'extent': { 'start': {'row': line - 1, 'column': start_col}, 'end': {'row': line - 1, 'column': end_col} } } return location else: log('No referenced information') return None loc = referenced.location log('Returning {0}:{1}:{2}'.format( os.path.basename(loc.file.name), loc.line, loc.column)) # An extent has a `start` and `end` property, each of which have a `line` # and `column` property. extent = cursor.extent type = None try: type = cursor.type and cursor.type.spelling except: logger.warn('Was not able to get cursor type') pass location = location_dict(loc) location['spelling'] = cursor.spelling location['type'] = type location['extent'] = range_dict_relative(extent) return location
def get_declaration_location_and_spelling(translation_unit, contents, flags, absolute_path, line, column): def log(s): logger.info('%s:%d:%d - %s', os.path.basename(absolute_path), line, column, s) source_location = translation_unit.get_location(absolute_path, (line, column)) cursor = Cursor.from_location(translation_unit, source_location) if cursor is None: log('No cursor') return None # Don't allow clicks/tooltips on most declarations, as their content is usually obvious. # Make an exception for variable declarations, as these can often have auto types. if cursor.kind != CursorKind.VAR_DECL and cursor.kind.is_declaration(): log('Ignoring declaration') return None referenced = cursor.referenced if referenced is None or referenced.location is None or referenced.location.file is None: # If cursor is over an include statement, attempt to resolve the location # of the included file. line_text = get_line(contents, line) bounds = get_include_path_extent(line_text) if bounds is not None: start_col, end_col = bounds # Don't allow hyperclick if cursor is not over the include name, i.e.: # #include "header.h" # ^^^^^^^^ if column < start_col or column > end_col: return None filename = resolve_include(absolute_path, line_text, flags) if filename is None: return None # Point location to beginning of the found included file (line 0, column 0) location = { 'file': filename, 'point': { 'row': 0, 'column': 0, }, # Show destination file of hyperclick in hover popover 'type': filename, 'spelling': None, 'extent': { 'start': { 'row': line - 1, 'column': start_col }, 'end': { 'row': line - 1, 'column': end_col } } } return location else: log('No referenced information') return None loc = referenced.location log('Returning {0}:{1}:{2}'.format(os.path.basename(loc.file.name), loc.line, loc.column)) # An extent has a `start` and `end` property, each of which have a `line` # and `column` property. extent = cursor.extent type = None try: type = cursor.type and cursor.type.spelling except: logger.warn('Was not able to get cursor type') pass location = location_dict(loc) location['spelling'] = cursor.spelling location['type'] = type location['extent'] = range_dict_relative(extent) return location