|
17 | 17 | You should have received a copy of the GNU General Public License |
18 | 18 | along with this program. If not, see http://www.gnu.org/licenses/. |
19 | 19 | ''' |
| 20 | + |
| 21 | +from index_transform.doxygen_tag import * |
20 | 22 | import argparse |
21 | | -from index_transform import IndexTransform |
22 | | -from xml_utils import xml_escape |
23 | 23 | from link_map import LinkMap |
24 | | -from functools import total_ordering |
25 | 24 | from lxml import etree |
26 | | -import sys |
27 | | - |
28 | | -class ItemKind: |
29 | | - VARIABLE = 0, |
30 | | - FUNCTION = 1, |
31 | | - CLASS = 2, |
32 | | - TYPEDEF = 3, |
33 | | - NAMESPACE = 4 |
34 | | - |
35 | | -@total_ordering |
36 | | -class Item: |
37 | | - |
38 | | - def __init__(self): |
39 | | - self.name = "" |
40 | | - self.full_name = "" |
41 | | - self.kind = ItemKind.NAMESPACE |
42 | | - self.link = "" |
43 | | - self.members = {} |
44 | | - |
45 | | - def __eq__(self, other): |
46 | | - return self.full_name == other.full_name |
47 | | - |
48 | | - def __lt__(self, other): |
49 | | - return self.full_name < other.full_name |
50 | | - |
51 | | -def add_to_map(ns_map, full_name, full_link, item_kind): |
52 | | - names = full_name.split('::') |
53 | | - parsed_names = [] |
54 | | - last_name = names.pop() # i.e. unqualified name |
55 | | - curr_item = ns_map |
56 | | - |
57 | | - for name in names: |
58 | | - parsed_names.append(name) |
59 | | - if name in curr_item.members: |
60 | | - curr_item = curr_item.members[name] |
61 | | - if curr_item.kind not in [ ItemKind.CLASS, ItemKind.NAMESPACE ]: |
62 | | - print("ERROR: " + name + " in " + full_name + |
63 | | - " is not a class or namespace") |
64 | | - return |
65 | | - else: |
66 | | - # we add inexistent intermediate elements as namespaces and convert |
67 | | - # them to classes later when class definitions are encountered |
68 | | - new_item = Item() |
69 | | - new_item.name = name |
70 | | - new_item.full_name = "::".join(parsed_names) |
71 | | - new_item.kind = ItemKind.NAMESPACE |
72 | | - |
73 | | - curr_item.members[name] = new_item |
74 | | - curr_item = new_item |
75 | | - |
76 | | - if last_name in curr_item.members: |
77 | | - curr_item = curr_item.members[last_name] |
78 | | - if (item_kind == ItemKind.CLASS and |
79 | | - curr_item.kind in [ ItemKind.CLASS, ItemKind.NAMESPACE ]): |
80 | | - curr_item.kind = item_kind # fix namespaces that are actually classes |
81 | | - curr_item.link = full_link |
82 | | - else: |
83 | | - print("ERROR: Duplicate element: " + full_name) |
84 | | - else: |
85 | | - new_item = Item() |
86 | | - new_item.full_name = full_name |
87 | | - new_item.name = last_name |
88 | | - new_item.link = full_link |
89 | | - new_item.kind = item_kind |
90 | | - curr_item.members[last_name] = new_item |
91 | | - curr_item = new_item |
92 | | - return |
93 | | - |
94 | | -def print_members(out_f, link_map, curr_item): |
95 | | - for item in sorted(curr_item.members.values()): |
96 | | - if link_map: |
97 | | - link = link_map.get_dest(item.link) |
98 | | - if link == None and item.kind != ItemKind.NAMESPACE: |
99 | | - print("WARN: " + item.full_name + " contains invalid link") |
100 | | - link = '404' |
101 | | - else: |
102 | | - link = item.link |
103 | | - |
104 | | - if item.kind == ItemKind.VARIABLE: |
105 | | - out_f.write(' <member kind="variable">\n' + |
106 | | - ' <type>T</type>\n' + |
107 | | - ' <name>' + xml_escape(item.name) + '</name>\n' + |
108 | | - ' <anchorfile>' + xml_escape(link) + '</anchorfile>\n' + |
109 | | - ' <anchor></anchor>\n' + |
110 | | - ' <arglist></arglist>\n' + |
111 | | - ' </member>\n') |
112 | | - elif item.kind == ItemKind.FUNCTION: |
113 | | - out_f.write(' <member kind="function">\n' + |
114 | | - ' <type>T</type>\n' + |
115 | | - ' <name>' + xml_escape(item.name) + '</name>\n' + |
116 | | - ' <anchorfile>' + xml_escape(link) + '</anchorfile>\n' + |
117 | | - ' <anchor></anchor>\n' + |
118 | | - ' <arglist>(T... args)</arglist>\n' + |
119 | | - ' </member>\n') |
120 | | - elif item.kind == ItemKind.CLASS: |
121 | | - out_f.write(' <class kind="class">' + xml_escape(item.full_name) + '</class>\n') |
122 | | - elif item.kind == ItemKind.NAMESPACE: |
123 | | - out_f.write(' <namespace>' + xml_escape(item.full_name) + '</namespace>\n') |
124 | | - |
125 | | -def print_map_item(out_f, link_map, curr_item): |
126 | | - item_kind_to_attr = { ItemKind.NAMESPACE : 'namespace', |
127 | | - ItemKind.CLASS : 'class' } |
128 | | - if curr_item.kind not in item_kind_to_attr: |
129 | | - print('ERROR: only namespaces and classes can have members') |
130 | | - return |
131 | | - |
132 | | - out_f.write(' <compound kind="' + item_kind_to_attr[curr_item.kind] + '">\n' + |
133 | | - ' <name>' + xml_escape(curr_item.full_name) + '</name>\n' + |
134 | | - ' <filename>' + xml_escape(curr_item.link) + '</filename>\n') |
135 | | - print_members(out_f, link_map, curr_item) |
136 | | - out_f.write(' </compound>\n') |
137 | | - |
138 | | - for item in sorted(curr_item.members.values()): |
139 | | - if item.kind in [ ItemKind.NAMESPACE, ItemKind.CLASS ]: |
140 | | - print_map_item(out_f, link_map, item) |
141 | | - |
142 | | -def print_map(out_f, link_map, ns_map): |
143 | | - for item in sorted(ns_map.members.values()): |
144 | | - if item.kind in [ ItemKind.NAMESPACE, ItemKind.CLASS ]: |
145 | | - print_map_item(out_f, link_map, item) |
146 | | - else: |
147 | | - print("WARN: " + item.full_name + " ignored") |
148 | | - |
149 | | -class Index2Devhelp(IndexTransform): |
150 | | - def __init__(self, ns_map): |
151 | | - super().__init__() |
152 | | - self.ns_map = ns_map |
153 | | - |
154 | | - def get_item_kind(self, el): |
155 | | - if el.tag == 'const': return None |
156 | | - elif el.tag == 'function': return ItemKind.FUNCTION |
157 | | - elif el.tag == 'constructor': return ItemKind.FUNCTION |
158 | | - elif el.tag == 'destructor': return ItemKind.FUNCTION |
159 | | - elif el.tag == 'class': return ItemKind.CLASS |
160 | | - elif el.tag == 'enum': return 'enum' |
161 | | - elif el.tag == 'typedef': return ItemKind.CLASS |
162 | | - elif el.tag == 'specialization': return None |
163 | | - elif el.tag == 'overload': return None |
164 | | - elif el.tag == 'variable': return ItemKind.VARIABLE |
165 | | - return None |
166 | | - |
167 | | - def process_item_hook(self, el, full_name, full_link): |
168 | | - item_kind = self.get_item_kind(el) |
169 | | - if item_kind != None: |
170 | | - add_to_map(self.ns_map, full_name, full_link, item_kind) |
171 | | - IndexTransform.process_item_hook(self, el, full_name, full_link) |
172 | 25 |
|
173 | 26 | def main(): |
174 | 27 | parser = argparse.ArgumentParser(prog='index2doxygen-tag') |
|
0 commit comments