[anjuta] anjuta-tags: add support for parsing vala tags (using libvala if available)



commit 08e5aa77b6ba850274d77ebb4c639a3e6ddf9d3e
Author: Abderrahim Kitouni <a kitouni gmail com>
Date:   Wed Feb 10 23:40:30 2010 +0100

    anjuta-tags: add support for parsing vala tags (using libvala if available)

 configure.in                                     |   11 +
 plugins/symbol-db/anjuta-tags/Makefile.am        |   14 +-
 plugins/symbol-db/anjuta-tags/ctags-visitor.vala |  369 ++++++++++++++++++++++
 plugins/symbol-db/anjuta-tags/parsers.h          |   48 +++
 plugins/symbol-db/anjuta-tags/vala.c             |  100 ++++++
 5 files changed, 541 insertions(+), 1 deletions(-)
---
diff --git a/configure.in b/configure.in
index da0f555..db766ac 100644
--- a/configure.in
+++ b/configure.in
@@ -44,6 +44,7 @@ GTKSOURCEVIEW_REQUIRED=2.9.3
 LIBWNCK_REQUIRED=2.12
 GDA_REQUIRED=4.0.0
 UNIQUE_REQUIRED=1.0.0
+VALA_REQUIRED=0.7.8
 
 AC_SUBST(GLIB_REQUIRED)
 AC_SUBST(GDK_PIXBUF_REQUIRED)
@@ -270,6 +271,16 @@ fi
 
 AM_CONDITIONAL(HAVE_PLUGIN_SOURCEVIEW, [test x$sourceview = xyes])
 
+dnl Check for vala
+dnl -------------------------------------------------------------
+
+PKG_CHECK_MODULES(VALA,
+	[vala-1.0 >= $VALA_REQUIRED],
+	[enable_vala="yes"],
+	[enable_vala="no"])
+
+AM_CONDITIONAL(ENABLE_VALA, [test x$enable_vala = xyes])
+
 PKG_CHECK_MODULES(PLUGIN_SYMBOL_DB,
 		[libgda-4.0 >= $GDA_REQUIRED])
 
diff --git a/plugins/symbol-db/anjuta-tags/Makefile.am b/plugins/symbol-db/anjuta-tags/Makefile.am
index 454fa30..d23e2a1 100644
--- a/plugins/symbol-db/anjuta-tags/Makefile.am
+++ b/plugins/symbol-db/anjuta-tags/Makefile.am
@@ -10,6 +10,7 @@ AM_CPPFLAGS = \
 AM_CFLAGS =\
 	 -Wall \
 	 $(GLIB_CFLAGS) \
+	 $(VALA_CFLAGS) \
 	 $(LIBXML_CFLAGS)
 
 bin_PROGRAMS = anjuta-tags
@@ -28,6 +29,9 @@ LEXCCFLAGS = -Cr -o js_parser/lex.yy.c --yylineno --bison-bridge
 js_parser/lex.yy.c : ${LEXFILE}
 	${LEXER} ${LEXCCFLAGS} ${LEXFILE}
 
+ctags-visitor.c: ctags-visitor.vala
+	valac -g -h ctags-vala.h -C --pkg vala-1.0 $^
+
 anjuta_tags_SOURCES = \
 	main.c        \
 	acconfig.h        \
@@ -126,6 +130,14 @@ anjuta_tags_LDFLAGS = \
 
 anjuta_tags_LDADD = \
 		$(GLIB_LIBS) \
+		$(VALA_LIBS) \
 		$(LIBXML_LIBS)
 
-EXTRA_DIST = ${YACCFILE} ${LEXFILE}
+EXTRA_DIST = ${YACCFILE} ${LEXFILE} ctags-visitor.vala ctags-visitor.c ctags-vala.h
+
+if ENABLE_VALA
+anjuta_tags_SOURCES += vala.c ctags-visitor.c
+AM_CPPFLAGS += -DENABLE_VALA
+BUILT_SOURCES = ctags-visitor.c
+endif
+
diff --git a/plugins/symbol-db/anjuta-tags/ctags-visitor.vala b/plugins/symbol-db/anjuta-tags/ctags-visitor.vala
new file mode 100644
index 0000000..09ac68e
--- /dev/null
+++ b/plugins/symbol-db/anjuta-tags/ctags-visitor.vala
@@ -0,0 +1,369 @@
+/*
+ * ctags-visitor.vala
+ *
+ * Copyright 2008, 2010 Abderrahim Kitouni <a kitouni gmail com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+using Vala;
+
+public class CTagsEntry {
+	public int line_number;
+	public string name;
+	public string kind_name;
+	public char kind;
+	public string access;
+	public string implementation;
+	public string inheritance;
+	public string signature;
+	public string typeref;
+}
+
+class DummyReport : Report {
+	public override void warn (SourceReference? source, string message) {}
+	public override void err (SourceReference? source, string message) {}
+}
+
+[CCode (has_target=false)]
+public delegate void CTagsEntryMaker (CTagsEntry entry);
+
+public class CTagsVisitor : CodeVisitor {
+	Parser vala_parser;
+	Genie.Parser genie_parser;
+	GLib.List<CTagsEntry> taglist;
+	public CTagsVisitor () {
+		vala_parser = new Parser();
+		genie_parser = new Genie.Parser();
+	}
+	/* helper functions */
+	static string get_access (Symbol sym) {
+		switch (sym.access) {
+		case SymbolAccessibility.PRIVATE : return "private";
+		case SymbolAccessibility.INTERNAL : return "internal";
+		case SymbolAccessibility.PROTECTED : return "protected";
+		case SymbolAccessibility.PUBLIC : return "public";
+		}
+		assert_not_reached ();
+	}
+	static string to_string (Iterable<DataType> seq, string sep = ",") {
+		var str = new StringBuilder();
+		var first = true;
+		foreach (var type in seq) {
+			if(first) {
+				first = false;
+			} else {
+				str.append(sep);
+			}
+			str.append(type.to_qualified_string());
+		}
+		return str.str;
+	}
+	static string? implementation (Symbol sym) {
+		var list = new GLib.List<string>();
+
+		if (sym is Vala.Signal) {
+			var sig = (Vala.Signal)sym;
+			if (sig.is_virtual)
+				list.append("virtual");
+		} else if (sym is Class) {
+			var cls = (Class)sym;
+			if (cls.is_abstract)
+				list.append("abstract");
+		} else if (sym is Method) {
+			var meth = (Method)sym;
+			if (meth.is_abstract)
+				list.append("abstract");
+			else if (meth.is_virtual)
+				list.append("virtual");
+		} else if (sym is Property) {
+			var prop = (Property)sym;
+			if (prop.is_abstract)
+				list.append("abstract");
+			else if (prop.is_virtual)
+				list.append("virtual");
+		} else
+			return_val_if_reached(null);
+
+		var ret = new StringBuilder();
+		var first = true;
+		foreach (var str in list) {
+			if(first) {
+				first = false;
+			} else {
+				ret.append(",");
+			}
+			ret.append(str);
+		}
+		return ret.str;
+	}
+	static string signature (Vala.List<Vala.FormalParameter> parameter) {
+		var ret = new StringBuilder("(");
+		var first = true;
+		foreach (var p in parameter) {
+			if(first) {
+				first = false;
+			} else {
+				ret.append(",");
+			}
+			if (p.ellipsis) {
+				ret.append("...");
+			} else {
+				ret.append (p.parameter_type.to_qualified_string());
+				ret.append (" ");
+				ret.append (p.name);
+			}
+		}
+		ret.append (")");
+		return ret.str;
+	}
+	/*static void print_tag(CTagsEntry en) {
+		stdout.printf("%s: %s at %d\n", en.name, en.kind_name, en.line_number);
+	}*/
+
+	public override void visit_source_file (SourceFile source_file) {
+		source_file.accept_children (this);
+	}
+
+	public override void visit_class (Class cl) {
+		var entry = new CTagsEntry();
+
+		entry.line_number = cl.source_reference.first_line;
+		entry.name = cl.name;
+		entry.kind_name = "class";
+		entry.kind = 'c';
+		entry.access = get_access (cl);
+		entry.implementation = implementation(cl);
+		entry.inheritance = to_string(cl.get_base_types(), ",");
+
+		taglist.append(entry);
+//		print_tag(entry);
+		cl.accept_children(this);
+	}
+	public override void visit_struct (Struct st) {
+		var entry = new CTagsEntry();
+		entry.line_number = st.source_reference.first_line;
+		entry.name = st.name;
+		entry.kind_name = "struct";
+		entry.kind = 's';
+		entry.access = get_access (st);
+
+		taglist.append(entry);
+//		print_tag(entry);
+		st.accept_children(this);
+	}
+	public override void visit_interface (Interface iface) {
+		var entry = new CTagsEntry();
+
+		entry.line_number = iface.source_reference.first_line;
+		entry.name = iface.name;
+		entry.kind_name = "interface";
+		entry.kind = 'i';
+		entry.access = get_access (iface);
+		entry.inheritance = to_string(iface.get_prerequisites());
+
+		taglist.append(entry);
+//		print_tag(entry);
+		iface.accept_children(this);
+	}
+
+	public override void visit_enum (Vala.Enum en) {
+		var entry = new CTagsEntry();
+
+		entry.line_number = en.source_reference.first_line;
+		entry.name = en.name;
+		entry.kind_name = "enum";
+		entry.kind = 'e';
+		entry.access = get_access (en);
+
+		taglist.append(entry);
+//		print_tag(entry);
+		en.accept_children(this);
+	}
+	public override void visit_error_domain (ErrorDomain edomain) {
+		var entry = new CTagsEntry();
+
+		entry.line_number = edomain.source_reference.first_line;
+		entry.name = edomain.name;
+		entry.kind_name = "errordomain";
+		entry.kind = 'E';
+		entry.access = get_access (edomain);
+
+		taglist.append(entry);
+//		print_tag(entry);
+		edomain.accept_children(this);
+	}
+
+	public override void visit_enum_value (Vala.EnumValue ev) {
+		var entry = new CTagsEntry();
+
+		entry.line_number = ev.source_reference.first_line;
+		entry.name = ev.name;
+		entry.kind_name = "enumvalue";
+		entry.kind = 'v';
+		entry.access = get_access (ev);
+
+		taglist.append(entry);
+//		print_tag(entry);
+	}
+	public override void visit_error_code (ErrorCode ecode) {
+		var entry = new CTagsEntry();
+
+		//entry.line_number = ecode.source_reference.first_line;
+		entry.name = ecode.name;
+		entry.kind_name = "errorcode";
+		entry.kind = 'r';
+		entry.access = get_access (ecode);
+
+		taglist.append(entry);
+//		print_tag(entry);
+	}
+
+	public override void visit_delegate (Delegate d) {
+		var entry = new CTagsEntry();
+
+		entry.line_number = d.source_reference.first_line;
+		entry.name = d.name;
+		entry.kind_name = "delegate";
+		entry.kind = 'd';
+		entry.access = get_access (d);
+		entry.typeref = d.return_type.to_qualified_string();
+		entry.signature = signature(d.get_parameters());
+
+		taglist.append(entry);
+//		print_tag(entry);
+	}
+	public override void visit_signal (Vala.Signal sig) {
+		var entry = new CTagsEntry();
+
+		entry.line_number = sig.source_reference.first_line;
+		entry.name = sig.name;
+		entry.kind_name = "signal";
+		entry.kind = 'S';
+		entry.access = get_access (sig);
+		entry.implementation = implementation(sig);
+		entry.typeref = sig.return_type.to_qualified_string();
+		entry.signature = signature(sig.get_parameters());
+
+		taglist.append(entry);
+//		print_tag(entry);
+	}
+	public override void visit_field (Field f) {
+		var entry = new CTagsEntry();
+
+		entry.line_number = f.source_reference.first_line;
+		entry.name = f.name;
+		entry.kind_name = "field";
+		entry.kind = 'f';
+		entry.access = get_access (f);
+		entry.typeref = f.field_type.to_qualified_string();
+
+		taglist.append(entry);
+//		print_tag(entry);
+	}
+	public override void visit_constant (Constant c) {
+		var entry = new CTagsEntry();
+
+		entry.line_number = c.source_reference.first_line;
+		entry.name = c.name;
+		entry.kind_name = "field";
+		entry.kind = 'f';
+		entry.access = get_access (c);
+		entry.typeref = c.type_reference.to_qualified_string();
+  
+		taglist.append(entry);
+//		print_tag(entry);
+	}
+	public override void visit_property (Property prop) {
+		var entry = new CTagsEntry();
+
+		entry.line_number = prop.source_reference.first_line;
+		entry.name = prop.name;
+		entry.kind_name = "property";
+		entry.kind = 'p';
+		entry.access = get_access (prop);
+		entry.implementation = implementation(prop);
+		entry.typeref = prop.property_type.to_qualified_string();
+
+		taglist.append(entry);
+//		print_tag(entry);
+	}
+
+	public override void visit_method (Method m) {
+		var entry = new CTagsEntry();
+
+		entry.line_number = m.source_reference.first_line;
+		entry.name = m.name;
+		entry.kind_name = "method";
+		entry.kind = 'm';
+		entry.access = get_access (m);
+		entry.implementation = implementation(m);
+		entry.typeref = m.return_type.to_qualified_string();
+		entry.signature = signature(m.get_parameters());
+
+		taglist.append(entry);
+//		print_tag(entry);
+	}
+
+	public override void visit_local_variable (LocalVariable local) {
+		var entry = new CTagsEntry();
+
+		entry.line_number = local.source_reference.first_line;
+		entry.name = local.name;
+		entry.kind_name = "local";
+		entry.kind = 'l';
+		entry.access = get_access (local);
+
+		taglist.append(entry);
+//		print_tag(entry);
+	}
+
+	public void parse_vala (string filename, CTagsEntryMaker maker ) {
+		taglist = new GLib.List<CTagsEntry>();
+		/* We create a context for every source file so that Parser.parse(context)
+		 * don't parse a file multiple times causing errors. Parser.parse_file(source_file)
+		 * assumes that Parser.context is the same as source_file.context anyway */
+		var context = new CodeContext();
+		context.report = new DummyReport();
+		var source_file = new SourceFile(context, filename, filename.has_suffix("vapi"));
+
+		CodeContext.push(context);
+		context.add_source_file(source_file);
+		vala_parser.parse(context);
+		context.accept(this);
+		foreach (var tagentry in taglist) {
+			maker(tagentry);
+		}
+		taglist = null;
+		CodeContext.pop();
+	}
+	public void parse_genie (string filename, CTagsEntryMaker maker ) {
+		taglist = new GLib.List<CTagsEntry>();
+		var context = new CodeContext();
+		context.report = new DummyReport();
+		var source_file = new SourceFile(context, filename);
+		context.add_source_file(source_file);
+
+		CodeContext.push(context);
+		genie_parser.parse(context);
+		context.accept(this);
+		foreach (var tagentry in taglist) {
+			maker(tagentry);
+		}
+		taglist = null;
+		CodeContext.pop();
+		}
+}
diff --git a/plugins/symbol-db/anjuta-tags/parsers.h b/plugins/symbol-db/anjuta-tags/parsers.h
index 44dd66f..bf5cb98 100644
--- a/plugins/symbol-db/anjuta-tags/parsers.h
+++ b/plugins/symbol-db/anjuta-tags/parsers.h
@@ -15,6 +15,7 @@
 #define _PARSERS_H
 
 /* Add the name of any new parser definition function here */
+#ifndef ENABLE_VALA
 #define PARSER_LIST \
 	AntParser, \
 	AsmParser, \
@@ -58,6 +59,53 @@
 	VhdlParser, \
 	VimParser, \
 	YaccParser
+#else
+#define PARSER_LIST \
+	AntParser, \
+	AsmParser, \
+	AspParser, \
+	AwkParser, \
+	BasicParser, \
+	BetaParser, \
+	CParser, \
+	CppParser, \
+	CsharpParser, \
+	CobolParser, \
+	DosBatchParser, \
+	EiffelParser, \
+	ErlangParser, \
+	FlexParser, \
+	FortranParser, \
+	GenieParser, \
+	GirParser,  \
+	HtmlParser, \
+	JavaParser, \
+	JavaScriptParser, \
+	LispParser, \
+	LuaParser, \
+	MakefileParser, \
+	MatLabParser, \
+	OcamlParser, \
+	PascalParser, \
+	PerlParser, \
+	PhpParser, \
+	PythonParser, \
+	RexxParser, \
+	RubyParser, \
+	SchemeParser, \
+	ShParser, \
+	SlangParser, \
+	SmlParser, \
+	SqlParser, \
+	TclParser, \
+	TexParser, \
+	ValaParse, \
+	VeraParser, \
+	VerilogParser, \
+	VhdlParser, \
+	VimParser, \
+	YaccParser
+#endif
 
 #endif  /* _PARSERS_H */
 
diff --git a/plugins/symbol-db/anjuta-tags/vala.c b/plugins/symbol-db/anjuta-tags/vala.c
new file mode 100644
index 0000000..075dd6b
--- /dev/null
+++ b/plugins/symbol-db/anjuta-tags/vala.c
@@ -0,0 +1,100 @@
+/*
+ * vala.c
+ *
+ * Copyright 2008 Abderrahim Kitouni <a kitouni gmail com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+/*
+ *   INCLUDE FILES
+ */
+#include "general.h"  /* must always come first */
+#include "parse.h"
+#include "read.h"
+
+#include "entry.h"
+#include "ctags-vala.h"
+
+CTagsVisitor *visitor;
+/* using different data structure because fpos_t isn't available in Vala*/
+static void make_ctags_entry (CTagsEntry* entry) {
+	tagEntryInfo tag;
+	initTagEntry(&tag, entry->name);
+
+	tag.lineNumberEntry = TRUE;
+	tag.lineNumber = entry->line_number;
+	tag.kindName = entry->kind_name;
+	tag.kind = entry->kind;
+	/* FIXME: add filePosition */
+	tag.extensionFields.access = entry->access;
+	tag.extensionFields.implementation = entry->implementation;
+	tag.extensionFields.inheritance = entry->inheritance;
+	tag.extensionFields.typeRef[0] = entry->typeref;
+	tag.extensionFields.signature = entry->signature;
+	makeTagEntry(&tag);
+}
+
+static kindOption ValaKinds [] = {
+	{ TRUE,	'c', "class", "Classes" },
+	{ TRUE, 's', "struct", "Structures" },
+	{ TRUE, 'i', "interface", "Interfaces" },
+	{ TRUE, 'e', "enum", "Enumerations" },
+	{ TRUE, 'v', "enumvalue", "Enumeration Values" },
+	{ TRUE, 'E', "errordomain", "Error domains" },
+	{ TRUE, 'r', "errorcode", "Error codes" },
+	{ TRUE, 'd', "delegate", "Delegates" },
+	{ TRUE, 'S', "signal", "Signals" },
+	{ TRUE,	'f', "field", "Fields" },
+	{ TRUE,	'p', "property", "Properties" },
+	{ TRUE, 'm', "method", "Methods" },
+	{ FALSE, 'l', "local", "Local variables" },
+};
+
+static void findValaTags (void) {
+	if (visitor == NULL) {
+		visitor = ctags_visitor_new();
+	}
+	ctags_visitor_parse_vala (visitor, getSourceFileName(), (CTagsEntryMaker) make_ctags_entry);
+}
+
+extern parserDefinition *ValaParse(void) {
+	g_type_init();
+	static const char *const extensions [] = { "vala", "vapi", NULL };
+	parserDefinition* def = parserNew ("Vala");
+	def->kinds      = ValaKinds;
+	def->kindCount  = KIND_COUNT (ValaKinds);
+	def->extensions = extensions;
+	def->parser     = findValaTags;
+	return def;
+}
+
+static void findGenieTags (void) {
+	if (visitor == NULL) {
+		visitor = ctags_visitor_new();
+	}
+	ctags_visitor_parse_genie (visitor, getSourceFileName(), (CTagsEntryMaker) make_ctags_entry);
+}
+
+extern parserDefinition *GenieParser(void) {
+	static const char *const extensions [] = { "gs", NULL };
+	parserDefinition* def = parserNew ("Genie");
+	def->kinds      = ValaKinds;
+	def->kindCount  = KIND_COUNT (ValaKinds);
+	def->extensions = extensions;
+	def->parser     = findGenieTags;
+	return def;
+}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]