[vala] girparser: Support tweaking type and type arguments in the metadata
- From: Evan Nemerson <evann src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala] girparser: Support tweaking type and type arguments in the metadata
- Date: Mon, 8 Nov 2010 10:03:05 +0000 (UTC)
commit 8a6407322503d3fe5eee4bd5e91298c8c2c35d63
Author: Luca Bruno <lucabru src gnome org>
Date: Sun Oct 31 15:23:10 2010 -0700
girparser: Support tweaking type and type arguments in the metadata
vala/valagirparser.vala | 198 +++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 191 insertions(+), 7 deletions(-)
---
diff --git a/vala/valagirparser.vala b/vala/valagirparser.vala
index 7e456a8..5bef016 100644
--- a/vala/valagirparser.vala
+++ b/vala/valagirparser.vala
@@ -480,6 +480,8 @@ public class Vala.GirParser : CodeVisitor {
public SourceReference source_reference;
}
+ static GLib.Regex type_from_string_regex;
+
MarkupReader reader;
CodeContext context;
@@ -892,6 +894,177 @@ public class Vala.GirParser : CodeVisitor {
metadata_stack.remove_at (metadata_stack.size - 1);
}
+ bool parse_type_arguments_from_string (DataType parent_type, string type_arguments, SourceReference? source_reference = null) {
+ int type_arguments_length = (int) type_arguments.length;
+ GLib.StringBuilder current = new GLib.StringBuilder.sized (type_arguments_length);
+
+ int depth = 0;
+ for (var c = 0 ; c < type_arguments_length ; c++) {
+ if (type_arguments[c] == '<' || type_arguments[c] == '[') {
+ depth++;
+ current.append_unichar (type_arguments[c]);
+ } else if (type_arguments[c] == '>' || type_arguments[c] == ']') {
+ depth--;
+ current.append_unichar (type_arguments[c]);
+ } else if (type_arguments[c] == ',') {
+ if (depth == 0) {
+ var dt = parse_type_from_string (current.str, true, source_reference);
+ if (dt == null) {
+ return false;
+ }
+ parent_type.add_type_argument (dt);
+ current.truncate ();
+ } else {
+ current.append_unichar (type_arguments[c]);
+ }
+ } else {
+ current.append_unichar (type_arguments[c]);
+ }
+ }
+
+ var dt = parse_type_from_string (current.str, true, source_reference);
+ if (dt == null) {
+ return false;
+ }
+ parent_type.add_type_argument (dt);
+
+ return true;
+ }
+
+ DataType? parse_type_from_string (string type_string, bool owned_by_default, SourceReference? source_reference = null) {
+ if (type_from_string_regex == null) {
+ try {
+ type_from_string_regex = new GLib.Regex ("^(?:(owned|unowned|weak) +)?([0-9a-zA-Z_\\.]+)(?:<(.+)>)?(\\*+)?(\\[(,*)?\\])?(\\?)?$", GLib.RegexCompileFlags.ANCHORED | GLib.RegexCompileFlags.DOLLAR_ENDONLY | GLib.RegexCompileFlags.OPTIMIZE);
+ } catch (GLib.RegexError e) {
+ GLib.error ("Unable to compile regex: %s", e.message);
+ }
+ }
+
+ GLib.MatchInfo match;
+ if (!type_from_string_regex.match (type_string, 0, out match)) {
+ Report.error (source_reference, "unable to parse type");
+ return null;
+ }
+
+ DataType? type = null;
+
+ var ownership_data = match.fetch (1);
+ var type_name = match.fetch (2);
+ var type_arguments_data = match.fetch (3);
+ var pointers_data = match.fetch (4);
+ var array_data = match.fetch (5);
+ var nullable_data = match.fetch (6);
+
+ var nullable = nullable_data != null && nullable_data.length > 0;
+
+ if (ownership_data == null && type_name == "void") {
+ if (array_data == null && !nullable) {
+ type = new VoidType (source_reference);
+ if (pointers_data != null) {
+ for (int i=0; i < pointers_data.length; i++) {
+ type = new PointerType (type);
+ }
+ }
+ return type;
+ } else {
+ Report.error (source_reference, "invalid void type");
+ return null;
+ }
+ }
+
+ bool value_owned = owned_by_default;
+
+ if (ownership_data == "owned") {
+ if (owned_by_default) {
+ Report.error (source_reference, "unexpected `owned' keyword");
+ } else {
+ value_owned = true;
+ }
+ } else if (ownership_data == "unowned") {
+ if (owned_by_default) {
+ value_owned = true;
+ } else {
+ Report.error (source_reference, "unexpected `unowned' keyword");
+ return null;
+ }
+ }
+
+ var sym = parse_symbol_from_string (type_name, source_reference);
+ if (sym == null) {
+ return null;
+ }
+ type = new UnresolvedType.from_symbol (sym, source_reference);
+
+ if (type_arguments_data != null && type_arguments_data.length > 0) {
+ if (!parse_type_arguments_from_string (type, type_arguments_data, source_reference)) {
+ return null;
+ }
+ }
+
+ if (pointers_data != null) {
+ for (int i=0; i < pointers_data.length; i++) {
+ type = new PointerType (type);
+ }
+ }
+
+ if (array_data != null) {
+ type = new ArrayType (type, (int) array_data.length + 1, source_reference);
+ }
+
+ type.nullable = nullable;
+ type.value_owned = value_owned;
+ return type;
+ }
+
+ DataType? element_get_type (DataType orig_type, bool owned_by_default, out bool changed = null) {
+ if (&changed != null) {
+ changed = false;
+ }
+
+ var type = orig_type;
+
+ if (metadata.has_argument (ArgumentType.TYPE)) {
+ var new_type = parse_type_from_string (metadata.get_string (ArgumentType.TYPE), owned_by_default, metadata.get_source_reference (ArgumentType.TYPE));
+ if (&changed != null) {
+ changed = true;
+ }
+ return new_type;
+ }
+
+ if (metadata.has_argument (ArgumentType.TYPE_ARGUMENTS)) {
+ parse_type_arguments_from_string (type, metadata.get_string (ArgumentType.TYPE_ARGUMENTS), metadata.get_source_reference (ArgumentType.TYPE_ARGUMENTS));
+ if (&changed != null) {
+ changed = true;
+ }
+ }
+
+ if (type is VoidType) {
+ return type;
+ }
+
+ if (metadata.get_bool (ArgumentType.ARRAY)) {
+ type = new ArrayType (type, 1, type.source_reference);
+ if (&changed != null) {
+ changed = true;
+ }
+ }
+
+ if (owned_by_default) {
+ if (metadata.has_argument (ArgumentType.UNOWNED)) {
+ type.value_owned = !metadata.get_bool (ArgumentType.UNOWNED);
+ }
+ } else {
+ if (metadata.has_argument (ArgumentType.OWNED)) {
+ type.value_owned = metadata.get_bool (ArgumentType.OWNED);
+ }
+ }
+ if (metadata.has_argument (ArgumentType.NULLABLE)) {
+ type.nullable = metadata.get_bool (ArgumentType.NULLABLE);
+ }
+
+ return type;
+ }
+
void parse_repository () {
start_element ("repository");
if (reader.get_attribute ("version") != GIR_VERSION) {
@@ -1099,7 +1272,7 @@ public class Vala.GirParser : CodeVisitor {
var alias = new Alias ();
alias.source_reference = get_current_src ();
alias.name = reader.get_attribute ("name");
- alias.base_type = parse_type_from_name (reader.get_attribute ("target"));
+ alias.base_type = element_get_type (parse_type_from_gir_name (reader.get_attribute ("target")), true);
alias.parent_namespace = current_namespace;
next ();
end_element ("alias");
@@ -1314,7 +1487,15 @@ public class Vala.GirParser : CodeVisitor {
param = new Parameter.with_ellipsis (get_current_src ());
end_element ("varargs");
} else {
- var type = parse_type (null, out array_length_idx, transfer == "full");
+ string ctype;
+ var type = parse_type (out ctype, out array_length_idx, transfer == "full");
+ bool changed;
+ type = element_get_type (type, false, out changed);
+ if (!changed) {
+ // discard ctype, duplicated information
+ ctype = null;
+ }
+
if (transfer == "full" || transfer == "container" || destroy != null) {
type.value_owned = true;
}
@@ -1322,6 +1503,7 @@ public class Vala.GirParser : CodeVisitor {
type.nullable = true;
}
param = new Parameter (name, type, get_current_src ());
+ param.ctype = ctype;
if (direction == "out") {
param.direction = ParameterDirection.OUT;
} else if (direction == "inout") {
@@ -1368,7 +1550,7 @@ public class Vala.GirParser : CodeVisitor {
type_name = "GLib.GenericArray";
}
- DataType type = parse_type_from_name (type_name);
+ DataType type = parse_type_from_gir_name (type_name);
// type arguments / element types
while (current_token == MarkupTokenType.START_ELEMENT) {
@@ -1381,7 +1563,7 @@ public class Vala.GirParser : CodeVisitor {
return type;
}
- DataType parse_type_from_name (string type_name) {
+ DataType parse_type_from_gir_name (string type_name) {
DataType type;
if (type_name == "none") {
type = new VoidType (get_current_src ());
@@ -1523,7 +1705,7 @@ public class Vala.GirParser : CodeVisitor {
string parent = reader.get_attribute ("parent");
if (parent != null) {
- cl.add_base_type (parse_type_from_name (parent));
+ cl.add_base_type (parse_type_from_gir_name (parent));
}
next ();
@@ -1537,7 +1719,7 @@ public class Vala.GirParser : CodeVisitor {
if (reader.name == "implements") {
start_element ("implements");
- cl.add_base_type (parse_type_from_name (reader.get_attribute ("name")));
+ cl.add_base_type (parse_type_from_gir_name (reader.get_attribute ("name")));
next ();
end_element ("implements");
} else if (reader.name == "constant") {
@@ -1604,7 +1786,7 @@ public class Vala.GirParser : CodeVisitor {
if (reader.name == "prerequisite") {
start_element ("prerequisite");
- iface.add_prerequisite (parse_type_from_name (reader.get_attribute ("name")));
+ iface.add_prerequisite (parse_type_from_gir_name (reader.get_attribute ("name")));
next ();
end_element ("prerequisite");
} else if (reader.name == "field") {
@@ -1707,6 +1889,7 @@ public class Vala.GirParser : CodeVisitor {
string allow_none = reader.get_attribute ("allow-none");
next ();
var type = parse_type ();
+ type = element_get_type (type, true);
if (type is DelegateType && current_gtype_struct_for != null) {
// virtual
var callback_scope = new CallbackScope ();
@@ -1833,6 +2016,7 @@ public class Vala.GirParser : CodeVisitor {
} else {
return_type = new VoidType ();
}
+ return_type = element_get_type (return_type, true);
Symbol s;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]