Search in sources :

Example 6 with TypedKlass

use of jetbrick.template.parser.support.TypedKlass in project jetbrick-template-1x by subchen.

the class JetTemplateCodeVisitor method visitExpr_method_invocation.

@Override
public Code visitExpr_method_invocation(Expr_method_invocationContext ctx) {
    // 处理参数
    Expression_listContext expression_list = ctx.expression_list();
    SegmentListCode segmentListCode = (expression_list == null) ? SegmentListCode.EMPTY : (SegmentListCode) expression_list.accept(this);
    Class<?>[] parameterTypes = segmentListCode.getParameterTypes();
    // 查找方法
    SegmentCode code = (SegmentCode) ctx.expression().accept(this);
    assert_not_null_constantContext(code.getNode());
    code = code.asBoxedSegmentCode();
    Class<?> beanClass = code.getKlass();
    String name = ctx.IDENTIFIER().getText();
    Method bean_method = resolver.resolveMethod(beanClass, name, parameterTypes);
    Method tool_method = (bean_method != null) ? null : resolver.resolveToolMethod(beanClass, name, parameterTypes);
    boolean tool_advanced = false;
    if (bean_method == null && tool_method == null) {
        tool_method = resolver.resolveToolMethod_advanced(beanClass, name, parameterTypes);
        tool_advanced = true;
    }
    if (bean_method == null && tool_method == null) {
        // reportError
        StringBuilder err = new StringBuilder(128);
        err.append("The method ").append(getMethodSignature(name, parameterTypes));
        err.append(" is undefined for the type ");
        err.append(beanClass.getName());
        err.append('.');
        if (Object.class.equals(beanClass)) {
            err.append("\n advise: ");
            if (code.getNode() instanceof Expr_identifierContext) {
                err.append("Please use #define(type ");
                err.append(code.getNode().getText());
                err.append(") to define variable type.");
            } else {
                err.append("Please use #set(type xxx = ");
                err.append(code.getNode().getText());
                err.append(") to define expression type.");
            }
        }
        throw reportError(err.toString(), ctx.IDENTIFIER());
    }
    boolean isSafeCall = globalSafeCall || "?.".equals(ctx.getChild(1).getText());
    // 得到方法的返回类型
    Method method = (bean_method == null) ? tool_method : bean_method;
    if (securityManager != null) {
        securityManager.checkMemberAccess(method);
    }
    TypedKlass resultKlass = TypedKlassUtils.getMethodReturnTypedKlass(method);
    boolean boxWhenSafeCall = resultKlass.isPrimitive();
    if (isSafeCall) {
        resultKlass = resultKlass.asBoxedTypedKlass();
    }
    // 生成code
    StringBuilder sb = new StringBuilder(64);
    if (tool_method != null) {
        // tool method
        if (isSafeCall) {
            // 安全调用,防止 NullPointException
            sb.append('(');
            sb.append(code.toString());
            sb.append("==null)?(");
            sb.append(resultKlass.getSource());
            sb.append(")null:");
            if (boxWhenSafeCall) {
                sb.append(resultKlass.getSource()).append(".valueOf(");
            }
        }
        sb.append(ClassUtils.getShortClassName(tool_method.getDeclaringClass()));
        sb.append('.');
        sb.append(name);
        sb.append('(');
        sb.append(code.toString());
        if (tool_advanced) {
            sb.append(",$ctx");
        }
        if (segmentListCode.size() > 0) {
            sb.append(',');
        }
    } else {
        if (isSafeCall) {
            // 安全调用,防止 NullPointException
            sb.append('(');
            sb.append(code.toString());
            sb.append("==null)?(");
            sb.append(resultKlass.getSource());
            sb.append(")null:");
            if (boxWhenSafeCall) {
                sb.append(resultKlass.getSource()).append(".valueOf(");
            }
        }
        sb.append(code.toString());
        sb.append('.');
        sb.append(name);
        sb.append('(');
    }
    if (segmentListCode.size() > 0) {
        sb.append(segmentListCode.toString());
    }
    sb.append(')');
    if (isSafeCall) {
        // 为了安全起见,用()包起来
        if (boxWhenSafeCall) {
            sb.append(')');
        }
        sb.insert(0, '(').append(')');
    }
    return new SegmentCode(resultKlass, sb.toString(), ctx);
}
Also used : TypedKlass(jetbrick.template.parser.support.TypedKlass) SegmentCode(jetbrick.template.parser.code.SegmentCode) Expression_listContext(jetbrick.template.parser.grammer.JetTemplateParser.Expression_listContext) Method(java.lang.reflect.Method) SegmentListCode(jetbrick.template.parser.code.SegmentListCode) Expr_identifierContext(jetbrick.template.parser.grammer.JetTemplateParser.Expr_identifierContext)

Example 7 with TypedKlass

use of jetbrick.template.parser.support.TypedKlass in project jetbrick-template-1x by subchen.

the class JetTemplateCodeVisitor method visitExpr_conditional_ternary.

@Override
public Code visitExpr_conditional_ternary(Expr_conditional_ternaryContext ctx) {
    SegmentCode condition = (SegmentCode) ctx.expression(0).accept(this);
    SegmentCode lhs = (SegmentCode) ctx.expression(1).accept(this);
    SegmentCode rhs = (SegmentCode) ctx.expression(2).accept(this);
    String source = "(" + get_if_expression_source(condition) + "?" + lhs.toString() + ":" + rhs.toString() + ")";
    TypedKlass klass = PromotionUtils.getResultClassForConditionalOperator(lhs.getTypedKlass(), rhs.getTypedKlass());
    return new SegmentCode(klass, source, ctx);
}
Also used : TypedKlass(jetbrick.template.parser.support.TypedKlass) SegmentCode(jetbrick.template.parser.code.SegmentCode)

Example 8 with TypedKlass

use of jetbrick.template.parser.support.TypedKlass in project jetbrick-template-1x by subchen.

the class JetTemplateCodeVisitor method visitExpr_static_field_access.

@Override
public Code visitExpr_static_field_access(Expr_static_field_accessContext ctx) {
    SegmentCode static_type_name_code = (SegmentCode) ctx.static_type_name().accept(this);
    String typeName = static_type_name_code.toString();
    String name = ctx.IDENTIFIER().getText();
    Class<?> beanClass = resolver.resolveClass(typeName);
    if (beanClass == null) {
        throw reportError("java.lang.ClassNotFoundException: " + typeName, static_type_name_code.getNode());
    }
    Field field = resolver.resolveStaticField(beanClass, name);
    if (field == null) {
        throw reportError(name + " is not a static field for type " + beanClass.getName(), ctx.IDENTIFIER());
    }
    if (securityManager != null) {
        securityManager.checkMemberAccess(field);
    }
    String source = ClassUtils.getShortClassName(field.getDeclaringClass()) + '.' + name;
    TypedKlass resultKlass = TypedKlassUtils.getFieldTypedKlass(field);
    return new SegmentCode(resultKlass, source, ctx);
}
Also used : Field(java.lang.reflect.Field) TypedKlass(jetbrick.template.parser.support.TypedKlass) SegmentCode(jetbrick.template.parser.code.SegmentCode)

Example 9 with TypedKlass

use of jetbrick.template.parser.support.TypedKlass 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);
}
Also used : TypedKlass(jetbrick.template.parser.support.TypedKlass) SegmentCode(jetbrick.template.parser.code.SegmentCode) Expression_listContext(jetbrick.template.parser.grammer.JetTemplateParser.Expression_listContext) Method(java.lang.reflect.Method) SegmentListCode(jetbrick.template.parser.code.SegmentListCode) MacroCode(jetbrick.template.parser.code.MacroCode)

Example 10 with TypedKlass

use of jetbrick.template.parser.support.TypedKlass in project jetbrick-template-1x by subchen.

the class TypedKlassParser method asTypedKlass.

protected TypedKlass asTypedKlass() {
    TypedKlass type = type();
    match(EOF);
    return type;
}
Also used : TypedKlass(jetbrick.template.parser.support.TypedKlass)

Aggregations

TypedKlass (jetbrick.template.parser.support.TypedKlass)13 SegmentCode (jetbrick.template.parser.code.SegmentCode)12 Method (java.lang.reflect.Method)4 SegmentListCode (jetbrick.template.parser.code.SegmentListCode)4 HashMap (java.util.HashMap)3 Map (java.util.Map)3 Expression_listContext (jetbrick.template.parser.grammer.JetTemplateParser.Expression_listContext)3 Field (java.lang.reflect.Field)2 BlockCode (jetbrick.template.parser.code.BlockCode)2 ForExpressionCode (jetbrick.template.parser.code.ForExpressionCode)2 MacroCode (jetbrick.template.parser.code.MacroCode)2 Expr_identifierContext (jetbrick.template.parser.grammer.JetTemplateParser.Expr_identifierContext)2 TypeContext (jetbrick.template.parser.grammer.JetTemplateParser.TypeContext)2 Member (java.lang.reflect.Member)1 Code (jetbrick.template.parser.code.Code)1 DefineExpressionCode (jetbrick.template.parser.code.DefineExpressionCode)1 ScopeCode (jetbrick.template.parser.code.ScopeCode)1 TagCode (jetbrick.template.parser.code.TagCode)1 TemplateClassCode (jetbrick.template.parser.code.TemplateClassCode)1 TextCode (jetbrick.template.parser.code.TextCode)1