1#!/usr/bin/env python 2 3# ===- cindex-dump.py - cindex/Python Source Dump -------------*- python -*--===# 4# 5# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 6# See https://llvm.org/LICENSE.txt for license information. 7# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 8# 9# ===------------------------------------------------------------------------===# 10 11""" 12A simple command line tool for dumping a source file using the Clang Index 13Library. 14""" 15 16 17def get_diag_info(diag): 18 return { 19 "severity": diag.severity, 20 "location": diag.location, 21 "spelling": diag.spelling, 22 "ranges": diag.ranges, 23 "fixits": diag.fixits, 24 } 25 26 27def get_cursor_id(cursor, cursor_list=[]): 28 if not opts.showIDs: 29 return None 30 31 if cursor is None: 32 return None 33 34 # FIXME: This is really slow. It would be nice if the index API exposed 35 # something that let us hash cursors. 36 for i, c in enumerate(cursor_list): 37 if cursor == c: 38 return i 39 cursor_list.append(cursor) 40 return len(cursor_list) - 1 41 42 43def get_info(node, depth=0): 44 if opts.maxDepth is not None and depth >= opts.maxDepth: 45 children = None 46 else: 47 children = [get_info(c, depth + 1) for c in node.get_children()] 48 return { 49 "id": get_cursor_id(node), 50 "kind": node.kind, 51 "usr": node.get_usr(), 52 "spelling": node.spelling, 53 "location": node.location, 54 "extent.start": node.extent.start, 55 "extent.end": node.extent.end, 56 "is_definition": node.is_definition(), 57 "definition id": get_cursor_id(node.get_definition()), 58 "children": children, 59 } 60 61 62def main(): 63 from clang.cindex import Index 64 from pprint import pprint 65 66 from optparse import OptionParser, OptionGroup 67 68 global opts 69 70 parser = OptionParser("usage: %prog [options] {filename} [clang-args*]") 71 parser.add_option( 72 "", 73 "--show-ids", 74 dest="showIDs", 75 help="Compute cursor IDs (very slow)", 76 action="store_true", 77 default=False, 78 ) 79 parser.add_option( 80 "", 81 "--max-depth", 82 dest="maxDepth", 83 help="Limit cursor expansion to depth N", 84 metavar="N", 85 type=int, 86 default=None, 87 ) 88 parser.disable_interspersed_args() 89 (opts, args) = parser.parse_args() 90 91 if len(args) == 0: 92 parser.error("invalid number arguments") 93 94 index = Index.create() 95 tu = index.parse(None, args) 96 if not tu: 97 parser.error("unable to load input") 98 99 pprint(("diags", [get_diag_info(d) for d in tu.diagnostics])) 100 pprint(("nodes", get_info(tu.cursor))) 101 102 103if __name__ == "__main__": 104 main() 105