use of jetbrick.template.parser.code.MacroCode in project jetbrick-template-1x by subchen.
the class JetTemplateCodeVisitor method visitExpr_function_call.
@Override
public Code visitExpr_function_call(Expr_function_callContext ctx) {
// 处理参数
Expression_listContext expression_list = ctx.expression_list();
SegmentListCode segmentListCode = (expression_list == null) ? SegmentListCode.EMPTY : (SegmentListCode) expression_list.accept(this);
Class<?>[] parameterTypes = segmentListCode.getParameterTypes();
// 查找方法
String name = ctx.IDENTIFIER().getText();
// 优先查找 macro
MacroCode macroCode = null;
if (macroMap != null) {
macroCode = macroMap.get(name);
if (macroCode != null) {
// macro 参数匹配
SegmentListCode defineListCode = macroCode.getDefineListCode();
int size = (defineListCode == null) ? 0 : defineListCode.size();
if (parameterTypes.length != size) {
throw reportError("Arguments mismatch for #macro " + getMethodSignature(name, parameterTypes) + ".", ctx.IDENTIFIER());
}
for (int i = 0; i < parameterTypes.length; i++) {
if (!ClassUtils.isAssignable(parameterTypes[i], defineListCode.getChild(i).getKlass())) {
throw reportError("Arguments mismatch for #macro " + getMethodSignature(name, parameterTypes) + ".", ctx.IDENTIFIER());
}
}
// 生成 macro 调用 code
StringBuilder sb = new StringBuilder(64);
sb.append("$macro_").append(name);
sb.append("($ctx");
if (segmentListCode.size() > 0) {
sb.append(',').append(segmentListCode.toString());
}
sb.append(')');
return new SegmentCode(TypedKlass.VOID, sb.toString(), ctx);
}
}
// 查找扩展方法
boolean advanced = false;
Method method = resolver.resolveFunction(name, parameterTypes);
if (method == null) {
method = resolver.resolveFunction_advanced(name, parameterTypes);
advanced = true;
}
if (method == null) {
throw reportError("Undefined function or arguments mismatch: " + getMethodSignature(name, parameterTypes) + ".", ctx.IDENTIFIER());
}
if (securityManager != null) {
securityManager.checkMemberAccess(method);
}
// 生成code
StringBuilder sb = new StringBuilder(64);
sb.append(ClassUtils.getShortClassName(method.getDeclaringClass()));
sb.append('.');
sb.append(name);
sb.append('(');
if (advanced) {
sb.append("$ctx");
}
if (segmentListCode.size() > 0) {
if (advanced)
sb.append(',');
sb.append(segmentListCode.toString());
}
sb.append(')');
TypedKlass typedKlass = TypedKlassUtils.getMethodReturnTypedKlass(method);
return new SegmentCode(typedKlass, sb.toString(), ctx);
}
use of jetbrick.template.parser.code.MacroCode in project jetbrick-template-1x by subchen.
the class JetTemplateCodeVisitor method visitMacro_directive.
@Override
public Code visitMacro_directive(Macro_directiveContext ctx) {
String text = ctx.getChild(0).getText();
String name = text.substring(7, text.length() - 1).trim();
MacroCode macroCode = scopeCode.createMacroCode();
macroCode.setName(name);
scopeCode = macroCode.getMethodCode();
scopeCode.define(Code.CONTEXT_NAME, TypedKlass.JetContext);
// 处理参数
Define_expression_listContext define_expression_list = ctx.define_expression_list();
if (define_expression_list != null) {
SegmentListCode define_list_code = (SegmentListCode) define_expression_list.accept(this);
macroCode.setDefineListCode(define_list_code);
// 设置参数 Context
for (SegmentCode node : define_list_code.getChildren()) {
DefineExpressionCode c = (DefineExpressionCode) node;
scopeCode.define(c.getName(), c.getTypedKlass());
}
}
// 需要先定义 macro,这样可以支持 macro 的递归调用 (issue 102)
if (macroMap == null) {
macroMap = new HashMap<String, MacroCode>(8);
}
MacroCode old = macroMap.put(name, macroCode);
if (old != null) {
throw reportError("Duplicated macro defination " + name, ctx);
}
tcc.addMacro(macroCode);
// 访问 macro body
// add body content
scopeCode.setBodyCode(ctx.block().accept(this));
scopeCode = scopeCode.pop();
return Code.EMPTY;
}
Aggregations