-
Notifications
You must be signed in to change notification settings - Fork 1
Aspect definition files
Aspect definition files contain the definitions of aspects which will be used to transform your code. The default suffix for such a file is .adf.
Global elements. These are either global aspects, advices, or pointcuts. A global element needs to have an id attribute if it is going to be referred to. Each aspect/advice/pointcut definition is made up of a list of attributes e.g. {aspect, ListOfAttribs}. {advice, ListOfAttribs}. {pointcut, ListOfAttribs}.
Note that the content of a .adf file is made up of Erlang terms. .adf files are read using file:consult/1, so each global element must end with a period character '.'.
Example of an aspect defined in a .adf file:
{aspect, [ {id, "logging"}, {advice, [ {type, 'after'}, {mf, advices, log_clean}, {ptcuts, ["clean_msg_receive", {pointcut, [ {send_msg, "{abort, _Id, _From}"} ]} ]} ]}, {pointcut, [ {id, "clean_msg_send"}, {send_msg, "{clean, _Id}"} ]} ]}.
An aspect definition can take the following attributes:
- One id - An id for the aspect. Optional.
- One or more advice definition/s. Having no advice definitions means this aspect will have no effect on the source files being compiled.
- Zero or more pointcut definition/s. The reason that an aspect can have zero pointcut definitions is because all pointcut definitions required may be found in the advice definition.
Examples of pointcut definitions:
{pointcut, [ {send_msg, "{clean, _Id, _From}"} ]}. {pointcut, [ {id, "clean_msg_receive"}, {receive_msg, "{clean, _Id, _From}"} ]}. {pointcut, [ {id, "all_service_calls"}, {functiondef, "program", "\\w*_service", "2"} ]}.
A pointcut definition can take the following attributes:
- One id - An id for the pointcut. May be optional depending on whether the pointcut needs to be referred to.
- One of the following depending on what kind of pointcut you are defining:
- send_msg: Takes 1 argument, a string representing the form in which a message being sent needs to be in order for the pointcut to apply. Note that the variables are preceded with an underscore. This is done in order to avoid compiler warnings that variable Id (for example) is never used.
- receive_msg: Takes 1 argument, a string representing the form in which a message being received needs to be in order for the pointcut to apply. Again, the underscore serves the same purpose as it does in the send_msg attribute.
- functiondef: A functiondef attribute takes 3 arguments. The first two arguments are either a string or an atom, the last is either a string or an integer. The first argument specifies the module/s in which the function being defined needs to be in in order for this pointcut to apply. If it's an atom the match is done exactly, otherwise, a string is interpreted as a regular expression (and can match more than a single module). The second argument specifies the name/s of the function which the pointcut will select. Again, an atom performs an exact match while a string is interpreted as a regex. The third argument specifies the function's arity. An integer requires an exact match while a string is interpreted as a regex.
Example of an advice definition:
{advice, [ {id, "advice_id"}, {type, 'after'}, {mf, advices, log_clean}, {ptcuts, ["clean_msg_send", "clean_msg_receive", {pointcut, [ {send_msg, "{abort, _Id, _From}"} ]} ]} ]}.
An advice definition can take the following attributes:
- One id - An id for the advice. May be optional depending on whether the advice needs to be referred to.
- A type. The value of the type attribute can be any of the following:
- before: The advice is applied before the join points selected by the pointcuts defined in this advice.
- 'after': The advice is applied after the join points selected by the pointcuts defined in this advice. Since after is a keyword in Erlang, it needs to be enclosed in single quotes to make it an atom.
- around: This applies only to join points selected by functiondef pointcuts. The advice is applied instead of the join points selected by the functiondef pointcuts. The applied advice is expected to invoke the function it substitutes and return its result.
- after_throw: This applies only to join points selected by functiondef pointcuts. The advice is applied only in the case that the function/s selected by the functiondef pointcut throw an exception.
- after_final: This applies only to join points selected by functiondef pointcuts. The advice is applied after the evaluation of the functions selected by the functiondef pointcuts, whether they throw an exception or not.
- The mf attribute takes the module and function name of the advice function to apply. These are passed as atoms.
- The ptcuts attribute takes a list of strings and/or pointcut definitions. The strings must refer to local or global pointcuts. An example is given here.