eo: Add debug_name read-only property to ease debugging

This will include the following information, by default:
 - class name
 - whether the class is an override
 - eo id (pointer)
 - refcount
 - name if one was set (Efl.Object property)

This also supports classes, which is why it's an EAPI in eo.c
and not only a method of Efl.Object

This can be overriden by subclasses using the empty method
Efl.Object.debug_name_override.get

If the function is overriden, then the returned string is used
as is and so it is left to the subclass to include all the
necessary information (as above). This can easily be achieved
by calling efl_debug_name_get(efl_super()) and then concatenating
the strings.

Think of this function as something like Java's toString(), but
only for debugging (i.e. a string class should not just return
its string value).

@feature
This commit is contained in:
Jean-Philippe Andre 2017-07-14 15:57:36 +09:00
parent 0834511067
commit c4769ff898
5 changed files with 95 additions and 1 deletions

View File

@ -690,6 +690,23 @@ EAPI Eina_Bool efl_isa(const Eo *obj, const Efl_Class *klass);
*/
EAPI const char *efl_class_name_get(const Efl_Class *klass);
/**
* @brief Gets a debug name for this object
* @param obj_id The object (or class)
* @return A name to use in logs and for other debugging purposes
*
* Note that subclasses can override Efl.Object "debug_name_override" to
* provide more meaningful debug strings. The standard format includes the
* class name, the object ID (this @p obj_id), the reference count and
* optionally the object name (as defined by Efl.Object.name).
*
* This might return a temporary string, as created by eina_slstr, which means
* that a main loop should probably be running.
*
* @since 1.21
*/
EAPI const char *efl_debug_name_get(const Eo *obj_id);
/**
* @}
*/

View File

@ -81,6 +81,16 @@ abstract Efl.Object ()
comment: string @nullable; [[The comment]]
}
}
@property debug_name_override {
[[ A read-only name for this object used for debugging.
@since 1.21
]]
get {}
values {
name: string; [[A name including class name and object name.]]
}
}
@property event_global_freeze_count @class {
get {
[[Return freeze events of object.

View File

@ -2476,6 +2476,67 @@ err:
return EINA_FALSE;
}
EAPI const char *
efl_debug_name_get(const Eo *obj_id)
{
const char *override = "";
const char *name, *clsname, *ret;
if (!obj_id) return "(null)";
if (_eo_is_a_class(obj_id))
{
const char *clstype;
EO_CLASS_POINTER(obj_id, klass);
if (!klass || !klass->desc)
return eina_slstr_printf("Invalid_Class_ID(invalid)@%p", obj_id);
switch (klass->desc->type)
{
case EFL_CLASS_TYPE_REGULAR: clstype = "regular"; break;
case EFL_CLASS_TYPE_REGULAR_NO_INSTANT: clstype = "abstract"; break;
case EFL_CLASS_TYPE_INTERFACE: clstype = "interface"; break;
case EFL_CLASS_TYPE_MIXIN: clstype = "mixin"; break;
default: clstype = "invalid"; break;
}
return eina_slstr_printf("%s(%s)@%p", klass->desc->name, clstype, obj_id);
}
EO_OBJ_POINTER(obj_id, obj);
if (!obj) return eina_slstr_printf("Invalid_Object_ID@%p", obj_id);
if (!obj->cur_klass)
{
ret = efl_debug_name_override_get(obj_id);
if (ret) goto end;
}
else
{
if (obj->super)
ret = efl_debug_name_override_get(efl_super(obj_id, (Efl_Class *) obj->cur_klass->header.id));
else
ret = efl_debug_name_override_get(efl_cast(obj_id, (Efl_Class *) obj->cur_klass->header.id));
obj->super = EINA_FALSE;
obj->cur_klass = NULL;
if (ret) goto end;
}
name = efl_name_get(obj_id);
clsname = obj->klass->desc->name;
if (_obj_is_override(obj)) override = "(override)";
if (name)
ret = eina_slstr_printf("%s%s@%p[%d]:'%s'", clsname, override, obj_id, (int) obj->refcount, name);
else
ret = eina_slstr_printf("%s%s@%p[%d]", clsname, override, obj_id, (int) obj->refcount);
end:
EO_OBJ_DONE(obj_id);
return ret;
}
EAPI int
efl_callbacks_cmp(const Efl_Callback_Array_Item *a, const Efl_Callback_Array_Item *b)
{

View File

@ -572,6 +572,12 @@ _efl_object_comment_get(Eo *obj EINA_UNUSED, Efl_Object_Data *pd)
return pd->ext->comment;
}
EOLIAN static const char *
_efl_object_debug_name_override_get(Eo *obj_id EINA_UNUSED, Efl_Object_Data *pd EINA_UNUSED)
{
return NULL;
}
EOLIAN static void
_efl_object_del(const Eo *obj, Efl_Object_Data *pd EINA_UNUSED)
{

View File

@ -69,7 +69,7 @@ void _eo_pointer_error(const Eo *obj_id, const char *func_name, const char *file
#define EO_CLASS_POINTER(klass_id, klass) \
_Efl_Class *klass; \
do { \
klass = _eo_class_pointer_get(klass_id, __FUNCTION__, __FILE__, __LINE__); \
klass = _eo_class_pointer_get(klass_id); \
} while (0)
#define EO_CLASS_POINTER_PROXY(klass_id, klass) \