Documentation/gist - prepend/append expr to method
No issue with the lib. But I use no-spoon almost exclusively to prepend/append expr to existing methods. This pattern is so ubiquitous for me that I wanted to make this gist easily accessible to anybody looking at the project:
public static function initMacro() {
no.Spoon.bend("pack.MyClass", function (fields, cls) {
appendToMethod(fields, "foo", macro {
trace("foo called from bend at the beginning of the method");
});
});
no.Spoon.bend("pack.MyClass", function (fields, cls) {
appendToMethod(fields, "foo", macro {
trace("foo called from bend 2 at the end of the method");
});
});
}
static function appendToMethod(fields: BuildFields, method: String, expr: Expr) {
var methodFields = fields.find(function(f) return f.name == method);
if (methodFields != null && methodFields.length > 0) {
switch (methodFields[0].kind) {
case FFun(func):
switch (func.expr.expr) {
case EBlock(stmts):
stmts.push(expr);
default:
func.expr = macro {
${func.expr};
$expr;
};
}
default:
}
}
}
static function prependToMethod(fields: BuildFields, method: String, expr: Expr) {
var methodFields = fields.find(function(f) return f.name == method);
if (methodFields != null && methodFields.length > 0) {
switch (methodFields[0].kind) {
case FFun(func):
switch (func.expr.expr) {
case EBlock(stmts):
stmts.unshift(expr);
default:
func.expr = macro {
$expr;
${func.expr};
};
}
default:
}
}
}
The benefit to the approach over wholesale replacement is that 1) you don't have to keep track of the logic of the original method if you want to retain it, and 2) it is compositional so you have stack bends on the same method.
This lib is 7 years old at the time of writing so it feels silly to suggest any kind of enhancement, but imo this use case is foundational to the concept and the lib would benefit from having it as an included utility, or perhaps just including the gist as documentation.