diff options
author | David Zeuthen <davidz@redhat.com> | 2009-05-15 21:06:39 -0400 |
---|---|---|
committer | David Zeuthen <davidz@redhat.com> | 2009-05-15 21:06:39 -0400 |
commit | bff070ee2be359d5555fdc29b98d5e8a31c85042 (patch) | |
tree | 2076f2702ac1c38296c3c8e1e12b133d1d2f7111 | |
parent | e4e6527f7ad3c486b23186c1ce53045664b28bb8 (diff) |
Add support for gtk-doc comments
-rw-r--r-- | src/Makefile.am | 53 | ||||
-rw-r--r-- | src/dbusidl.c | 949 | ||||
-rw-r--r-- | src/dbusidl.h | 74 | ||||
-rw-r--r-- | src/dbusidlprivate.h | 37 | ||||
-rw-r--r-- | src/idllexer.l | 62 | ||||
-rw-r--r-- | src/idlparser.y | 121 | ||||
-rw-r--r-- | src/org.freedesktop.DBus.Idl.Tests1.didl | 198 |
7 files changed, 1254 insertions, 240 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 5291751..3c8ae67 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -3,24 +3,6 @@ NULL = INCLUDES = -DDBUS_IDL_I_UNDERSTAND_THAT_API_IS_UNSTABLE -noinst_PROGRAMS = dbus-idl-test - -pkgconfigdir=$(libdir)/pkgconfig -pkgconfig_DATA = dbus-idl-1.pc - -dbus_idl_test_SOURCES = \ - test.c \ - $(NULL) - -dbus_idl_test_CFLAGS = \ - $(GLIB2_CFLAGS) \ - $(NULL) - -dbus_idl_test_LDADD = \ - $(GLIB2_LIBS) \ - libdbus-idl-1.la \ - $(NULL) - lib_LTLIBRARIES=libdbus-idl-1.la libdbus_idl_1_la_includedir = \ @@ -54,12 +36,47 @@ libdbus_idl_1_la_YFLAGS = -v -d # ---------------------------------------------------------------------------------------------------- +noinst_PROGRAMS = dbus-idl-test + +pkgconfigdir=$(libdir)/pkgconfig +pkgconfig_DATA = dbus-idl-1.pc + +dbus_idl_test_SOURCES = \ + test.c \ + $(NULL) + +dbus_idl_test_CFLAGS = \ + $(GLIB2_CFLAGS) \ + $(NULL) + +dbus_idl_test_LDADD = \ + $(GLIB2_LIBS) \ + libdbus-idl-1.la \ + $(NULL) + TESTS = dbus-idl-test EXTRA_DIST = org.freedesktop.DBus.Idl.Tests1.didl # ---------------------------------------------------------------------------------------------------- +bin_PROGRAMS = dbus-idl-to-docbook + +dbus_idl_to_docbook_SOURCES = \ + didl2docbook.c \ + $(NULL) + +dbus_idl_to_docbook_CFLAGS = \ + $(GLIB2_CFLAGS) \ + $(NULL) + +dbus_idl_to_docbook_LDADD = \ + $(GLIB2_LIBS) \ + libdbus-idl-1.la \ + $(NULL) + +# ---------------------------------------------------------------------------------------------------- + clean-local: rm -f *~ libdbus_idl_1_la-* diff --git a/src/dbusidl.c b/src/dbusidl.c index 947d486..e537ebf 100644 --- a/src/dbusidl.c +++ b/src/dbusidl.c @@ -21,12 +21,40 @@ #include "config.h" #include <string.h> +#include <ctype.h> #include "idl.h" #include "dbusidl.h" /* ---------------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------------- */ + +static const gchar * +di_base_type_to_string (DIBaseType type) +{ + const gchar *ret; + ret = NULL; + switch (type) + { + case DI_BASE_TYPE_METHOD: ret = "method"; break; + case DI_BASE_TYPE_SIGNAL: ret = "signal"; break; + case DI_BASE_TYPE_PROPERTY: ret = "property"; break; + case DI_BASE_TYPE_INTERFACE: ret = "interface"; break; + case DI_BASE_TYPE_STRUCT_MEMBER: ret = "struct_member"; break; + case DI_BASE_TYPE_STRUCT: ret = "struct"; break; + case DI_BASE_TYPE_DYNAMIC_STRUCT: ret = "dynamic_struct"; break; + case DI_BASE_TYPE_ENUM_MEMBER: ret = "enum_member"; break; + case DI_BASE_TYPE_ENUM: ret = "enum"; break; + case DI_BASE_TYPE_ERROR_MEMBER: ret = "error_member"; break; + case DI_BASE_TYPE_ERROR_DOMAIN: ret = "error_domain"; break; + case DI_BASE_TYPE_NAMESPACE: ret = "namespace"; break; + default: + g_assert_not_reached (); + break; + } + return ret; +} + /* ---------------------------------------------------------------------------------------------------- */ DIBaseType @@ -47,6 +75,70 @@ di_base_get_decl_lineno (DIBase *base) return base->decl_lineno; } +GList * +di_base_get_annotations (DIBase *base) +{ + return base->annotations; +} + +DIAnnotation * +di_base_get_annotation (DIBase *base, + const gchar *name) +{ + GList *l; + + for (l = base->annotations; l != NULL; l = l->next) + { + DIAnnotation *annotation = l->data; + if (g_strcmp0 (annotation->name, name) == 0) + return annotation; + } + return NULL; +} + +const gchar * +di_base_get_annotation_value (DIBase *base, + const gchar *name) +{ + DIAnnotation *annotation; + + annotation = di_base_get_annotation (base, name); + if (annotation == NULL) + return NULL; + else + return annotation->value; +} + +const gchar * +di_base_get_doc (DIBase *base) +{ + const gchar *doc; + const gchar *brief; + + doc = di_base_get_annotation_value (base, "Doc"); + brief = di_base_get_annotation_value (base, "DocBrief"); + + if (doc != NULL) + return doc; + else + return brief; +} + +const gchar * +di_base_get_doc_brief (DIBase *base) +{ + const gchar *doc; + const gchar *brief; + + doc = di_base_get_annotation_value (base, "Doc"); + brief = di_base_get_annotation_value (base, "DocBrief"); + + if (brief != NULL) + return brief; + else + return doc; +} + /* ---------------------------------------------------------------------------------------------------- */ /* getters */ @@ -126,12 +218,6 @@ di_arg_get_direction (DIArg *arg) return arg->direction; } -GList * -di_arg_get_annotations (DIArg *arg) -{ - return arg->annotations; -} - const gchar * di_method_get_name (DIMethod *method) @@ -139,16 +225,16 @@ di_method_get_name (DIMethod *method) return method->name; } -GList * -di_method_get_args (DIMethod *method) +const gchar * +di_method_get_fully_qualified_name (DIMethod *method) { - return method->args; + return method->fully_qualified_name; } GList * -di_method_get_annotations (DIMethod *method) +di_method_get_args (DIMethod *method) { - return method->annotations; + return method->args; } const gchar * @@ -170,16 +256,16 @@ di_signal_get_name (DISignal *signal) return signal->name; } -GList * -di_signal_get_args (DISignal *signal) +const gchar * +di_signal_get_fully_qualified_name (DISignal *signal) { - return signal->args; + return signal->fully_qualified_name; } GList * -di_signal_get_annotations (DISignal *signal) +di_signal_get_args (DISignal *signal) { - return signal->annotations; + return signal->args; } const gchar * @@ -195,16 +281,16 @@ di_property_get_name (DIProperty *property) return property->name; } -DIType * -di_property_get_type (DIProperty *property) +const gchar * +di_property_get_fully_qualified_name (DIProperty *property) { - return property->type; + return property->fully_qualified_name; } -GList * -di_property_get_annotations (DIProperty *property) +DIType * +di_property_get_type (DIProperty *property) { - return property->annotations; + return property->type; } const gchar * @@ -213,6 +299,12 @@ di_property_get_signature (DIProperty *property) return property->signature; } +DIPropertyFlags +di_property_get_flags (DIProperty *property) +{ + return property->flags; +} + const gchar * di_interface_get_name (DIInterface *interface) @@ -220,6 +312,12 @@ di_interface_get_name (DIInterface *interface) return interface->name; } +const gchar * +di_interface_get_fully_qualified_name (DIInterface *interface) +{ + return interface->fully_qualified_name; +} + GList * di_interface_get_methods (DIInterface *interface) { @@ -238,13 +336,6 @@ di_interface_get_properties (DIInterface *interface) return interface->properties; } -GList * -di_interface_get_annotations (DIInterface *interface) -{ - return interface->annotations; -} - - /* ---------------------------------------------------------------------------------------------------- */ const gchar * @@ -259,29 +350,22 @@ di_struct_member_get_type (DIStructMember *struct_member) return struct_member->type; } -GList * -di_struct_member_get_annotations (DIStructMember *struct_member) -{ - return struct_member->annotations; -} - - const gchar * di_struct_get_name (DIStruct *struct_) { return struct_->name; } -GList * -di_struct_get_members (DIStruct *struct_) +const gchar * +di_struct_get_fully_qualified_name (DIStruct *struct_) { - return struct_->members; + return struct_->fully_qualified_name; } GList * -di_struct_get_annotations (DIStruct *struct_) +di_struct_get_members (DIStruct *struct_) { - return struct_->annotations; + return struct_->members; } const gchar * @@ -297,16 +381,16 @@ di_dynamic_struct_get_name (DIDynamicStruct *dynamic_struct) return dynamic_struct->name; } -GList * -di_dynamic_struct_get_members (DIDynamicStruct *dynamic_struct) +const gchar * +di_dynamic_struct_get_fully_qualified_name (DIDynamicStruct *dynamic_struct) { - return dynamic_struct->members; + return dynamic_struct->fully_qualified_name; } GList * -di_dynamic_struct_get_annotations (DIDynamicStruct *dynamic_struct) +di_dynamic_struct_get_members (DIDynamicStruct *dynamic_struct) { - return dynamic_struct->annotations; + return dynamic_struct->members; } const gchar * @@ -323,6 +407,12 @@ di_enum_member_get_name (DIEnumMember *enum_member) return enum_member->name; } +const gchar * +di_enum_member_get_fully_qualified_name (DIEnumMember *enum_member) +{ + return enum_member->fully_qualified_name; +} + guint di_enum_member_get_value (DIEnumMember *enum_member) { @@ -335,32 +425,24 @@ di_enum_member_get_unset (DIEnumMember *enum_member) return enum_member->unset; } -GList * -di_enum_member_get_annotations (DIEnumMember *enum_member) -{ - return enum_member->annotations; -} - - const gchar * di_enum_get_name (DIEnum *enum_) { return enum_->name; } -GList * -di_enum_get_members (DIEnum *enum_) +const gchar * +di_enum_get_fully_qualified_name (DIEnum *enum_) { - return enum_->members; + return enum_->fully_qualified_name; } GList * -di_enum_get_annotations (DIEnum *enum_) +di_enum_get_members (DIEnum *enum_) { - return enum_->annotations; + return enum_->members; } - /* ---------------------------------------------------------------------------------------------------- */ const gchar * @@ -369,32 +451,30 @@ di_error_member_get_name (DIErrorMember *error_member) return error_member->name; } -GList * -di_error_member_get_annotations (DIErrorMember *error_member) +const gchar * +di_error_member_get_fully_qualified_name (DIErrorMember *error_member) { - return error_member->annotations; + return error_member->fully_qualified_name; } - const gchar * di_error_domain_get_name (DIErrorDomain *error_domain) { return error_domain->name; } -GList * -di_error_domain_get_members (DIErrorDomain *error_domain) +const gchar * +di_error_domain_get_fully_qualified_name (DIErrorDomain *error_domain) { - return error_domain->members; + return error_domain->fully_qualified_name; } GList * -di_error_domain_get_annotations (DIErrorDomain *error_domain) +di_error_domain_get_members (DIErrorDomain *error_domain) { - return error_domain->annotations; + return error_domain->members; } - /* ---------------------------------------------------------------------------------------------------- */ const gchar * @@ -433,12 +513,145 @@ di_namespace_get_error_domains (DINamespace *namespace) return namespace->error_domains; } +/* ---------------------------------------------------------------------------------------------------- */ + +const gchar * +di_comment_get_raw (DIComment *comment) +{ + return comment->raw; +} + +gboolean +di_comment_get_is_multiline (DIComment *comment) +{ + return comment->is_multiline; +} + +DIBase * +di_comment_get_base (DIComment *comment) +{ + return comment->link; +} + + +const gchar * +di_comment_get_symbol (DIComment *comment) +{ + const gchar *ret; + + ret = NULL; + + if (comment->link == NULL) + goto out; + + switch (di_base_get_type (comment->link)) + { + case DI_BASE_TYPE_METHOD: + ret = di_method_get_name ((DIMethod *) comment->link); + break; + case DI_BASE_TYPE_SIGNAL: + ret = di_signal_get_name ((DISignal *) comment->link); + break; + case DI_BASE_TYPE_PROPERTY: + ret = di_property_get_name ((DIProperty *) comment->link); + break; + case DI_BASE_TYPE_INTERFACE: + ret = di_interface_get_name ((DIInterface *) comment->link); + break; + case DI_BASE_TYPE_STRUCT: + ret = di_struct_get_name ((DIStruct *) comment->link); + break; + case DI_BASE_TYPE_DYNAMIC_STRUCT: + ret = di_dynamic_struct_get_name ((DIDynamicStruct *) comment->link); + break; + case DI_BASE_TYPE_ENUM: + ret = di_enum_get_name ((DIEnum *) comment->link); + break; + case DI_BASE_TYPE_ERROR_DOMAIN: + ret = di_error_domain_get_name ((DIErrorDomain *) comment->link); + break; + case DI_BASE_TYPE_NAMESPACE: + ret = di_namespace_get_name ((DINamespace *) comment->link); + break; + + default: + g_warning ("Cannot use gtkdoc-style comment on base %s", + di_base_type_to_string (comment->link->type)); + break; + } + + out: + return ret; +} + +const gchar * +di_comment_get_fully_qualified_symbol (DIComment *comment) +{ + const gchar *ret; + + ret = NULL; + + if (comment->link == NULL) + goto out; + + switch (di_base_get_type (comment->link)) + { + case DI_BASE_TYPE_METHOD: + ret = di_method_get_fully_qualified_name ((DIMethod *) comment->link); + break; + case DI_BASE_TYPE_SIGNAL: + ret = di_signal_get_fully_qualified_name ((DISignal *) comment->link); + break; + case DI_BASE_TYPE_PROPERTY: + ret = di_property_get_fully_qualified_name ((DIProperty *) comment->link); + break; + case DI_BASE_TYPE_INTERFACE: + ret = di_interface_get_fully_qualified_name ((DIInterface *) comment->link); + break; + case DI_BASE_TYPE_STRUCT: + ret = di_struct_get_fully_qualified_name ((DIStruct *) comment->link); + break; + case DI_BASE_TYPE_DYNAMIC_STRUCT: + ret = di_dynamic_struct_get_fully_qualified_name ((DIDynamicStruct *) comment->link); + break; + case DI_BASE_TYPE_ENUM: + ret = di_enum_get_fully_qualified_name ((DIEnum *) comment->link); + break; + case DI_BASE_TYPE_ERROR_DOMAIN: + ret = di_error_domain_get_fully_qualified_name ((DIErrorDomain *) comment->link); + break; + case DI_BASE_TYPE_NAMESPACE: + ret = di_namespace_get_name ((DINamespace *) comment->link); + break; + + default: + g_warning ("Cannot use gtkdoc-style comment on base %s", + di_base_type_to_string (comment->link->type)); + break; + } + + out: + return ret; +} + +const gchar * +di_comment_get_text (DIComment *comment) +{ + return comment->text; +} + GList * -di_namespace_get_annotations (DINamespace *namespace) +di_comment_get_tags (DIComment *comment) { - return namespace->annotations; + return comment->tags; } +const gchar * +di_comment_get_tag_value (DIComment *comment, + const gchar *tag) +{ + return g_hash_table_lookup (comment->hash_tag_to_value, tag); +} /* ---------------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------------- */ @@ -519,6 +732,11 @@ di_namespace_free (DINamespace *namespace) { } +void +di_comment_free (DIComment *comment) +{ +} + /* ---------------------------------------------------------------------------------------------------- */ DIAnnotation *di_annotation_new (gchar *decl_filename, @@ -568,7 +786,7 @@ di_arg_new (gchar *decl_filename, ret->name = name; ret->type = type; ret->direction = direction; - ret->annotations = annotations; + ret->base.annotations = annotations; return ret; } @@ -586,7 +804,7 @@ di_method_new (gchar *decl_filename, ret->base.decl_lineno = decl_lineno; ret->name = name; ret->args = args; - ret->annotations = annotations; + ret->base.annotations = annotations; return ret; } @@ -604,7 +822,7 @@ di_signal_new (gchar *decl_filename, ret->base.decl_lineno = decl_lineno; ret->name = name; ret->args = args; - ret->annotations = annotations; + ret->base.annotations = annotations; return ret; } @@ -624,7 +842,7 @@ di_property_new (gchar *decl_filename, ret->name = name; ret->type = type; ret->flags = flags; - ret->annotations = annotations; + ret->base.annotations = annotations; return ret; } @@ -646,7 +864,7 @@ di_interface_new (gchar *decl_filename, ret->methods = methods; ret->signals = signals; ret->properties = properties; - ret->annotations = annotations; + ret->base.annotations = annotations; return ret; } @@ -664,7 +882,7 @@ di_struct_member_new (gchar *decl_filename, ret->base.decl_lineno = decl_lineno; ret->name = name; ret->type = type; - ret->annotations = annotations; + ret->base.annotations = annotations; return ret; } @@ -682,7 +900,7 @@ di_struct_new (gchar *decl_filename, ret->base.decl_lineno = decl_lineno; ret->name = name; ret->members = members; - ret->annotations = annotations; + ret->base.annotations = annotations; return ret; } @@ -700,7 +918,7 @@ di_dynamic_struct_new (gchar *decl_filename, ret->base.decl_lineno = decl_lineno; ret->name = name; ret->members = members; - ret->annotations = annotations; + ret->base.annotations = annotations; return ret; } @@ -720,7 +938,7 @@ di_enum_member_new (gchar *decl_filename, ret->name = name; ret->value = value; ret->unset = unset; - ret->annotations = annotations; + ret->base.annotations = annotations; return ret; } @@ -738,7 +956,7 @@ di_enum_new (gchar *decl_filename, ret->base.decl_lineno = decl_lineno; ret->name = name; ret->members = members; - ret->annotations = annotations; + ret->base.annotations = annotations; return ret; } @@ -754,7 +972,7 @@ di_error_member_new (gchar *decl_filename, ret->base.decl_filename = decl_filename; ret->base.decl_lineno = decl_lineno; ret->name = name; - ret->annotations = annotations; + ret->base.annotations = annotations; return ret; } @@ -772,7 +990,7 @@ di_error_domain_new (gchar *decl_filename, ret->base.decl_lineno = decl_lineno; ret->name = name; ret->members = members; - ret->annotations = annotations; + ret->base.annotations = annotations; return ret; } @@ -798,10 +1016,114 @@ di_namespace_new (gchar *decl_filename, ret->dynamic_structs = dynamic_structs; ret->enums = enums; ret->error_domains = error_domains; - ret->annotations = annotations; + ret->base.annotations = annotations; return ret; } +DIComment * +di_comment_new (gchar *decl_filename, + guint decl_lineno, + gboolean is_multiline, + gchar *raw) +{ + DIComment *comment; + gchar *s; + gchar **lines; + guint n; + GString *text; + + comment = g_new0 (DIComment, 1); + comment->base.type = DI_BASE_TYPE_COMMENT; + comment->base.decl_filename = decl_filename; + comment->base.decl_lineno = decl_lineno; + comment->raw = raw; + comment->is_multiline = is_multiline; + comment->hash_tag_to_value = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + + text = g_string_new (NULL); + + /* Simple gtkdoc-style comment parser */ + + /* process one line at a time */ + lines = g_strsplit (comment->raw, "\n", 0); + for (n = 0; lines[n] != NULL; n++) + { + gchar *line = lines[n]; + gchar *tag; + gchar *tag_value; + + if (comment->is_multiline) + { + while (*line != '*' && *line != '\0') + line++; + if (*line == '\0') + continue; + line++; + } + + while (isspace (*line)) + line++; + if (*line == '\0') + continue; + + /* extract tag (TODO: handle tags spanning multiple lines) */ + tag = NULL; + tag_value = NULL; + if (g_str_has_prefix (line, "@")) + { + s = strchr (line, ':'); + if (s == NULL) + { + s = strchr (line, ' '); + if (s == NULL) + { + tag = g_strdup (line + 1); + } + else + { + tag = g_strndup (line + 1, s - line - 1); + } + } + else + { + tag = g_strndup (line + 1, s - line - 1); + s++; + while (isspace (*s)) + s++; + tag_value = g_strdup (s); + } + } + + if (tag != NULL) + { + //g_print ("tag '%s' -> '%s'\n", tag, tag_value); + /* hash table and tags list steals tag, tag_value */ + g_hash_table_insert (comment->hash_tag_to_value, + tag, + tag_value); + comment->tags = g_list_append (comment->tags, tag); + } + else + { + g_string_append (text, line); + g_string_append_c (text, '\n'); + //g_print ("line: '%s'\n", line); + } + } + g_strfreev (lines); + + comment->text = text->str; + g_string_free (text, FALSE); + + return comment; +} + +void +di_comment_set (DIComment *comment, + DIBase *link) +{ + comment->link = link; +} /* ---------------------------------------------------------------------------------------------------- */ @@ -835,11 +1157,20 @@ di_type_print (DIType *type, guint indent) } } +static void +di_base_print_annotations (DIBase *base, + guint indent) +{ + GList *l; + + for (l = base->annotations; l != NULL; l = l->next) + di_annotation_print ((DIAnnotation *) l->data, indent); +} + void di_arg_print (DIArg *arg, guint indent) { const gchar *direction; - GList *l; switch (arg->direction) { @@ -853,8 +1184,7 @@ di_arg_print (DIArg *arg, guint indent) direction = "OUT "; break; } - for (l = arg->annotations; l != NULL; l = l->next) - di_annotation_print ((DIAnnotation *) l->data, indent); + di_base_print_annotations ((DIBase *) arg, indent); g_print ("%*s%s", indent, "", direction); di_type_print (arg->type, 0); g_print (" %s", arg->name); @@ -868,13 +1198,12 @@ di_signal_print (DISignal *signal, guint indent) arg_indent = indent + 7 + strlen (signal->name) + 2; - for (l = signal->annotations; l != NULL; l = l->next) - di_annotation_print ((DIAnnotation *) l->data, indent); + di_base_print_annotations ((DIBase *) signal, indent); g_print ("%*s# signature=%s\n", indent, "", signal->signature); g_print ("%*ssignal %s (", indent, "", signal->name); for (l = signal->args; l != NULL; l = l->next) { - if (((DIArg *) l->data)->annotations != NULL) + if (((DIBase *) l->data)->annotations != NULL) di_arg_print (l->data, arg_indent); else di_arg_print (l->data, (l == signal->args ? 0 : arg_indent)); @@ -892,8 +1221,7 @@ di_method_print (DIMethod *method, guint indent) arg_indent = indent + 7 + strlen (method->name) + 2; - for (l = method->annotations; l != NULL; l = l->next) - di_annotation_print ((DIAnnotation *) l->data, indent); + di_base_print_annotations ((DIBase *) method, indent); g_print ("%*s# in_signature=%s out_signature=%s\n", indent, "", method->in_signature, @@ -902,7 +1230,7 @@ di_method_print (DIMethod *method, guint indent) method->name); for (l = method->args; l != NULL; l = l->next) { - if (((DIArg *) l->data)->annotations != NULL) + if (((DIBase *) l->data)->annotations != NULL) di_arg_print (l->data, arg_indent); else di_arg_print (l->data, (l == method->args ? 0 : arg_indent)); @@ -916,7 +1244,6 @@ void di_property_print (DIProperty *property, guint indent) { const gchar *flags_str; - GList *l; switch (property->flags) { @@ -933,8 +1260,7 @@ di_property_print (DIProperty *property, guint indent) g_assert_not_reached (); break; } - for (l = property->annotations; l != NULL; l = l->next) - di_annotation_print ((DIAnnotation *) l->data, indent); + di_base_print_annotations ((DIBase *) property, indent); g_print ("%*s# signature=%s\n", indent, "", property->signature); g_print ("%*s%s property ", indent, "", @@ -947,8 +1273,7 @@ void di_interface_print (DIInterface *interface, guint indent) { GList *l; - for (l = interface->annotations; l != NULL; l = l->next) - di_annotation_print ((DIAnnotation *) l->data, indent); + di_base_print_annotations ((DIBase *) interface, indent); g_print ("%*sinterface %s {\n", indent, "", interface->name); for (l = interface->methods; l != NULL; l = l->next) di_method_print (l->data, indent + 2); @@ -962,10 +1287,7 @@ di_interface_print (DIInterface *interface, guint indent) void di_struct_member_print (DIStructMember *struct_member, guint indent) { - GList *l; - - for (l = struct_member->annotations; l != NULL; l = l->next) - di_annotation_print ((DIAnnotation *) l->data, indent); + di_base_print_annotations ((DIBase *) struct_member, indent); g_print ("%*s", indent, ""); di_type_print (struct_member->type, 0); g_print (" %s;\n", struct_member->name); @@ -976,8 +1298,7 @@ di_struct_print (DIStruct *struct_, guint indent) { GList *l; - for (l = struct_->annotations; l != NULL; l = l->next) - di_annotation_print ((DIAnnotation *) l->data, indent); + di_base_print_annotations ((DIBase *) struct_, indent); g_print ("%*s# signature=%s\n", indent, "", struct_->signature); g_print ("%*sstruct %s {\n", indent, "", struct_->name); for (l = struct_->members; l != NULL; l = l->next) @@ -990,8 +1311,7 @@ di_dynamic_struct_print (DIDynamicStruct *dynamic_struct, guint indent) { GList *l; - for (l = dynamic_struct->annotations; l != NULL; l = l->next) - di_annotation_print ((DIAnnotation *) l->data, indent); + di_base_print_annotations ((DIBase *) dynamic_struct, indent); g_print ("%*sdynamic_struct %s {\n", indent, "", dynamic_struct->name); for (l = dynamic_struct->members; l != NULL; l = l->next) di_struct_member_print (l->data, indent + 2); @@ -1001,10 +1321,7 @@ di_dynamic_struct_print (DIDynamicStruct *dynamic_struct, guint indent) void di_enum_member_print (DIEnumMember *enum_member, guint indent) { - GList *l; - - for (l = enum_member->annotations; l != NULL; l = l->next) - di_annotation_print ((DIAnnotation *) l->data, indent); + di_base_print_annotations ((DIBase *) enum_member, indent); if (enum_member->unset) { g_print ("%*s%s = 0x%08x (unset),\n", indent, "", @@ -1024,8 +1341,7 @@ di_enum_print (DIEnum *enum_, guint indent) { GList *l; - for (l = enum_->annotations; l != NULL; l = l->next) - di_annotation_print ((DIAnnotation *) l->data, indent); + di_base_print_annotations ((DIBase *) enum_, indent); g_print ("%*senum %s {\n", indent, "", enum_->name); for (l = enum_->members; l != NULL; l = l->next) di_enum_member_print (l->data, indent + 2); @@ -1035,10 +1351,7 @@ di_enum_print (DIEnum *enum_, guint indent) void di_error_member_print (DIErrorMember *error_member, guint indent) { - GList *l; - - for (l = error_member->annotations; l != NULL; l = l->next) - di_annotation_print ((DIAnnotation *) l->data, indent); + di_base_print_annotations ((DIBase *) error_member, indent); g_print ("%*s%s,\n", indent, "", error_member->name); } @@ -1048,8 +1361,7 @@ di_error_domain_print (DIErrorDomain *error_domain, guint indent) { GList *l; - for (l = error_domain->annotations; l != NULL; l = l->next) - di_annotation_print ((DIAnnotation *) l->data, indent); + di_base_print_annotations ((DIBase *) error_domain, indent); g_print ("%*serror_domain %s {\n", indent, "", error_domain->name); for (l = error_domain->members; l != NULL; l = l->next) di_error_member_print (l->data, indent + 2); @@ -1061,8 +1373,7 @@ di_namespace_print (DINamespace *namespace, guint indent) { GList *l; - for (l = namespace->annotations; l != NULL; l = l->next) - di_annotation_print ((DIAnnotation *) l->data, indent); + di_base_print_annotations ((DIBase *) namespace, indent); g_print ("%*snamespace %s {\n", indent, "", namespace->name); for (l = namespace->structs; l != NULL; l = l->next) di_struct_print (l->data, indent + 2); @@ -1093,7 +1404,7 @@ ensure_method (DIParser *parser, if (g_strcmp0 (other->name, i->name) == 0) { parser->errors = g_list_append (parser->errors, - g_strdup_printf ("%s:%d: Method %s already has an argument named %s", + g_strdup_printf ("%s:%d: error: method %s already has an argument named %s", method->base.decl_filename, method->base.decl_lineno, method->name, @@ -1117,7 +1428,7 @@ ensure_signal (DIParser *parser, if (g_strcmp0 (other->name, i->name) == 0) { parser->errors = g_list_append (parser->errors, - g_strdup_printf ("%s:%d: Signal %s already has an argument named %s", + g_strdup_printf ("%s:%d: error: signal %s already has an argument named %s", signal->base.decl_filename, signal->base.decl_lineno, signal->name, @@ -1127,32 +1438,6 @@ ensure_signal (DIParser *parser, } } -static const gchar * -di_base_type_to_string (DIBaseType type) -{ - const gchar *ret; - ret = NULL; - switch (type) - { - case DI_BASE_TYPE_METHOD: ret = "method"; break; - case DI_BASE_TYPE_SIGNAL: ret = "signal"; break; - case DI_BASE_TYPE_PROPERTY: ret = "property"; break; - case DI_BASE_TYPE_INTERFACE: ret = "interface"; break; - case DI_BASE_TYPE_STRUCT_MEMBER: ret = "struct_member"; break; - case DI_BASE_TYPE_STRUCT: ret = "struct"; break; - case DI_BASE_TYPE_DYNAMIC_STRUCT: ret = "dynstruct"; break; - case DI_BASE_TYPE_ENUM_MEMBER: ret = "enum_member"; break; - case DI_BASE_TYPE_ENUM: ret = "enum"; break; - case DI_BASE_TYPE_ERROR_MEMBER: ret = "error_member"; break; - case DI_BASE_TYPE_ERROR_DOMAIN: ret = "error_domain"; break; - case DI_BASE_TYPE_NAMESPACE: ret = "namespace"; break; - default: - g_assert_not_reached (); - break; - } - return ret; -} - /* ---------------------------------------------------------------------------------------------------- */ static gboolean @@ -1640,6 +1925,347 @@ check_types (DIParser *parser) /* ---------------------------------------------------------------------------------------------------- */ +static void +inject_gtkdoc_style_comments (DIParser *parser) +{ + GList *l, *ll; + DIAnnotation *annotation; + const gchar *s; + + for (l = parser->comments; l != NULL; l = l->next) + { + DIComment *comment = l->data; + DIBase *base; + + base = di_comment_get_base (comment); + if (base == NULL) + continue; + + switch (di_base_get_type (base)) + { + case DI_BASE_TYPE_METHOD: + for (ll = di_method_get_args ((DIMethod *) base); ll != NULL; ll = ll->next) + { + DIArg *arg = ll->data; + s = di_comment_get_tag_value (comment, di_arg_get_name (arg)); + if (s != NULL) + { + annotation = di_annotation_new (comment->base.decl_filename, + comment->base.decl_lineno, + g_strdup ("Doc"), + g_strdup (s)); + ((DIBase *) arg)->annotations = g_list_append (((DIBase *) arg)->annotations, annotation); + } + } + break; + + case DI_BASE_TYPE_SIGNAL: + for (ll = di_signal_get_args ((DISignal *) base); ll != NULL; ll = ll->next) + { + DIArg *arg = ll->data; + s = di_comment_get_tag_value (comment, di_arg_get_name (arg)); + if (s != NULL) + { + annotation = di_annotation_new (comment->base.decl_filename, + comment->base.decl_lineno, + g_strdup ("Doc"), + g_strdup (s)); + ((DIBase *) arg)->annotations = g_list_append (((DIBase *) arg)->annotations, annotation); + } + } + break; + + case DI_BASE_TYPE_STRUCT: + for (ll = di_struct_get_members ((DIStruct *) base); ll != NULL; ll = ll->next) + { + DIStructMember *member = ll->data; + s = di_comment_get_tag_value (comment, di_struct_member_get_name (member)); + if (s != NULL) + { + annotation = di_annotation_new (comment->base.decl_filename, + comment->base.decl_lineno, + g_strdup ("Doc"), + g_strdup (s)); + ((DIBase *) member)->annotations = g_list_append (((DIBase *) member)->annotations, annotation); + } + } + break; + + case DI_BASE_TYPE_DYNAMIC_STRUCT: + for (ll = di_dynamic_struct_get_members ((DIDynamicStruct *) base); ll != NULL; ll = ll->next) + { + DIStructMember *member = ll->data; + s = di_comment_get_tag_value (comment, di_struct_member_get_name (member)); + if (s != NULL) + { + annotation = di_annotation_new (comment->base.decl_filename, + comment->base.decl_lineno, + g_strdup ("Doc"), + g_strdup (s)); + ((DIBase *) member)->annotations = g_list_append (((DIBase *) member)->annotations, annotation); + } + } + break; + + case DI_BASE_TYPE_ENUM: + for (ll = di_enum_get_members ((DIEnum *) base); ll != NULL; ll = ll->next) + { + DIEnumMember *member = ll->data; + s = di_comment_get_tag_value (comment, di_enum_member_get_name (member)); + if (s != NULL) + { + annotation = di_annotation_new (comment->base.decl_filename, + comment->base.decl_lineno, + g_strdup ("Doc"), + g_strdup (s)); + ((DIBase *) member)->annotations = g_list_append (((DIBase *) member)->annotations, annotation); + } + } + break; + + case DI_BASE_TYPE_ERROR_DOMAIN: + for (ll = di_error_domain_get_members ((DIErrorDomain *) base); ll != NULL; ll = ll->next) + { + DIErrorMember *member = ll->data; + s = di_comment_get_tag_value (comment, di_error_member_get_name (member)); + if (s != NULL) + { + annotation = di_annotation_new (comment->base.decl_filename, + comment->base.decl_lineno, + g_strdup ("Doc"), + g_strdup (s)); + ((DIBase *) member)->annotations = g_list_append (((DIBase *) member)->annotations, annotation); + } + } + break; + + case DI_BASE_TYPE_PROPERTY: + case DI_BASE_TYPE_INTERFACE: + case DI_BASE_TYPE_NAMESPACE: + /* do nothing */ + break; + + default: + g_warning ("Cannot use gtkdoc-style comment on base %s", + di_base_type_to_string (base->type)); + goto skip; + break; + } + + annotation = di_annotation_new (comment->base.decl_filename, + comment->base.decl_lineno, + g_strdup ("Doc"), + g_strdup (comment->text)); + base->annotations = g_list_append (base->annotations, annotation); + + s = di_comment_get_tag_value (comment, "brief"); + if (s != NULL) + { + annotation = di_annotation_new (comment->base.decl_filename, + comment->base.decl_lineno, + g_strdup ("DocBrief"), + g_strdup (s)); + base->annotations = g_list_append (base->annotations, annotation); + } + + skip: + ; + } + +} + +/* ---------------------------------------------------------------------------------------------------- */ + +static void +whine_about_missing_comments (DIParser *parser) +{ + GHashTableIter iter; + GList *l; + const gchar *fqn; + DIBase *base; + DIArg *arg; + DIMethod *method; + DISignal *signal; + DIProperty *property; + DIStruct *struct_; + DIDynamicStruct *dynamic_struct; + DIStructMember *struct_member; + DIErrorDomain *error_domain; + DIErrorMember *error_member; + DIEnum *enum_; + DIEnumMember *enum_member; + + g_hash_table_iter_init (&iter, parser->symbol_table); + while (g_hash_table_iter_next (&iter, (gpointer) &fqn, (gpointer) &base)) + { + switch (base->type) + { + case DI_BASE_TYPE_METHOD: + method = (DIMethod *) base; + if (di_base_get_annotation_value (base, "Doc") == NULL) + parser->warnings = g_list_append (parser->warnings, + g_strdup_printf ("%s:%d: warning: missing docs for method %s.", + base->decl_filename, base->decl_lineno, + method->name)); + for (l = method->args; l != NULL; l = l->next) + { + arg = l->data; + base = (DIBase *) arg; + if (di_base_get_annotation_value (base, "Doc") == NULL) + parser->warnings = g_list_append (parser->warnings, + g_strdup_printf ("%s:%d: warning: missing docs for method arg %s.", + base->decl_filename, base->decl_lineno, + arg->name)); + } + break; + + case DI_BASE_TYPE_SIGNAL: + signal = (DISignal *) base; + if (di_base_get_annotation_value (base, "Doc") == NULL) + parser->warnings = g_list_append (parser->warnings, + g_strdup_printf ("%s:%d: warning: missing docs for signal %s.", + base->decl_filename, base->decl_lineno, + signal->name)); + for (l = signal->args; l != NULL; l = l->next) + { + arg = l->data; + base = (DIBase *) arg; + if (di_base_get_annotation_value (base, "Doc") == NULL) + parser->warnings = g_list_append (parser->warnings, + g_strdup_printf ("%s:%d: warning: missing docs for signal arg %s.", + base->decl_filename, base->decl_lineno, + arg->name)); + } + break; + + case DI_BASE_TYPE_PROPERTY: + property = (DIProperty *) base; + if (di_base_get_annotation_value (base, "Doc") == NULL) + parser->warnings = g_list_append (parser->warnings, + g_strdup_printf ("%s:%d: warning: missing docs for property %s.", + base->decl_filename, base->decl_lineno, + property->name)); + break; + + case DI_BASE_TYPE_STRUCT: + struct_ = (DIStruct *) base; + if (di_base_get_annotation_value (base, "Doc") == NULL) + parser->warnings = g_list_append (parser->warnings, + g_strdup_printf ("%s:%d: warning: missing docs for struct %s.", + base->decl_filename, base->decl_lineno, + struct_->name)); + if (di_base_get_annotation_value (base, "DocBrief") == NULL) + parser->warnings = g_list_append (parser->warnings, + g_strdup_printf ("%s:%d: warning: missing brief docs for struct %s.", + base->decl_filename, base->decl_lineno, + struct_->name)); + for (l = struct_->members; l != NULL; l = l->next) + { + struct_member = (DIStructMember *) l->data; + base = (DIBase *) struct_member; + if (di_base_get_annotation_value (base, "Doc") == NULL) + parser->warnings = g_list_append (parser->warnings, + g_strdup_printf ("%s:%d: warning: missing docs for struct member %s.", + base->decl_filename, base->decl_lineno, + struct_member->name)); + } + break; + + case DI_BASE_TYPE_DYNAMIC_STRUCT: + dynamic_struct = (DIDynamicStruct *) base; + if (di_base_get_annotation_value (base, "Doc") == NULL) + parser->warnings = g_list_append (parser->warnings, + g_strdup_printf ("%s:%d: warning: missing docs for dynamic_struct %s.", + base->decl_filename, base->decl_lineno, + dynamic_struct->name)); + if (di_base_get_annotation_value (base, "DocBrief") == NULL) + parser->warnings = g_list_append (parser->warnings, + g_strdup_printf ("%s:%d: warning: missing brief docs for dynamic_struct %s.", + base->decl_filename, base->decl_lineno, + dynamic_struct->name)); + for (l = dynamic_struct->members; l != NULL; l = l->next) + { + struct_member = (DIStructMember *) l->data; + base = (DIBase *) struct_member; + if (di_base_get_annotation_value (base, "Doc") == NULL) + parser->warnings = g_list_append (parser->warnings, + g_strdup_printf ("%s:%d: warning: missing docs for dynamic_struct member %s.", + base->decl_filename, base->decl_lineno, + struct_member->name)); + } + break; + + case DI_BASE_TYPE_ERROR_DOMAIN: + error_domain = (DIErrorDomain *) base; + if (di_base_get_annotation_value (base, "Doc") == NULL) + parser->warnings = g_list_append (parser->warnings, + g_strdup_printf ("%s:%d: warning: missing docs for error_domain %s.", + base->decl_filename, base->decl_lineno, + error_domain->name)); + if (di_base_get_annotation_value (base, "DocBrief") == NULL) + parser->warnings = g_list_append (parser->warnings, + g_strdup_printf ("%s:%d: warning: missing brief docs for error_domain %s.", + base->decl_filename, base->decl_lineno, + error_domain->name)); + for (l = error_domain->members; l != NULL; l = l->next) + { + error_member = (DIErrorMember *) l->data; + base = (DIBase *) error_member; + if (di_base_get_annotation_value (base, "Doc") == NULL) + parser->warnings = g_list_append (parser->warnings, + g_strdup_printf ("%s:%d: warning: missing docs for error_domain member %s.", + base->decl_filename, base->decl_lineno, + error_member->name)); + } + break; + + case DI_BASE_TYPE_ENUM: + enum_ = (DIEnum *) base; + if (di_base_get_annotation_value (base, "Doc") == NULL) + parser->warnings = g_list_append (parser->warnings, + g_strdup_printf ("%s:%d: warning: missing docs for enum %s.", + base->decl_filename, base->decl_lineno, + enum_->name)); + if (di_base_get_annotation_value (base, "DocBrief") == NULL) + parser->warnings = g_list_append (parser->warnings, + g_strdup_printf ("%s:%d: warning: missing brief docs for enum %s.", + base->decl_filename, base->decl_lineno, + enum_->name)); + for (l = enum_->members; l != NULL; l = l->next) + { + enum_member = (DIEnumMember *) l->data; + base = (DIBase *) enum_member; + if (di_base_get_annotation_value (base, "Doc") == NULL) + parser->warnings = g_list_append (parser->warnings, + g_strdup_printf ("%s:%d: warning: missing docs for enum member %s.", + base->decl_filename, base->decl_lineno, + enum_member->name)); + } + break; + + case DI_BASE_TYPE_INTERFACE: + enum_ = (DIEnum *) base; + if (di_base_get_annotation_value (base, "Doc") == NULL) + parser->warnings = g_list_append (parser->warnings, + g_strdup_printf ("%s:%d: warning: missing docs for interface %s.", + base->decl_filename, base->decl_lineno, + enum_->name)); + if (di_base_get_annotation_value (base, "DocBrief") == NULL) + parser->warnings = g_list_append (parser->warnings, + g_strdup_printf ("%s:%d: warning: missing brief docs for interface %s.", + base->decl_filename, base->decl_lineno, + enum_->name)); + break; + + default: + /* ignore symbols where we don't expect docs */ + break; + } + } +} + +/* ---------------------------------------------------------------------------------------------------- */ + DIParser * di_parser_new (const gchar *path) { @@ -1703,6 +2329,12 @@ di_parser_new (const gchar *path) */ check_types (parser); + /* Inject gtkdoc-style docs from comments */ + inject_gtkdoc_style_comments (parser); + + /* Warn about missing comments */ + whine_about_missing_comments (parser); + out: return parser; } @@ -1714,6 +2346,27 @@ di_parser_get_namespaces (DIParser *parser) } GList * +di_parser_get_comments (DIParser *parser) +{ + return parser->comments; +} + +DIComment * +di_parser_lookup_comment_for_symbol (DIParser *parser, + const gchar *fully_qualified_name) +{ + GList *l; + for (l = parser->comments; l != NULL; l = l->next) + { + DIComment *comment = l->data; + + if (g_strcmp0 (di_comment_get_fully_qualified_symbol (comment), fully_qualified_name) == 0) + return comment; + } + return NULL; +} + +GList * di_parser_get_warnings (DIParser *parser) { return parser->warnings; diff --git a/src/dbusidl.h b/src/dbusidl.h index d1e45b2..bc21376 100644 --- a/src/dbusidl.h +++ b/src/dbusidl.h @@ -46,6 +46,7 @@ typedef enum DI_BASE_TYPE_ERROR_MEMBER, DI_BASE_TYPE_ERROR_DOMAIN, DI_BASE_TYPE_NAMESPACE, + DI_BASE_TYPE_COMMENT, } DIBaseType; typedef enum @@ -53,6 +54,7 @@ typedef enum DI_PROPERTY_FLAGS_NONE = 0, DI_PROPERTY_FLAGS_READABLE = (1<<0), DI_PROPERTY_FLAGS_WRITABLE = (1<<1), + DI_PROPERTY_FLAGS_READWRITE = DI_PROPERTY_FLAGS_READABLE|DI_PROPERTY_FLAGS_WRITABLE } DIPropertyFlags; typedef enum @@ -84,12 +86,20 @@ typedef struct _DIEnum DIEnum; typedef struct _DIErrorMember DIErrorMember; typedef struct _DIErrorDomain DIErrorDomain; typedef struct _DINamespace DINamespace; +typedef struct _DIComment DIComment; /* ---------------------------------------------------------------------------------------------------- */ -DIBaseType di_base_get_type (DIBase *base); -const gchar *di_base_get_decl_path (DIBase *base); -guint di_base_get_decl_lineno (DIBase *base); +DIBaseType di_base_get_type (DIBase *base); +const gchar *di_base_get_decl_path (DIBase *base); +guint di_base_get_decl_lineno (DIBase *base); +const gchar *di_base_get_doc (DIBase *base); +const gchar *di_base_get_doc_brief (DIBase *base); +GList *di_base_get_annotations (DIBase *base); +DIAnnotation *di_base_get_annotation (DIBase *base, + const gchar *name); +const gchar *di_base_get_annotation_value (DIBase *base, + const gchar *name); /* ---------------------------------------------------------------------------------------------------- */ @@ -103,14 +113,12 @@ GList *di_type_get_inner_types (DIType *type); const gchar *di_arg_get_name (DIArg *arg); DIType *di_arg_get_type (DIArg *arg); DIArgDirection di_arg_get_direction (DIArg *arg); -GList *di_arg_get_annotations (DIArg *arg); /* ---------------------------------------------------------------------------------------------------- */ const gchar *di_method_get_name (DIMethod *method); const gchar *di_method_get_fully_qualified_name (DIMethod *method); GList *di_method_get_args (DIMethod *method); -GList *di_method_get_annotations (DIMethod *method); const gchar *di_method_get_in_signature (DIMethod *method); const gchar *di_method_get_out_signature (DIMethod *method); @@ -119,16 +127,15 @@ const gchar *di_method_get_out_signature (DIMethod *method); const gchar *di_signal_get_name (DISignal *signal); const gchar *di_signal_get_fully_qualified_name (DISignal *signal); GList *di_signal_get_args (DISignal *signal); -GList *di_signal_get_annotations (DISignal *signal); const gchar *di_signal_get_signature (DISignal *signal); /* ---------------------------------------------------------------------------------------------------- */ -const gchar *di_property_get_name (DIProperty *property); -const gchar *di_property_get_fully_qualified_name (DIProperty *property); -DIType *di_property_get_type (DIProperty *property); -GList *di_property_get_annotations (DIProperty *property); -const gchar *di_property_get_signature (DIProperty *property); +const gchar *di_property_get_name (DIProperty *property); +const gchar *di_property_get_fully_qualified_name (DIProperty *property); +DIType *di_property_get_type (DIProperty *property); +const gchar *di_property_get_signature (DIProperty *property); +DIPropertyFlags di_property_get_flags (DIProperty *property); /* ---------------------------------------------------------------------------------------------------- */ @@ -137,7 +144,6 @@ const gchar *di_interface_get_fully_qualified_name (DIInterface *interface); GList *di_interface_get_methods (DIInterface *interface); GList *di_interface_get_signals (DIInterface *interface); GList *di_interface_get_properties (DIInterface *interface); -GList *di_interface_get_annotations (DIInterface *interface); DIMethod *di_interface_lookup_method (DIInterface *interface, const gchar *name); DISignal *di_interface_lookup_signal (DIInterface *interface, @@ -149,22 +155,19 @@ DIProperty *di_interface_lookup_property (DIInterface *interface, const gchar *di_struct_member_get_name (DIStructMember *struct_member); DIType *di_struct_member_get_type (DIStructMember *struct_member); -GList *di_struct_member_get_annotations (DIStructMember *struct_member); /* ---------------------------------------------------------------------------------------------------- */ const gchar *di_struct_get_name (DIStruct *struct_); const gchar *di_struct_get_fully_qualified_name (DIStruct *struct_); GList *di_struct_get_members (DIStruct *struct_); -GList *di_struct_get_annotations (DIStruct *struct_); const gchar *di_struct_get_signature (DIStruct *struct_); /* ---------------------------------------------------------------------------------------------------- */ const gchar *di_dynamic_struct_get_name (DIDynamicStruct *dynamic_struct); -const gchar *di_dynamic_get_fully_qualified_name (DIDynamicStruct *dynamic_struct); +const gchar *di_dynamic_struct_get_fully_qualified_name (DIDynamicStruct *dynamic_struct); GList *di_dynamic_struct_get_members (DIDynamicStruct *dynamic_struct); -GList *di_dynamic_struct_get_annotations (DIDynamicStruct *dynamic_struct); const gchar *di_dynamic_struct_get_signature (DIDynamicStruct *dynamic_struct); /* ---------------------------------------------------------------------------------------------------- */ @@ -173,27 +176,23 @@ const gchar *di_enum_member_get_name (DIEnumMember *enum_member const gchar *di_enum_member_get_fully_qualified_name (DIEnumMember *enum_member); guint di_enum_member_get_value (DIEnumMember *enum_member); gboolean di_enum_member_get_unset (DIEnumMember *enum_member); -GList *di_enum_member_get_annotations (DIEnumMember *enum_member); /* ---------------------------------------------------------------------------------------------------- */ const gchar *di_enum_get_name (DIEnum *enum_); const gchar *di_enum_get_fully_qualified_name (DIEnum *enum_); GList *di_enum_get_members (DIEnum *enum_); -GList *di_enum_get_annotations (DIEnum *enum_); /* ---------------------------------------------------------------------------------------------------- */ const gchar *di_error_member_get_name (DIErrorMember *error_member); const gchar *di_error_member_get_fully_qualified_name (DIErrorMember *error_member); -GList *di_error_member_get_annotations (DIErrorMember *error_member); /* ---------------------------------------------------------------------------------------------------- */ const gchar *di_error_domain_get_name (DIErrorDomain *error_domain); const gchar *di_error_domain_get_fully_qualified_name (DIErrorDomain *error_domain); GList *di_error_domain_get_members (DIErrorDomain *error_domain); -GList *di_error_domain_get_annotations (DIErrorDomain *error_domain); /* ---------------------------------------------------------------------------------------------------- */ @@ -203,7 +202,6 @@ GList *di_namespace_get_structs (DINamespace *namespace); GList *di_namespace_get_dynamic_structs (DINamespace *namespace); GList *di_namespace_get_enums (DINamespace *namespace); GList *di_namespace_get_error_domains (DINamespace *namespace); -GList *di_namespace_get_annotations (DINamespace *namespace); DIInterface *di_namespace_lookup_interface (DINamespace *namespace, const gchar *name); DIStruct *di_namespace_lookup_struct (DINamespace *namespace, @@ -217,15 +215,31 @@ DIErrorDomain *di_namespace_lookup_error_domain (DINamespace *namespace, /* ---------------------------------------------------------------------------------------------------- */ -DIParser *di_parser_new (const gchar *path); -GList *di_parser_get_namespaces (DIParser *parser); -DINamespace *di_parser_lookup_namespace (DIParser *parser, - const gchar *name); -DIBase *di_parser_lookup_symbol (DIParser *parser, - const gchar *fully_qualified_name); -GList *di_parser_get_warnings (DIParser *parser); -GList *di_parser_get_errors (DIParser *parser); -void di_parser_free (DIParser *parser); +const gchar *di_comment_get_raw (DIComment *comment); +gboolean di_comment_get_is_multiline (DIComment *comment); +const gchar *di_comment_get_symbol (DIComment *comment); +const gchar *di_comment_get_fully_qualified_symbol (DIComment *comment); +DIBase *di_comment_get_base (DIComment *comment); +const gchar *di_comment_get_brief (DIComment *comment); +const gchar *di_comment_get_text (DIComment *comment); +GList *di_comment_get_tags (DIComment *comment); +const gchar *di_comment_get_tag_value (DIComment *comment, + const gchar *tag); + +/* ---------------------------------------------------------------------------------------------------- */ + +DIParser *di_parser_new (const gchar *path); +GList *di_parser_get_namespaces (DIParser *parser); +GList *di_parser_get_comments (DIParser *parser); +DINamespace *di_parser_lookup_namespace (DIParser *parser, + const gchar *name); +DIBase *di_parser_lookup_symbol (DIParser *parser, + const gchar *fully_qualified_name); +DIComment *di_parser_lookup_comment_for_symbol (DIParser *parser, + const gchar *fully_qualified_name); +GList *di_parser_get_warnings (DIParser *parser); +GList *di_parser_get_errors (DIParser *parser); +void di_parser_free (DIParser *parser); /* ---------------------------------------------------------------------------------------------------- */ diff --git a/src/dbusidlprivate.h b/src/dbusidlprivate.h index 4f0b9ec..20477da 100644 --- a/src/dbusidlprivate.h +++ b/src/dbusidlprivate.h @@ -30,6 +30,7 @@ struct _DIBase DIBaseType type; gchar *decl_filename; guint decl_lineno; + GList *annotations; }; struct _DIAnnotation @@ -57,7 +58,6 @@ struct _DIArg gchar *name; DIType *type; DIArgDirection direction; - GList *annotations; }; struct _DIMethod @@ -66,7 +66,6 @@ struct _DIMethod gchar *name; gchar *fully_qualified_name; GList *args; - GList *annotations; gchar *in_signature; gchar *out_signature; @@ -78,7 +77,6 @@ struct _DISignal gchar *name; gchar *fully_qualified_name; GList *args; - GList *annotations; gchar *signature; }; @@ -90,7 +88,6 @@ struct _DIProperty gchar *fully_qualified_name; DIType *type; DIPropertyFlags flags; - GList *annotations; gchar *signature; }; @@ -103,7 +100,6 @@ struct _DIInterface GList *methods; GList *signals; GList *properties; - GList *annotations; }; struct _DIStructMember @@ -111,7 +107,6 @@ struct _DIStructMember DIBase base; gchar *name; DIType *type; - GList *annotations; }; struct _DIStruct @@ -120,7 +115,6 @@ struct _DIStruct gchar *name; gchar *fully_qualified_name; GList *members; - GList *annotations; gchar *signature; }; @@ -131,7 +125,6 @@ struct _DIDynamicStruct gchar *name; gchar *fully_qualified_name; GList *members; - GList *annotations; }; struct _DIEnumMember @@ -141,7 +134,6 @@ struct _DIEnumMember gchar *fully_qualified_name; guint32 value; gboolean unset; - GList *annotations; }; struct _DIEnum @@ -150,7 +142,6 @@ struct _DIEnum gchar *name; gchar *fully_qualified_name; GList *members; - GList *annotations; }; struct _DIErrorMember @@ -158,7 +149,6 @@ struct _DIErrorMember DIBase base; gchar *name; gchar *fully_qualified_name; - GList *annotations; }; struct _DIErrorDomain @@ -167,7 +157,6 @@ struct _DIErrorDomain gchar *name; gchar *fully_qualified_name; GList *members; - GList *annotations; }; struct _DINamespace @@ -179,8 +168,19 @@ struct _DINamespace GList *dynamic_structs; GList *enums; GList *error_domains; +}; - GList *annotations; +struct _DIComment +{ + DIBase base; + gboolean is_multiline; + gchar *raw; + gchar *text; + GList *tags; + GHashTable *hash_tag_to_value; + + /* the symbol the comment is for */ + DIBase *link; }; struct _DIParser @@ -189,6 +189,7 @@ struct _DIParser GList *namespaces; GList *warnings; GList *errors; + GList *comments; /* hash from fully-qualified name to DIBase* */ GHashTable *symbol_table; @@ -277,6 +278,14 @@ DINamespace *di_namespace_new (gchar *decl_filename, GList *enums, GList *error_domains, GList *annotations); +DIComment *di_comment_new (gchar *decl_filename, + guint decl_lineno, + gboolean is_multiline, + gchar *raw); + +void di_comment_set (DIComment *comment, + DIBase *link); + /* ---------------------------------------------------------------------------------------------------- */ @@ -295,6 +304,7 @@ void di_enum_free (DIEnum *enum_); void di_error_member_free (DIErrorMember *error_member); void di_error_domain_free (DIErrorDomain *error_domain); void di_namespace_free (DINamespace *namespace); +void di_comment_free (DIComment *comment); /* ---------------------------------------------------------------------------------------------------- */ @@ -313,6 +323,7 @@ void di_enum_print (DIEnum *enum_, guint indent); void di_error_member_print (DIErrorMember *error_member, guint indent); void di_error_domain_print (DIErrorDomain *error_domain, guint indent); void di_namespace_print (DINamespace *namespace, guint indent); +void di_comment_print (DIComment *comment, guint indent); /* ---------------------------------------------------------------------------------------------------- */ diff --git a/src/idllexer.l b/src/idllexer.l index e54c7a7..5bbb886 100644 --- a/src/idllexer.l +++ b/src/idllexer.l @@ -24,9 +24,14 @@ #include <stdio.h> #include <glib.h> #include "libdbus_idl_1_la-idlparser.h" +#include "idl.h" + +extern int yylex (DIParser *parser); +#define YY_DECL int yylex (DIParser *parser) + +static DIComment *parse_comment (DIParser *parser); +static DIComment *parse_eol_comment (DIParser *parser); -static void parse_comment (void); -static void parse_eol_comment (void); static gchar *unescape_string (const gchar *str); %} @@ -36,8 +41,10 @@ stringtext ([^\\\"])|(\\.) %% -"//" { parse_eol_comment (); yylineno++; } -"/*" { parse_comment (); } +"/**" {yylval.comment = parse_comment (parser); return DOC_COMMENT;} +"///" {yylval.comment = parse_eol_comment (parser); yylineno++; return DOC_COMMENT;} +"/*" {parse_comment (parser);} +"//" {parse_eol_comment (parser); yylineno++;} "namespace" {return NAMESPACE;} "interface" {return INTERFACE;} "signal" {return SIGNAL;} @@ -92,9 +99,10 @@ stringtext ([^\\\"])|(\\.) %% -static void -parse_comment (void) +static DIComment * +parse_comment (DIParser *parser) { + DIComment *c; GString *comment; int c1, c2; @@ -113,27 +121,45 @@ parse_comment (void) c1 = c2; c2 = input(); } - /* TODO: use comment */ - g_string_free (comment, TRUE); -} + c = di_comment_new (g_strdup (parser->path_to_current_file), + yylineno, + TRUE, + comment->str); + + parser->comments = g_list_append (parser->comments, c); + + g_string_free (comment, FALSE); + + return c; +} -static void -parse_eol_comment (void) +static DIComment * +parse_eol_comment (DIParser *parser) { GString *comment; - int c; + DIComment *c; + int c1; - c = input(); + c1 = input(); comment = g_string_new (""); - while (c != EOF && c != '\r' && c != '\n') + while (c1 != EOF && c1 != '\r' && c1 != '\n') { - g_string_append_c (comment, c); - c = input (); + g_string_append_c (comment, c1); + c1 = input (); } - /* TODO: use comment */ - g_string_free (comment, TRUE); + + c = di_comment_new (g_strdup (parser->path_to_current_file), + yylineno, + FALSE, + comment->str); + + parser->comments = g_list_append (parser->comments, c); + + g_string_free (comment, FALSE); + + return c; } static gchar * diff --git a/src/idlparser.y b/src/idlparser.y index e141575..223633d 100644 --- a/src/idlparser.y +++ b/src/idlparser.y @@ -57,6 +57,7 @@ int yywrap (void) gchar *str; guint32 number; gint direction; + struct _DIComment *comment; struct _DIType *type; struct _DIArg *arg; struct _DIMethod *method; @@ -108,24 +109,32 @@ int yywrap (void) %type <arg> signal_arg %type <method> method +%type <method> method2 %type <signal> signal +%type <signal> signal2 %type <interface> iface_decl +%type <interface> iface_decl2 %type <arg_list> method_arg_list %type <arg_list> signal_arg_list %type <property> property +%type <property> property2 %type <property_flags> property_flags %type <dynamic_struct> dynamic_struct_decl +%type <dynamic_struct> dynamic_struct_decl2 %type <struct_> struct_decl +%type <struct_> struct_decl2 %type <struct_member> struct_member %type <struct_body> struct_body %type <error_domain> error_domain_decl +%type <error_domain> error_domain_decl2 %type <error_member> error_member %type <error_body> error_body %type <enum_> enum_decl +%type <enum_> enum_decl2 %type <enum_member> enum_member %type <enum_body> enum_body @@ -150,16 +159,17 @@ file: ns_decl : annotation_list NAMESPACE dbus_name OBRACE ns_decls EBRACE SEMICOLON { - parser->namespaces = g_list_append (parser->namespaces, - di_namespace_new (g_strdup (parser->path_to_current_file), - yylineno, - $3, - $5.interfaces, - $5.structs, - $5.dynamic_structs, - $5.enums, - $5.error_domains, - $1)); + DINamespace *namespace; + namespace = di_namespace_new (g_strdup (parser->path_to_current_file), + yylineno, + $3, + $5.interfaces, + $5.structs, + $5.dynamic_structs, + $5.enums, + $5.error_domains, + $1); + parser->namespaces = g_list_append (parser->namespaces, namespace); $5.interfaces = NULL; $5.dynamic_structs = NULL; $5.structs = NULL; @@ -249,6 +259,18 @@ dbus_name /* ---------------------------------------------------------------------------------------------------- */ error_domain_decl + : error_domain_decl2 + { + $$ = $1; + } + | DOC_COMMENT error_domain_decl2 + { + di_comment_set ($1, (DIBase *) $2); + $$ = $2; + } + + +error_domain_decl2 : annotation_list ERROR_DOMAIN IDENTIFIER OBRACE error_body EBRACE SEMICOLON { $$ = di_error_domain_new (g_strdup (parser->path_to_current_file), @@ -283,6 +305,17 @@ error_member /* ---------------------------------------------------------------------------------------------------- */ enum_decl + : enum_decl2 + { + $$ = $1; + } + | DOC_COMMENT enum_decl2 + { + di_comment_set ($1, (DIBase *) $2); + $$ = $2; + } + +enum_decl2 : annotation_list ENUM IDENTIFIER OBRACE enum_body EBRACE SEMICOLON { $$ = di_enum_new (g_strdup (parser->path_to_current_file), @@ -381,6 +414,17 @@ numberexpr /* ---------------------------------------------------------------------------------------------------- */ dynamic_struct_decl + : dynamic_struct_decl2 + { + $$ = $1; + } + | DOC_COMMENT dynamic_struct_decl2 + { + di_comment_set ($1, (DIBase *) $2); + $$ = $2; + } + +dynamic_struct_decl2 : annotation_list DYNAMIC_STRUCT IDENTIFIER OBRACE struct_body EBRACE SEMICOLON { $$ = di_dynamic_struct_new (g_strdup (parser->path_to_current_file), @@ -394,6 +438,17 @@ dynamic_struct_decl /* ---------------------------------------------------------------------------------------------------- */ struct_decl + : struct_decl2 + { + $$ = $1; + } + | DOC_COMMENT struct_decl2 + { + di_comment_set ($1, (DIBase *) $2); + $$ = $2; + } + +struct_decl2 : annotation_list STRUCT IDENTIFIER OBRACE struct_body EBRACE SEMICOLON { $$ = di_struct_new (g_strdup (parser->path_to_current_file), @@ -429,6 +484,17 @@ struct_member /* ---------------------------------------------------------------------------------------------------- */ iface_decl + : iface_decl2 + { + $$ = $1; + } + | DOC_COMMENT iface_decl2 + { + di_comment_set ($1, (DIBase *) $2); + $$ = $2; + } + +iface_decl2 : annotation_list INTERFACE IDENTIFIER OBRACE iface_body EBRACE SEMICOLON { $$ = di_interface_new (g_strdup (parser->path_to_current_file), @@ -474,6 +540,17 @@ iface_body /* ---------------------------------------------------------------------------------------------------- */ signal + : signal2 + { + $$ = $1; + } + | DOC_COMMENT signal2 + { + di_comment_set ($1, (DIBase *) $2); + $$ = $2; + } + +signal2 : annotation_list SIGNAL IDENTIFIER OPAREN signal_arg_list EPAREN SEMICOLON { $$ = di_signal_new (g_strdup (parser->path_to_current_file), @@ -514,6 +591,17 @@ signal_arg /* ---------------------------------------------------------------------------------------------------- */ method + : method2 + { + $$ = $1; + } + | DOC_COMMENT method2 + { + di_comment_set ($1, (DIBase *) $2); + $$ = $2; + } + +method2 : annotation_list IDENTIFIER OPAREN method_arg_list EPAREN SEMICOLON { $$ = di_method_new (g_strdup (parser->path_to_current_file), @@ -565,6 +653,17 @@ direction /* ---------------------------------------------------------------------------------------------------- */ property + : property2 + { + $$ = $1; + } + | DOC_COMMENT property2 + { + di_comment_set ($1, (DIBase *) $2); + $$ = $2; + } + +property2 : annotation_list property_flags PROPERTY type IDENTIFIER SEMICOLON { $$ = di_property_new (g_strdup (parser->path_to_current_file), @@ -778,6 +877,8 @@ basic_type %token <number> NUMBER; %token <str> STRING; +%token <comment> DOC_COMMENT; + // braces / parens etc %token OBRACE EBRACE OPAREN EPAREN OBRACKET EBRACKET SEMICOLON COMMA DOT EQUAL ATSIGN; diff --git a/src/org.freedesktop.DBus.Idl.Tests1.didl b/src/org.freedesktop.DBus.Idl.Tests1.didl index e506fd7..c630bb9 100644 --- a/src/org.freedesktop.DBus.Idl.Tests1.didl +++ b/src/org.freedesktop.DBus.Idl.Tests1.didl @@ -1,8 +1,48 @@ -// -*- idl -*- - @Version("1.5") namespace org.freedesktop.DBus.Idl.Tests1 { + /** + * @Failed: The operation failed. + * @Busy: The operation cannot be performed because the flux capicator is busy. + * @Cancelled: The operation was cancelled. + * @WouldBlock: The operation would block and non-blocking semantics was requested. + * + * An example of an error domain. + * + * @brief: Error domain + */ + error_domain Error + { + Failed, + Busy, + Cancelled, + WouldBlock + }; + + // An example of manual doc tags. + + @Doc("Another Error Domain.") + @DocBrief("Another Error Domain") + error_domain Error2 + { + @Doc("Parsing failed.") + ParsingFailed, + @Doc("Foo operation failed.") + FooFailed + }; + + /** + * An example struct. + * @bar: First member. + * @baz: Second member. + * @something: Third member. + * @lots_of_something: An array of #Variant<!-- -->s. + * @property_bag: A property bag. + * + * A longer explanation of the example struct. + * + * @brief: An example struct + */ struct Struct1 { int32 bar; @@ -12,6 +52,19 @@ namespace org.freedesktop.DBus.Idl.Tests1 dict<string,variant> property_bag; }; + /** + * @a: Blah. + * @b: Baz. + * @c: Dah. + * @d: Frob. + * @stuff: Stuff. + * @foo: Foo. + * + * Some dynamic structure - this is marshalled as + * <literal>a{sv}</literal> on the wire. + * + * @brief: A Dynamic Struct + */ dynamic_struct Struct2 { uint64 a; @@ -19,8 +72,29 @@ namespace org.freedesktop.DBus.Idl.Tests1 uint64 c; string d; array<string> stuff; + Struct1 foo; }; + /** + * @Foo: Some value. + * @Bar: Some value. + * @Baz: Some value. + * @BigFoo: Some value. + * @BigBar: Some value. + * @BigBaz: Some value. + * @A: Some value. + * @B: Some value. + * @C: Some value. + * @D: Some value. + * @E: Some value. + * @F: Some value. + * @G: Some value. + * @H: Some value. + * + * An enumeration. + * + * @brief: Brief docs for enum + */ enum Enum1 { Foo, @@ -39,6 +113,16 @@ namespace org.freedesktop.DBus.Idl.Tests1 H = 1<<5 + 10 }; + /** + * @None: No flags set. + * @AllowReplacement: Allow replacement of bla. + * @Replace: Replace exisiting bla. + * @Activate: Activate the Yoyo. + * + * Flags used in the EnumMethod() method. + * + * @brief: Flags used for EnumMethod() + */ @Flags enum Enum2 { @@ -48,22 +132,79 @@ namespace org.freedesktop.DBus.Idl.Tests1 Activate = 1<<2 }; + /** + * @x: The X coordinate. + * @y: The Y coordinate. + * + * A data type representing coordinates in a two-dimensional + * Cartesian coordinate system using integers. + * + * See + * <ulink url="http://en.wikipedia.org/wiki/Cartesian_coordinate_system"> + * <citetitle>this Wikipedia article</citetitle> + * </ulink> + * for more information. + * + * @brief: Fixed-point 2D coordinate + * @see: #RealPoint + */ struct Point { int32 x; int32 y; }; + /** + * @x: The X coordinate. + * @y: The Y coordinate. + * + * A data type representing coordinates in a two-dimensional + * Cartesian coordinate system using floating point numbers. + * + * @brief: 2D coordinate + */ + struct RealPoint + { + double x; + double y; + }; + + @Doc("A data type holding a pair of 32-bit integers.") + @DocBrief("Pair of integers") struct Pair { + @Doc("First element in pair.") int32 first; + @Doc("Second element in pair.") int32 second; }; + /** + * Here is a longer description of the #Frobnicable interface. + * + * @brief: An interface for frobbing + */ interface Frobnicable { + /// Method doing nothing VoidMethod (); + /** + * @a1: A parameter. + * @a2: A parameter. + * @a3: A parameter. + * @a4: A parameter. + * @a5: A parameter. + * @a6: A parameter. + * @a7: A parameter. + * @a8: A parameter. + * @a9: A parameter. + * @a10: A parameter. + * @a11: A parameter. + * @a12: A parameter. + * + * Method taking primitive types. + */ PrimitiveMethod (in byte a1, in boolean a2, in int16 a3, @@ -77,13 +218,33 @@ namespace org.freedesktop.DBus.Idl.Tests1 in objpath a11, in signature a12); + /** + * @a1: An array of #int32<!-- -->s. + * @a2: An array of #string<!-- -->s. + * @a3: An array of an array of #int32. + * @a4: A hash from #int32 to #int32. + * @a5: Some weird Hash Table. + * + * This tests various container stuff. + */ @NoReply ContainerMethod (in array<int32> a1, in array<string> a2, in array<array<int32>> a3, in dict<int32,int32> a4, - in dict<string,dict<array<string>,string>> a5); + in dict<string,dict<string,array<string>>> a5); + /** + * @a1: A parameter. + * @a2: A parameter. + * @a3: A parameter. + * @a4: A parameter. + * @a5: A parameter. + * @a6: A parameter. + * @a7: A parameter. + * + * Method for test various structs. + */ @Deprecated StructsMethod (in Struct1 a1, in array<Struct1> a2, @@ -93,23 +254,54 @@ namespace org.freedesktop.DBus.Idl.Tests1 out array<Struct2> a6, out dict<string,Struct2> a7); + /** + * @a1: A parameter. + * @a2: A parameter. + * + * Method for testing enum stuff. + */ @Since("1.3") EnumMethod (in Enum1 a1, out Enum2 a2); + /// Signal doing nothing @Deprecated("1.2") signal VoidSignal(); + /** + * @points: An array of #Point<!-- -->s. + * @pairs: An array of #Pairs<!-- -->s. + * + * A signal with some points and pairs. + */ signal ArgSignal (array<Point> points, array<Pair> pairs); + /// This is a property that is both readable and writable. property int32 RWProperty; + + /// This is a read-only property. readonly property int32 ROProperty; + + /// And a write-only property. writeonly property int32 WOProperty; + /** + * A rather complex property. + */ property dict<string,array<Point>> ComplexProperty; }; + /** + * This is an example of another interface. + * + * @brief: Another interface + */ interface SecondaryProtocol { + /** + * @foo: Secret parameter. + * + * This method is secret. Shh! + */ SecretMethod (in int32 foo); }; |