Handle template expressions that may use the << or >> operators
[arduino-ctags.git] / ctags-visitor.vala
blobf7c050ab768730883389dad8ac0969a9bfc19416
1 /*
2 * ctags-visitor.vala
4 * Copyright 2008, 2010 Abderrahim Kitouni <a.kitouni@gmail.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 * MA 02110-1301, USA.
22 using Vala;
24 public struct CTagsEntry {
25 public int line_number;
26 public string name;
27 public string kind_name;
28 public char kind;
29 public string access;
30 public string implementation;
31 public string inheritance;
32 public string scope[2];
33 public string signature;
34 public string typeref;
35 public string returntype;
38 class DummyReport : Report {
39 public override void warn (SourceReference? source, string message) {}
40 public override void err (SourceReference? source, string message) {}
43 [CCode (has_target=false)]
44 public delegate void CTagsEntryMaker (CTagsEntry entry);
46 public class CTagsVisitor : CodeVisitor {
47 Parser vala_parser;
48 Genie.Parser genie_parser;
49 GLib.List<CTagsEntry?> taglist;
50 public CTagsVisitor () {
51 vala_parser = new Parser();
52 genie_parser = new Genie.Parser();
54 /* helper functions */
55 static string get_access (Symbol sym) {
56 switch (sym.access) {
57 case SymbolAccessibility.PRIVATE : return "private";
58 case SymbolAccessibility.INTERNAL : return "internal";
59 case SymbolAccessibility.PROTECTED : return "protected";
60 case SymbolAccessibility.PUBLIC : return "public";
62 assert_not_reached ();
64 static string to_string (Iterable<DataType> seq, string sep = ",") {
65 var str = new StringBuilder();
66 var first = true;
67 foreach (var type in seq) {
68 if(first) {
69 first = false;
70 } else {
71 str.append(sep);
73 str.append(type.to_qualified_string());
75 return str.str;
77 static string? implementation (Symbol sym) {
78 var list = new GLib.List<string>();
80 if (sym is Vala.Signal) {
81 var sig = (Vala.Signal)sym;
82 if (sig.is_virtual)
83 list.append("virtual");
84 } else if (sym is Class) {
85 var cls = (Class)sym;
86 if (cls.is_abstract)
87 list.append("abstract");
88 } else if (sym is Method) {
89 var meth = (Method)sym;
90 if (meth.is_abstract)
91 list.append("abstract");
92 else if (meth.is_virtual)
93 list.append("virtual");
94 } else if (sym is Property) {
95 var prop = (Property)sym;
96 if (prop.is_abstract)
97 list.append("abstract");
98 else if (prop.is_virtual)
99 list.append("virtual");
100 } else
101 return_val_if_reached(null);
103 var ret = new StringBuilder();
104 var first = true;
105 foreach (var str in list) {
106 if(first) {
107 first = false;
108 } else {
109 ret.append(",");
111 ret.append(str);
113 return ret.str;
115 static string signature (Vala.List<Vala.Parameter> parameter) {
116 var ret = new StringBuilder("(");
117 var first = true;
118 foreach (var p in parameter) {
119 if(first) {
120 first = false;
121 } else {
122 ret.append(",");
124 if (p.ellipsis) {
125 ret.append("...");
126 } else {
127 ret.append (p.variable_type.to_qualified_string());
128 ret.append (" ");
129 ret.append (p.name);
132 ret.append (")");
133 return ret.str;
135 static string[] scope (Symbol s) {
136 string scope[2];
137 var par = s.parent_symbol;
138 if (par != null && par.name != null) {
139 if (par is Class)
140 scope[0] = "class";
141 else if (par is Struct)
142 scope[0] = "struct";
143 else if (par is Interface)
144 scope[0] = "interface";
145 else
146 return scope;
147 scope[1] = par.name;
149 return scope;
151 /*static void print_tag(CTagsEntry en) {
152 stdout.printf("%s: %s at %d\n", en.name, en.kind_name, en.line_number);
155 public override void visit_source_file (SourceFile source_file) {
156 source_file.accept_children (this);
159 public override void visit_class (Class cl) {
160 var entry = CTagsEntry();
162 entry.line_number = cl.source_reference.begin.line;
163 entry.name = cl.name;
164 entry.kind_name = "class";
165 entry.kind = 'c';
166 entry.access = get_access (cl);
167 entry.implementation = implementation(cl);
168 entry.inheritance = to_string(cl.get_base_types(), ",");
169 entry.scope = scope (cl);
171 taglist.append(entry);
172 // print_tag(entry);
173 cl.accept_children(this);
175 public override void visit_struct (Struct st) {
176 var entry = CTagsEntry();
177 entry.line_number = st.source_reference.begin.line;
178 entry.name = st.name;
179 entry.kind_name = "struct";
180 entry.kind = 's';
181 entry.access = get_access (st);
182 entry.scope = scope (st);
184 taglist.append(entry);
185 // print_tag(entry);
186 st.accept_children(this);
188 public override void visit_interface (Interface iface) {
189 var entry = CTagsEntry();
191 entry.line_number = iface.source_reference.begin.line;
192 entry.name = iface.name;
193 entry.kind_name = "interface";
194 entry.kind = 'i';
195 entry.access = get_access (iface);
196 entry.inheritance = to_string(iface.get_prerequisites());
197 entry.scope = scope (iface);
199 taglist.append(entry);
200 // print_tag(entry);
201 iface.accept_children(this);
204 public override void visit_enum (Vala.Enum en) {
205 var entry = CTagsEntry();
207 entry.line_number = en.source_reference.begin.line;
208 entry.name = en.name;
209 entry.kind_name = "enum";
210 entry.kind = 'e';
211 entry.access = get_access (en);
212 entry.scope = scope (en);
214 taglist.append(entry);
215 // print_tag(entry);
216 en.accept_children(this);
218 public override void visit_error_domain (ErrorDomain edomain) {
219 var entry = CTagsEntry();
221 entry.line_number = edomain.source_reference.begin.line;
222 entry.name = edomain.name;
223 entry.kind_name = "errordomain";
224 entry.kind = 'E';
225 entry.access = get_access (edomain);
226 entry.scope = scope (edomain);
228 taglist.append(entry);
229 // print_tag(entry);
230 edomain.accept_children(this);
233 public override void visit_enum_value (Vala.EnumValue ev) {
234 var entry = CTagsEntry();
236 entry.line_number = ev.source_reference.begin.line;
237 entry.name = ev.name;
238 entry.kind_name = "enumvalue";
239 entry.kind = 'v';
240 entry.access = get_access (ev);
241 entry.scope = scope (ev);
243 taglist.append(entry);
244 // print_tag(entry);
246 public override void visit_error_code (ErrorCode ecode) {
247 var entry = CTagsEntry();
249 //entry.line_number = ecode.source_reference.begin.line;
250 entry.name = ecode.name;
251 entry.kind_name = "errorcode";
252 entry.kind = 'r';
253 entry.access = get_access (ecode);
254 entry.scope = scope (ecode);
256 taglist.append(entry);
257 // print_tag(entry);
260 public override void visit_delegate (Delegate d) {
261 var entry = CTagsEntry();
263 entry.line_number = d.source_reference.begin.line;
264 entry.name = d.name;
265 entry.kind_name = "delegate";
266 entry.kind = 'd';
267 entry.access = get_access (d);
268 entry.scope = scope (d);
269 entry.returntype = d.return_type.to_qualified_string();
270 entry.signature = signature(d.get_parameters());
272 taglist.append(entry);
273 // print_tag(entry);
275 public override void visit_signal (Vala.Signal sig) {
276 var entry = CTagsEntry();
278 entry.line_number = sig.source_reference.begin.line;
279 entry.name = sig.name;
280 entry.kind_name = "signal";
281 entry.kind = 'S';
282 entry.access = get_access (sig);
283 entry.implementation = implementation(sig);
284 entry.scope = scope (sig);
285 entry.returntype = sig.return_type.to_qualified_string();
286 entry.signature = signature(sig.get_parameters());
288 taglist.append(entry);
289 // print_tag(entry);
291 public override void visit_field (Field f) {
292 var entry = CTagsEntry();
294 entry.line_number = f.source_reference.begin.line;
295 entry.name = f.name;
296 entry.kind_name = "field";
297 entry.kind = 'f';
298 entry.access = get_access (f);
299 entry.scope = scope (f);
300 entry.typeref = f.variable_type.to_qualified_string();
302 taglist.append(entry);
303 // print_tag(entry);
305 public override void visit_constant (Constant c) {
306 var entry = CTagsEntry();
308 entry.line_number = c.source_reference.begin.line;
309 entry.name = c.name;
310 entry.kind_name = "field";
311 entry.kind = 'f';
312 entry.access = get_access (c);
313 entry.scope = scope (c);
314 entry.typeref = c.type_reference.to_qualified_string();
316 taglist.append(entry);
317 // print_tag(entry);
319 public override void visit_property (Property prop) {
320 var entry = CTagsEntry();
322 entry.line_number = prop.source_reference.begin.line;
323 entry.name = prop.name;
324 entry.kind_name = "property";
325 entry.kind = 'p';
326 entry.access = get_access (prop);
327 entry.implementation = implementation(prop);
328 entry.scope = scope (prop);
329 entry.typeref = prop.property_type.to_qualified_string();
331 taglist.append(entry);
332 // print_tag(entry);
335 public override void visit_method (Method m) {
336 var entry = CTagsEntry();
338 entry.line_number = m.source_reference.begin.line;
339 entry.name = m.name;
340 entry.kind_name = "method";
341 entry.kind = 'm';
342 entry.access = get_access (m);
343 entry.implementation = implementation(m);
344 entry.scope = scope (m);
345 entry.returntype = m.return_type.to_qualified_string();
346 entry.signature = signature(m.get_parameters());
348 taglist.append(entry);
349 // print_tag(entry);
352 public override void visit_local_variable (LocalVariable local) {
353 var entry = CTagsEntry();
355 entry.line_number = local.source_reference.begin.line;
356 entry.name = local.name;
357 entry.kind_name = "local";
358 entry.kind = 'l';
359 entry.access = get_access (local);
361 taglist.append(entry);
362 // print_tag(entry);
365 public void parse_vala (string filename, CTagsEntryMaker maker ) {
366 taglist = new GLib.List<CTagsEntry?>();
367 /* We create a context for every source file so that Parser.parse(context)
368 * don't parse a file multiple times causing errors. Parser.parse_file(source_file)
369 * assumes that Parser.context is the same as source_file.context anyway */
370 var context = new CodeContext();
371 context.report = new DummyReport();
372 var source_file = new SourceFile(context, filename.has_suffix("vapi") ? SourceFileType.PACKAGE : SourceFileType.SOURCE, filename);
374 CodeContext.push(context);
375 context.add_source_file(source_file);
376 vala_parser.parse(context);
377 context.accept(this);
378 foreach (var tagentry in taglist) {
379 maker(tagentry);
381 taglist = null;
382 CodeContext.pop();
384 public void parse_genie (string filename, CTagsEntryMaker maker ) {
385 taglist = new GLib.List<CTagsEntry?>();
386 var context = new CodeContext();
387 context.report = new DummyReport();
388 var source_file = new SourceFile(context, SourceFileType.SOURCE, filename);
389 context.add_source_file(source_file);
391 CodeContext.push(context);
392 genie_parser.parse(context);
393 context.accept(this);
394 foreach (var tagentry in taglist) {
395 maker(tagentry);
397 taglist = null;
398 CodeContext.pop();