efl: add code to enforce presence of @since tags

This is not yet enabled because there's too many instances where
this is broken.

Ref T7704
This commit is contained in:
Daniel Kolesa 2019-09-30 19:45:45 +02:00
parent 835e230f2f
commit 71c83d2005
14 changed files with 192 additions and 24 deletions

View File

@ -24,7 +24,10 @@ enum @beta Efl.Gfx.Colorspace {
} }
enum Efl.Gfx.Render_Op { enum Efl.Gfx.Render_Op {
[[Graphics render operation mode]] [[Graphics render operation mode
@since 1.23
]]
blend = 0, [[Alpha blending onto destination (default); d = d*(1-sa) + s.]] blend = 0, [[Alpha blending onto destination (default); d = d*(1-sa) + s.]]
copy = 1, [[Copy source to destination; d = s.]] copy = 1, [[Copy source to destination; d = s.]]
last [[Sentinel value to indicate last enum field during iteration]] last [[Sentinel value to indicate last enum field during iteration]]
@ -182,6 +185,8 @@ enum Efl.Gfx.Hint_Aspect
[[Aspect types/policies for scaling size hints. [[Aspect types/policies for scaling size hints.
See also @Efl.Gfx.Hint.hint_aspect. See also @Efl.Gfx.Hint.hint_aspect.
@since 1.23
]] ]]
none = 0, [[No preference on either direction of the container none = 0, [[No preference on either direction of the container

View File

@ -3,6 +3,8 @@ enum Efl.Input.Device_Type
[[General type of input device. [[General type of input device.
Legacy support since 1.8 as $Evas_Device_Class. Legacy support since 1.8 as $Evas_Device_Class.
@since 1.23
]] ]]
none, [[Not a device.]] none, [[Not a device.]]
seat, [[The user/seat (the user themselves).]] seat, [[The user/seat (the user themselves).]]
@ -22,6 +24,8 @@ enum Efl.Input.Device_Type
class Efl.Input.Device extends Efl.Object class Efl.Input.Device extends Efl.Object
{ {
[[Represents a pointing device such as a touch finger, pen or mouse. [[Represents a pointing device such as a touch finger, pen or mouse.
@since 1.23
]] ]]
methods { methods {
@property device_type { @property device_type {

View File

@ -1,5 +1,8 @@
struct Efl.Model_Property_Event { struct Efl.Model_Property_Event {
[[EFL model property event data structure]] [[EFL model property event data structure
@since 1.23
]]
changed_properties: array<stringshare>; [[List of changed properties]] changed_properties: array<stringshare>; [[List of changed properties]]
invalidated_properties: array<stringshare>; [[Removed properties identified by name]] invalidated_properties: array<stringshare>; [[Removed properties identified by name]]
} }
@ -22,6 +25,8 @@ interface Efl.Model
Additionally a model can have a list of children. The fetching of the children is asynchronous, this has the advantage of Additionally a model can have a list of children. The fetching of the children is asynchronous, this has the advantage of
having as few data sets as possible in the memory itself. having as few data sets as possible in the memory itself.
@since 1.23
]] ]]
c_prefix: efl_model; c_prefix: efl_model;
methods { methods {

View File

@ -2,6 +2,8 @@ interface Efl.Pack extends Efl.Container
{ {
[[Common interface for objects (containers) with multiple contents [[Common interface for objects (containers) with multiple contents
(sub-objects) which can be added and removed at runtime. (sub-objects) which can be added and removed at runtime.
@since 1.23
]] ]]
methods methods
{ {

View File

@ -1,6 +1,9 @@
interface Efl.Player interface Efl.Player
{ {
[[Efl media player interface]] [[Efl media player interface
@since 1.23
]]
c_prefix: efl_player; c_prefix: efl_player;
methods { methods {
@property playing { @property playing {

View File

@ -1,5 +1,8 @@
enum Efl.Text_Bidirectional_Type { enum Efl.Text_Bidirectional_Type {
[[Bidirectionaltext type]] [[Bidirectionaltext type
@since 1.23
]]
natural = 0, [[Natural text type, same as neutral]] natural = 0, [[Natural text type, same as neutral]]
neutral = 0, [[Neutral text type, same as natural]] neutral = 0, [[Neutral text type, same as natural]]
ltr, [[Left to right text type]] ltr, [[Left to right text type]]

View File

@ -2,7 +2,10 @@ import eina_types;
struct Efl.Ui.Property_Event { struct Efl.Ui.Property_Event {
[[EFL Ui property event data structure triggered when an object property change due [[EFL Ui property event data structure triggered when an object property change due
to the interaction on the object.]] to the interaction on the object.
@since 1.23
]]
changed_properties: array<stringshare>; [[List of changed properties]] changed_properties: array<stringshare>; [[List of changed properties]]
} }
@ -12,7 +15,9 @@ interface Efl.Ui.Property_Bind
view object can have @Efl.Model to manage the data, view object can have @Efl.Model to manage the data,
the interface can help loading and tracking child data from the model property. the interface can help loading and tracking child data from the model property.
see @Efl.Model see @Efl.Model
see @Efl.Ui.Factory]] see @Efl.Ui.Factory
@since 1.23]]
methods { methods {
property_bind { property_bind {
[[bind property data with the given key string. when the data is ready or changed, [[bind property data with the given key string. when the data is ready or changed,

View File

@ -17,7 +17,10 @@ error Efl.Ui.Theme.Apply_Error.VERSION = "The widget attempted to load a theme t
enum Efl.Ui.Focus.Direction enum Efl.Ui.Focus.Direction
{ {
[[ Focus directions. ]] [[ Focus directions.
@since 1.23
]]
previous = 0, [[ previous direction ]] previous = 0, [[ previous direction ]]
next = 1, [[ next direction ]] next = 1, [[ next direction ]]
up = 2, [[ up direction ]] up = 2, [[ up direction ]]

View File

@ -26,11 +26,20 @@ type Efl.Callback_Priority : short;
]] ]]
const Efl.Callback_Priority_Before : Efl.Callback_Priority = -100; const Efl.Callback_Priority_Before : Efl.Callback_Priority = -100;
[[Slightly more prioritized than default.]] [[Slightly more prioritized than default.
@since 1.22
]]
const Efl.Callback_Priority_Default : Efl.Callback_Priority = 0; const Efl.Callback_Priority_Default : Efl.Callback_Priority = 0;
[[Default priority.]] [[Default priority.
@since 1.22
]]
const Efl.Callback_Priority_After : Efl.Callback_Priority = 100; const Efl.Callback_Priority_After : Efl.Callback_Priority = 100;
[[Slightly less prioritized than default.]] [[Slightly less prioritized than default.
@since 1.22
]]
abstract Efl.Object abstract Efl.Object
{ {

View File

@ -1,6 +1,9 @@
/* FIXME: Move to Eina when we decide they are handled properly. */ /* FIXME: Move to Eina when we decide they are handled properly. */
struct @extern @free(eina_rectangle_free) Eina.Rect { struct @extern @free(eina_rectangle_free) Eina.Rect {
[[A rectangle in pixel dimensions.]] [[A rectangle in pixel dimensions.
@since 1.22
]]
x: int; [[X coordinate of the rectangle, from the top-left corner.]] x: int; [[X coordinate of the rectangle, from the top-left corner.]]
y: int; [[Y coordinate of the rectangle, from the top-left corner.]] y: int; [[Y coordinate of the rectangle, from the top-left corner.]]
w: int; [[Width of the rectangle in pixels.]] w: int; [[Width of the rectangle in pixels.]]
@ -8,27 +11,42 @@ struct @extern @free(eina_rectangle_free) Eina.Rect {
} }
struct @extern Eina.Position2D { struct @extern Eina.Position2D {
[[A 2D location in pixels.]] [[A 2D location in pixels.
@since 1.22
]]
x: int; [[X position in pixels, from the top-left corner.]] x: int; [[X position in pixels, from the top-left corner.]]
y: int; [[Y position in pixels, from the top-left corner.]] y: int; [[Y position in pixels, from the top-left corner.]]
} }
struct @extern Eina.Size2D { struct @extern Eina.Size2D {
[[A 2D size in pixels.]] [[A 2D size in pixels.
@since 1.22
]]
w: int; [[X position in pixels, from the top-left corner.]] w: int; [[X position in pixels, from the top-left corner.]]
h: int; [[Y position in pixels, from the top-left corner.]] h: int; [[Y position in pixels, from the top-left corner.]]
} }
struct @extern Eina.File; [[Eina file data structure]] struct @extern Eina.File; [[Eina file data structure
@since 1.22
]]
struct @extern Eina.Vector2 { struct @extern Eina.Vector2 {
[[A simple 2D vector type using floating point values.]] [[A simple 2D vector type using floating point values.
@since 1.22
]]
x: double; [[X coordinate.]] x: double; [[X coordinate.]]
y: double; [[Y coordinate.]] y: double; [[Y coordinate.]]
} }
struct @extern Eina.Matrix3 { struct @extern Eina.Matrix3 {
[[Eina 3x3 Matrix]] [[Eina 3x3 Matrix
@since 1.22
]]
xx: double; [[XX matrix value]] xx: double; [[XX matrix value]]
xy: double; [[XY matrix value]] xy: double; [[XY matrix value]]
xz: double; [[XZ matrix value]] xz: double; [[XZ matrix value]]
@ -60,7 +78,10 @@ enum @extern @beta Eina.Xattr.Flags {
created [[This will only succeed if the extended attribute wasn't previously set]] created [[This will only succeed if the extended attribute wasn't previously set]]
} }
type @extern Eina.Error: int; [[Eina error type]] type @extern Eina.Error: int; [[Eina error type
@since 1.22
]]
struct @extern @beta @free(eina_binbuf_free) Eina.Binbuf; [[Eina binbuf data structure]] struct @extern @beta @free(eina_binbuf_free) Eina.Binbuf; [[Eina binbuf data structure]]
struct @extern @beta @free(eina_strbuf_free) Eina.Strbuf; [[Eina strbuf data structure]] struct @extern @beta @free(eina_strbuf_free) Eina.Strbuf; [[Eina strbuf data structure]]
@ -100,7 +121,10 @@ struct @extern @beta Eina.Stat {
ctimensec: ulong; [[The nano version of the timestmap when the file was created]] ctimensec: ulong; [[The nano version of the timestmap when the file was created]]
} }
struct @extern @free(eina_promise_free) Eina.Promise; [[Eina promise type]] struct @extern @free(eina_promise_free) Eina.Promise; [[Eina promise type
@since 1.22
]]
/* FIXME: This definitely shouldn't be here. */ /* FIXME: This definitely shouldn't be here. */
type @beta Efl.Event_Cb: __undefined_type; [[Efl event callback type]] type @beta Efl.Event_Cb: __undefined_type; [[Efl event callback type]]

View File

@ -1,5 +1,6 @@
#include <ctype.h> #include <ctype.h>
#include <assert.h> #include <assert.h>
#include <stdlib.h>
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
# include "config.h" # include "config.h"
@ -12,7 +13,10 @@ typedef struct _Validate_State
{ {
Eina_Bool warned; Eina_Bool warned;
Eina_Bool stable; Eina_Bool stable;
Eina_Bool in_tree;
Eina_Bool unimplemented_beta; Eina_Bool unimplemented_beta;
Eina_Bool verify_since;
const char *since_ver;
} Validate_State; } Validate_State;
static Eina_Bool static Eina_Bool
@ -87,6 +91,60 @@ _validate_docstr(Eina_Stringshare *str, const Eolian_Object *info, Eina_List **r
return ret; return ret;
} }
static Eina_Bool
_validate_doc_since(Validate_State *vals, Eolian_Documentation *doc)
{
if (!doc || !vals->stable || !vals->verify_since)
return EINA_TRUE;
if (doc->since)
{
if (!doc->since[0])
{
/* this should not really happen */
_eo_parser_log(&doc->base, "empty @since tag");
return EINA_FALSE;
}
/* this is EFL; check the numbers */
if (vals->in_tree)
{
const char *snum = doc->since;
if (strncmp(snum, "1.", 2))
{
_eo_parser_log(&doc->base, "invalid EFL version in @since");
return EINA_FALSE;
}
snum += 2;
unsigned long min = strtoul(snum, NULL, 10);
if (min < 22)
{
_eo_parser_log(&doc->base, "stable APIs must be 1.22 or higher");
return EINA_FALSE;
}
}
vals->since_ver = doc->since;
}
else if (!vals->since_ver)
{
_eo_parser_log(&doc->base, "missing @since tag");
return EINA_FALSE;
}
return EINA_TRUE;
}
static Eina_Bool
_validate_doc_since_reset(Validate_State *vals, Eolian_Documentation *doc)
{
if (!doc || !doc->since)
return EINA_TRUE;
const char *old_since = vals->since_ver;
Eina_Bool ret = _validate_doc_since(vals, doc);
vals->since_ver = old_since;
return ret;
}
static Eina_Bool static Eina_Bool
_validate_doc(Eolian_Documentation *doc) _validate_doc(Eolian_Documentation *doc)
{ {
@ -133,6 +191,7 @@ _sf_map_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED,
return EINA_FALSE; return EINA_FALSE;
sc->succ = _validate_doc(sf->doc); sc->succ = _validate_doc(sf->doc);
if (sc->succ) sc->succ = _validate_doc_since_reset(sc->vals, sf->doc);
return sc->succ; return sc->succ;
} }
@ -150,6 +209,7 @@ _ef_map_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED,
return EINA_FALSE; return EINA_FALSE;
sc->succ = _validate_doc(ef->doc); sc->succ = _validate_doc(ef->doc);
if (sc->succ) sc->succ = _validate_doc_since_reset(sc->vals, ef->doc);
return sc->succ; return sc->succ;
} }
@ -160,12 +220,18 @@ _validate_typedecl(Validate_State *vals, Eolian_Typedecl *tp)
if (tp->base.validated) if (tp->base.validated)
return EINA_TRUE; return EINA_TRUE;
if (!_validate_doc(tp->doc)) const char *old_since = vals->since_ver;
return EINA_FALSE; vals->since_ver = NULL;
/* for the time being assume all typedecls are beta unless overridden */ /* for the time being assume all typedecls are beta unless overridden */
Eina_Bool was_stable = _set_stable(vals, !tp->base.is_beta); Eina_Bool was_stable = _set_stable(vals, !tp->base.is_beta);
if (!_validate_doc(tp->doc))
return EINA_FALSE;
if (!_validate_doc_since(vals, tp->doc))
return EINA_FALSE;
switch (tp->type) switch (tp->type)
{ {
case EOLIAN_TYPEDECL_ALIAS: case EOLIAN_TYPEDECL_ALIAS:
@ -174,6 +240,7 @@ _validate_typedecl(Validate_State *vals, Eolian_Typedecl *tp)
if (tp->base_type->ownable) if (tp->base_type->ownable)
tp->ownable = EINA_TRUE; tp->ownable = EINA_TRUE;
_reset_stable(vals, was_stable, EINA_TRUE); _reset_stable(vals, was_stable, EINA_TRUE);
vals->since_ver = old_since;
return _validate(&tp->base); return _validate(&tp->base);
case EOLIAN_TYPEDECL_STRUCT: case EOLIAN_TYPEDECL_STRUCT:
{ {
@ -182,10 +249,12 @@ _validate_typedecl(Validate_State *vals, Eolian_Typedecl *tp)
if (!rt.succ) if (!rt.succ)
return _reset_stable(vals, was_stable, EINA_FALSE); return _reset_stable(vals, was_stable, EINA_FALSE);
_reset_stable(vals, was_stable, EINA_TRUE); _reset_stable(vals, was_stable, EINA_TRUE);
vals->since_ver = old_since;
return _validate(&tp->base); return _validate(&tp->base);
} }
case EOLIAN_TYPEDECL_STRUCT_OPAQUE: case EOLIAN_TYPEDECL_STRUCT_OPAQUE:
_reset_stable(vals, was_stable, EINA_TRUE); _reset_stable(vals, was_stable, EINA_TRUE);
vals->since_ver = old_since;
return _validate(&tp->base); return _validate(&tp->base);
case EOLIAN_TYPEDECL_ENUM: case EOLIAN_TYPEDECL_ENUM:
{ {
@ -199,12 +268,14 @@ _validate_typedecl(Validate_State *vals, Eolian_Typedecl *tp)
if (!rt.succ) if (!rt.succ)
return _reset_stable(vals, was_stable, EINA_FALSE); return _reset_stable(vals, was_stable, EINA_FALSE);
_reset_stable(vals, was_stable, EINA_TRUE); _reset_stable(vals, was_stable, EINA_TRUE);
vals->since_ver = old_since;
return _validate(&tp->base); return _validate(&tp->base);
} }
case EOLIAN_TYPEDECL_FUNCTION_POINTER: case EOLIAN_TYPEDECL_FUNCTION_POINTER:
if (!_validate_function(vals, tp->function_pointer, NULL)) if (!_validate_function(vals, tp->function_pointer, NULL))
return _reset_stable(vals, was_stable, EINA_FALSE); return _reset_stable(vals, was_stable, EINA_FALSE);
_reset_stable(vals, was_stable, EINA_TRUE); _reset_stable(vals, was_stable, EINA_TRUE);
vals->since_ver = old_since;
return _validate(&tp->base); return _validate(&tp->base);
default: default:
return _reset_stable(vals, was_stable, EINA_FALSE); return _reset_stable(vals, was_stable, EINA_FALSE);
@ -576,6 +647,8 @@ _validate_part(Validate_State *vals, Eolian_Part *part, Eina_Hash *phash)
if (!_validate_doc(part->doc)) if (!_validate_doc(part->doc))
return _reset_stable(vals, was_stable, EINA_FALSE); return _reset_stable(vals, was_stable, EINA_FALSE);
if (!_validate_doc_since_reset(vals, part->doc))
return _reset_stable(vals, was_stable, EINA_FALSE);
/* switch the class name for class */ /* switch the class name for class */
Eolian_Class *pcl = eina_hash_find(part->base.unit->classes, part->klass_name); Eolian_Class *pcl = eina_hash_find(part->base.unit->classes, part->klass_name);
@ -695,6 +768,8 @@ _validate_event(Validate_State *vals, Eolian_Event *event, Eina_Hash *nhash)
if (!_validate_doc(event->doc)) if (!_validate_doc(event->doc))
return _reset_stable(vals, was_stable, EINA_FALSE); return _reset_stable(vals, was_stable, EINA_FALSE);
if (!_validate_doc_since_reset(vals, event->doc))
return _reset_stable(vals, was_stable, EINA_FALSE);
eina_hash_set(nhash, &event->base.name, &event->base); eina_hash_set(nhash, &event->base.name, &event->base);
@ -1346,7 +1421,7 @@ _db_fill_inherits(Validate_State *vals, Eolian_Class *cl, Eina_Hash *fhash,
} }
static Eina_Bool static Eina_Bool
_validate_implement(Eolian_Implement *impl) _validate_implement(Validate_State *vals, Eolian_Implement *impl)
{ {
if (impl->base.validated) if (impl->base.validated)
return EINA_TRUE; return EINA_TRUE;
@ -1358,6 +1433,16 @@ _validate_implement(Eolian_Implement *impl)
if (!_validate_doc(impl->set_doc)) if (!_validate_doc(impl->set_doc))
return EINA_FALSE; return EINA_FALSE;
/* common doc inherits @since into get/set doc */
const char *old_since = vals->since_ver;
if (impl->common_doc && !_validate_doc_since(vals, impl->common_doc))
return EINA_FALSE;
if (!_validate_doc_since_reset(vals, impl->get_doc))
return EINA_FALSE;
if (!_validate_doc_since_reset(vals, impl->set_doc))
return EINA_FALSE;
vals->since_ver = old_since;
return _validate(&impl->base); return _validate(&impl->base);
} }
@ -1485,6 +1570,10 @@ _validate_class(Validate_State *vals, Eolian_Class *cl,
} }
_set_stable(vals, !cl->base.is_beta); _set_stable(vals, !cl->base.is_beta);
vals->since_ver = NULL;
if (!_validate_doc_since(vals, cl->doc))
return EINA_FALSE;
EINA_LIST_FOREACH(cl->properties, l, func) EINA_LIST_FOREACH(cl->properties, l, func)
if (!_validate_function(vals, func, nhash)) if (!_validate_function(vals, func, nhash))
@ -1503,7 +1592,7 @@ _validate_class(Validate_State *vals, Eolian_Class *cl,
return EINA_FALSE; return EINA_FALSE;
EINA_LIST_FOREACH(cl->implements, l, impl) EINA_LIST_FOREACH(cl->implements, l, impl)
if (!_validate_implement(impl)) if (!_validate_implement(vals, impl))
return EINA_FALSE; return EINA_FALSE;
/* all the checks that need to be done every time are performed now */ /* all the checks that need to be done every time are performed now */
@ -1529,8 +1618,14 @@ _validate_constant(Validate_State *vals, Eolian_Constant *var)
if (var->base.validated) if (var->base.validated)
return EINA_TRUE; return EINA_TRUE;
const char *old_since = vals->since_ver;
vals->since_ver = NULL;
Eina_Bool was_stable = _set_stable(vals, !var->base.is_beta && vals->stable); Eina_Bool was_stable = _set_stable(vals, !var->base.is_beta && vals->stable);
if (!_validate_doc_since(vals, var->doc))
return EINA_FALSE;
if (!_validate_type(vals, var->base_type, EINA_FALSE, EINA_FALSE)) if (!_validate_type(vals, var->base_type, EINA_FALSE, EINA_FALSE))
return _reset_stable(vals, was_stable, EINA_FALSE); return _reset_stable(vals, was_stable, EINA_FALSE);
@ -1541,6 +1636,7 @@ _validate_constant(Validate_State *vals, Eolian_Constant *var)
return _reset_stable(vals, was_stable, EINA_FALSE); return _reset_stable(vals, was_stable, EINA_FALSE);
_reset_stable(vals, was_stable, EINA_TRUE); _reset_stable(vals, was_stable, EINA_TRUE);
vals->since_ver = old_since;
return _validate(&var->base); return _validate(&var->base);
} }
@ -1566,7 +1662,9 @@ database_validate(const Eolian_Unit *src)
Validate_State vals = { Validate_State vals = {
EINA_FALSE, EINA_FALSE,
EINA_TRUE, EINA_TRUE,
!!getenv("EOLIAN_CLASS_UNIMPLEMENTED_BETA_WARN") !!getenv("EFL_RUN_IN_TREE"),
!!getenv("EOLIAN_CLASS_UNIMPLEMENTED_BETA_WARN"),
!!getenv("EOLIAN_ENFORCE_SINCE")
}; };
/* do an initial pass to refill inherits */ /* do an initial pass to refill inherits */

View File

@ -2,7 +2,10 @@ import efl_text_types;
struct @beta Efl.Canvas.Object_Animation_Event; [[Information of animation events]] struct @beta Efl.Canvas.Object_Animation_Event; [[Information of animation events]]
struct Efl.Event_Animator_Tick { struct Efl.Event_Animator_Tick {
[[EFL event animator tick data structure]] [[EFL event animator tick data structure
@since 1.22
]]
update_area: Eina.Rect; [[Area of the canvas that will be pushed to screen.]] update_area: Eina.Rect; [[Area of the canvas that will be pushed to screen.]]
} }

View File

@ -7,6 +7,8 @@ mixin Efl.Input.Event requires Efl.Object extends Efl.Duplicate
Note: Most Efl Events do not carry Efl Objects, rather simple data Note: Most Efl Events do not carry Efl Objects, rather simple data
structures. This class is intended to carry more complex event structures. This class is intended to carry more complex event
data, such as pointer events. data, such as pointer events.
@since 1.23
]] ]]
c_prefix: efl_input; c_prefix: efl_input;
data: null; data: null;

View File

@ -18,6 +18,8 @@ interface Efl.Input.Interface
A "key" is a key press from a keyboard or equivalent type of input device. A "key" is a key press from a keyboard or equivalent type of input device.
Long, repeated, key presses will always happen like this: Long, repeated, key presses will always happen like this:
down...up,down...up,down...up (not down...up or down...down...down...up). down...up,down...up,down...up (not down...up or down...down...down...up).
@since 1.23
]] ]]
c_prefix: efl_input; c_prefix: efl_input;
event_c_prefix: efl; event_c_prefix: efl;