We keep a hash tracking implements that were already errored on
so that we don't print some errors multiple times. The problem is
that it wasn't getting cleared when switching to a new inheritance
tree so errors from an interface implemented in multiple distinct
inheritance trees would only get printed once.
Since _extend_impl always marks the impl at least IMPL_STATUS_NONE,
we need to retrieve the original status before calling into it,
or it will get overwritten and will inadvertently disable some
of the checks.
We worked under the assumption that when inheriting callables
from a regular class, it's good enough to just set those as
fully implemented, because the underlying class is already
checked. This assumption is wrong, as the callables may contain
multiple implements pointing at the same function (consider when
a regular class implements just the get part of a property but
some underlying class implements it whole) - the old logic would
result in just the first reached implement (possibly incomplete)
being added into callables of the inheriting class, which results
in false positives.
Consider this example:
class A has a fully implemented property foo
class B inherits from A and partially implements foo
abstract C inherits from B
class D inherits from C
abstract C would go over B's implements, encounter the first
partial implementation of foo, adding it into its own callables
and marking it as fully implemented (because it came from an
already checked regular class B), which would result in the
other implement being skipped.
So make no assumptions and use the same logic for all class types.
Of course, this brings in another problem: some errors would now
get printed twice, because if you have a class A which has funcs
that are unimplemented and class B inheriting from it, errors would
get printed for A but also for B, which would include A's errors.
To battle that, introduce a "global" (well, local to the entry
point of the validator) hash tracking which implements have already
been errored on; and skip those appropriately.
It hasn't been necessary to keep these temporary buffers around
for quite a while, nobody just got around to remove them. Eolian
has a good formattable error logging system in its core now.
Also, use same erroring style on parts as on functions, i.e.
batch-print all the conflicts at once.
There isn't any more logic necessary because checks are still only
done on regular classes; we just need to make sure that composite
lists from its inheritance tree are accounted for.
if there is no free function, then there is no way that this value is
owned by the caller,
Reviewed-by: Daniel Kolesa <daniel@octaforge.org>
Differential Revision: https://phab.enlightenment.org/D7712
Each regular class can now have a section called 'composite',
which can contain interfaces and interfaces only. This defines
a list of interfaces that are allowed to be unimplemented on the
class, as it is assumed the class will be composited with some
other class implementing those interfaces.
Only regular classes can have this, as only regular classes can
be instantiated.
It will also be necessary to check whether the classes in the
section appear somewhere within the inheritance tree. For now,
this testing is not being done.
Example of usage:
composite {
Some.Magic.Interface;
Another.Magic.Interface;
}
directly in the class body.
base of the impl is where the function is defined, not where the missing
implementation is.
ref T5719
Reviewed-by: Daniel Kolesa <daniel@octaforge.org>
Differential Revision: https://phab.enlightenment.org/D7680
The checks are only done for regular classes. It's also disabled
by default as too many methods would be unimplemented.
Use EOLIAN_CLASS_UNIMPLEMENTED_WARN=1 to enable the errors.
It appears that NULL is not really usefull here, as this will lead to
errors later on. (void) will force the free function to just do nothing
and be later converted to a NOP.
Reviewed-by: Daniel Kolesa <daniel@octaforge.org>
Differential Revision: https://phab.enlightenment.org/D7629
This introduces a new keyword called required. It only works on mixins.
You can specify a list of regular/abstract classes in there.
Classes specified after the required keyword are later used to verify
the usage of the mixin. With this feature a mixin can define a list of
types that the inheriting object (the object that inherits from a mixin)
needs to fullfill, if one class that is required is not in the
implemented classes, then eolian will bail out.
Differential Revision: https://phab.enlightenment.org/D7584
As per T7240, we intend to disallow multi-class inheritance in Eo
at some point. In order to achieve that, it is necessary to find
out which classes still use multi-class inheritance and change
them accordingly.
Eo multi-class inheritance is not actually multi-class, as doing
so will simply treat all the other classes as interfaces, which
is misleading and poor design on its own.
By setting EOLIAN_CLASS_REGULAR_AS_EXT_WARN environment variable,
Eolian will now warn about such classes, allowing them to be
fixed.
Closes T7365.
Eolian now separates 'parent' and 'extensions'. For regular
classes, parent is the first item in the inherits list and
extesions is the rest. For interfaces and mixins, parent is
NULL and extends is the inherits list.
The reason for this is the separation of them in syntax in near
future. It also slightly changes the behavior; since for interfaces
and mixins, parent is always NULL now, you can freely inherit from
all types of classes without needing to manually put an interface
type as the first item of the inherits list.
Previously, the EOLIAN_EVENT_REDEF_WARN environment variable
enabled extra checks that would include events in checking
conflicts against methods. Since this is probably not necessary
and naming events the same as methods is perfectly fine in itself,
relax this rule and check events completely independently.
In practice, this will disallow using the same name for two
events within the same inheritance tree, which is desirable
in longer term, but cannot be enabled just yet because we have
too many of those conflicts. But it also allows the events to
be named the same as methods or parts, which is fine and was not
possible before.
Summary:
Strings are const and if these are meant to be owned then it
should define its own special free func. Mstrings are mutable
and therefore can be owned and freed using standard free() by
default.
This fixes some warnings around the EFL caused by empty fallback
free funcs created by the eolian generator, and these mutable
strings were not being freed and potentially leaked.
Reviewers: bu5hm4n, stefan_schmidt
Subscribers: cedric, #reviewers, #committers
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D7261
This will make it easier for generators and utilities to retrieve
the class that implemented a method/property/etc rather than the
class the implement was originally defined for. Thanks to this
it will no longer be necessary to carry the class pointer around
the place.
Set the EOLIAN_EVENT_NO_TYPE_WARN environment variable to enable
those warnings during Eolian usage. They will be considered a part
of the validation then.
Use the void type for events to suppress the warning.
This is necessary because inheritance trees need to be validated
individually for proper name conflict checks. It also prevents
eina_hash_add related errors.
Doc refs no longer introduce new dependencies into files. Instead,
they're parsed globally, and any doc ref lookup is also made
globally. This allows unit based dependencies to correspond more
to what files actually really need at compile time/runtime, with
docs being irrelevant to that; it also simplifies the API.
The doc resolution API now takes Eolian_State instead of
Eolian_Unit, too.
Eolian doc objects now bundle debug information necessary to
provide correct line/column numbers. It is not possible to get
this information cirectly from the text, as it's reformatted and
contains no extra whitespace or newlines beyond paragraph
separators.
Fixes T6701.