1ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao#!/usr/bin/env python
2ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao
3ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao#===- cindex-dump.py - cindex/Python Source Dump -------------*- python -*--===#
4ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao#
5ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao#                     The LLVM Compiler Infrastructure
6ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao#
7ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao# This file is distributed under the University of Illinois Open Source
8ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao# License. See LICENSE.TXT for details.
9ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao#
10ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao#===------------------------------------------------------------------------===#
11ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao
12ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao"""
13ea285162342df160e7860e26528bc7110bc6c0cdShih-wei LiaoA simple command line tool for dumping a source file using the Clang Index
14ea285162342df160e7860e26528bc7110bc6c0cdShih-wei LiaoLibrary.
15ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao"""
16ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao
17ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liaodef get_diag_info(diag):
18ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    return { 'severity' : diag.severity,
19ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao             'location' : diag.location,
20ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao             'spelling' : diag.spelling,
21ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao             'ranges' : diag.ranges,
22ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao             'fixits' : diag.fixits }
23ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao
24ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liaodef get_cursor_id(cursor, cursor_list = []):
25ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    if not opts.showIDs:
26ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao        return None
27ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao
28ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    if cursor is None:
29ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao        return None
30ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao
31ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    # FIXME: This is really slow. It would be nice if the index API exposed
32ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    # something that let us hash cursors.
33ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    for i,c in enumerate(cursor_list):
34ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao        if cursor == c:
35ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao            return i
36ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    cursor_list.append(cursor)
37ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    return len(cursor_list) - 1
38ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao
39ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liaodef get_info(node, depth=0):
40ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    if opts.maxDepth is not None and depth >= opts.maxDepth:
41ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao        children = None
42ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    else:
43ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao        children = [get_info(c, depth+1)
44ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao                    for c in node.get_children()]
45ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    return { 'id' : get_cursor_id(node),
46ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao             'kind' : node.kind,
47ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao             'usr' : node.get_usr(),
48ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao             'spelling' : node.spelling,
49ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao             'location' : node.location,
50ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao             'extent.start' : node.extent.start,
51ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao             'extent.end' : node.extent.end,
52ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao             'is_definition' : node.is_definition(),
53ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao             'definition id' : get_cursor_id(node.get_definition()),
54ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao             'children' : children }
55ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao
56ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liaodef main():
57ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    from clang.cindex import Index
58ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    from pprint import pprint
59ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao
60ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    from optparse import OptionParser, OptionGroup
61ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao
62ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    global opts
63ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao
64ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    parser = OptionParser("usage: %prog [options] {filename} [clang-args*]")
65ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    parser.add_option("", "--show-ids", dest="showIDs",
666bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                      help="Compute cursor IDs (very slow)",
676bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                      action="store_true", default=False)
68ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    parser.add_option("", "--max-depth", dest="maxDepth",
69ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao                      help="Limit cursor expansion to depth N",
70ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao                      metavar="N", type=int, default=None)
71ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    parser.disable_interspersed_args()
72ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    (opts, args) = parser.parse_args()
73ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao
74ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    if len(args) == 0:
75ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao        parser.error('invalid number arguments')
76ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao
77ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    index = Index.create()
78ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    tu = index.parse(None, args)
79ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    if not tu:
80ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao        parser.error("unable to load input")
81ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao
82ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    pprint(('diags', map(get_diag_info, tu.diagnostics)))
83ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    pprint(('nodes', get_info(tu.cursor)))
84ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao
85ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liaoif __name__ == '__main__':
86ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao    main()
87ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao
88