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,
24 public struct CTagsEntry
{
25 public int line_number
;
27 public string kind_name
;
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
{
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
) {
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();
67 foreach (var type
in seq
) {
73 str
.append(type
.to_qualified_string());
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
;
83 list
.append("virtual");
84 } else if (sym is Class
) {
87 list
.append("abstract");
88 } else if (sym is Method
) {
89 var meth
= (Method
)sym
;
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
;
97 list
.append("abstract");
98 else if (prop
.is_virtual
)
99 list
.append("virtual");
101 return_val_if_reached(null);
103 var ret
= new
StringBuilder();
105 foreach (var str
in list
) {
115 static string signature (Vala
.List
<Vala
.Parameter
> parameter
) {
116 var ret
= new
StringBuilder("(");
118 foreach (var p
in parameter
) {
127 ret
.append (p
.variable_type
.to_qualified_string());
135 static string[] scope (Symbol s
) {
137 var par
= s
.parent_symbol
;
138 if (par
!= null && par
.name
!= null) {
141 else if (par is Struct
)
143 else if (par is Interface
)
144 scope
[0] = "interface";
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";
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
);
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";
181 entry
.access
= get_access (st
);
182 entry
.scope
= scope (st
);
184 taglist
.append(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";
195 entry
.access
= get_access (iface
);
196 entry
.inheritance
= to_string(iface
.get_prerequisites());
197 entry
.scope
= scope (iface
);
199 taglist
.append(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";
211 entry
.access
= get_access (en
);
212 entry
.scope
= scope (en
);
214 taglist
.append(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";
225 entry
.access
= get_access (edomain
);
226 entry
.scope
= scope (edomain
);
228 taglist
.append(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";
240 entry
.access
= get_access (ev
);
241 entry
.scope
= scope (ev
);
243 taglist
.append(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";
253 entry
.access
= get_access (ecode
);
254 entry
.scope
= scope (ecode
);
256 taglist
.append(entry
);
260 public override void visit_delegate (Delegate d
) {
261 var entry
= CTagsEntry();
263 entry
.line_number
= d
.source_reference
.begin
.line
;
265 entry
.kind_name
= "delegate";
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
);
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";
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
);
291 public override void visit_field (Field f
) {
292 var entry
= CTagsEntry();
294 entry
.line_number
= f
.source_reference
.begin
.line
;
296 entry
.kind_name
= "field";
298 entry
.access
= get_access (f
);
299 entry
.scope
= scope (f
);
300 entry
.typeref
= f
.variable_type
.to_qualified_string();
302 taglist
.append(entry
);
305 public override void visit_constant (Constant c
) {
306 var entry
= CTagsEntry();
308 entry
.line_number
= c
.source_reference
.begin
.line
;
310 entry
.kind_name
= "field";
312 entry
.access
= get_access (c
);
313 entry
.scope
= scope (c
);
314 entry
.typeref
= c
.type_reference
.to_qualified_string();
316 taglist
.append(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";
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
);
335 public override void visit_method (Method m
) {
336 var entry
= CTagsEntry();
338 entry
.line_number
= m
.source_reference
.begin
.line
;
340 entry
.kind_name
= "method";
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
);
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";
359 entry
.access
= get_access (local
);
361 taglist
.append(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
) {
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
) {