Search in sources :

Example 1 with Expr_identifierContext

use of jetbrick.template.parser.grammer.JetTemplateParser.Expr_identifierContext 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 2 with Expr_identifierContext

use of jetbrick.template.parser.grammer.JetTemplateParser.Expr_identifierContext in project jetbrick-template-1x by subchen.

the class JetTemplateCodeVisitor method visitExpr_field_access.

@Override
public Code visitExpr_field_access(Expr_field_accessContext ctx) {
    SegmentCode code = (SegmentCode) ctx.expression().accept(this);
    String name = ctx.IDENTIFIER().getText();
    assert_not_null_constantContext(code.getNode());
    // 进行类型推导,找到方法的返回类型
    code = code.asBoxedSegmentCode();
    Class<?> beanClass = code.getKlass();
    Member member = null;
    if ((!beanClass.isArray()) || (!"length".equals(name))) {
        // not array.length
        member = resolver.resolveProperty(beanClass, name);
        if (member == null) {
            // reportError
            name = name.substring(0, 1).toUpperCase() + name.substring(1);
            StringBuilder err = new StringBuilder(128);
            err.append("The method ");
            err.append("get" + name);
            err.append("() or ");
            err.append("is" + name);
            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());
    // 生成code
    StringBuilder sb = new StringBuilder(64);
    TypedKlass resultKlass = null;
    if (member instanceof Method) {
        Method method = (Method) member;
        if (securityManager != null) {
            securityManager.checkMemberAccess(method);
        }
        // special code for Map.get()
        // https://github.com/subchen/jetbrick-template/issues/100
        TypedKlass typedKlass = code.getTypedKlass();
        if ("get".equals(method.getName()) && member.getDeclaringClass() == Map.class) {
            if (typedKlass.getTypeArgs().length >= 2) {
                resultKlass = typedKlass.getTypeArgs()[1];
            }
        }
        if (resultKlass == null) {
            resultKlass = TypedKlassUtils.getMethodReturnTypedKlass(method);
        }
        if (method.getParameterTypes().length == 0) {
            // getXXX() or isXXX()
            if (isSafeCall) {
                // 安全调用,防止 NullPointException
                boolean boxWhenSafeCall = false;
                if (resultKlass.isPrimitive()) {
                    boxWhenSafeCall = true;
                    resultKlass = resultKlass.asBoxedTypedKlass();
                }
                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(method.getName());
                sb.append("()");
                if (boxWhenSafeCall) {
                    sb.append(')');
                }
                sb.append(')');
            } else {
                sb.append(code.toString());
                sb.append('.');
                sb.append(method.getName());
                sb.append("()");
            }
        } else {
            // get(String)
            if (isSafeCall) {
                // 安全调用,防止 NullPointException
                boolean boxWhenSafeCall = false;
                if (resultKlass.isPrimitive()) {
                    boxWhenSafeCall = true;
                    resultKlass = resultKlass.asBoxedTypedKlass();
                }
                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(".get(\"");
                sb.append(name);
                sb.append("\")");
                if (boxWhenSafeCall) {
                    sb.append(')');
                }
                sb.append(')');
            } else {
                sb.append(code.toString());
                sb.append(".get(\"");
                sb.append(name);
                sb.append("\")");
            }
        }
    } else {
        if (member instanceof Field) {
            if (securityManager != null) {
                securityManager.checkMemberAccess((Field) member);
            }
            resultKlass = TypedKlassUtils.getFieldTypedKlass((Field) member);
        } else {
            // array.length
            resultKlass = TypedKlass.create(Integer.TYPE);
        }
        if (isSafeCall) {
            // 安全调用,防止 NullPointException
            boolean boxWhenSafeCall = false;
            if (resultKlass.isPrimitive()) {
                boxWhenSafeCall = true;
                resultKlass = resultKlass.asBoxedTypedKlass();
            }
            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);
            if (boxWhenSafeCall) {
                sb.append(')');
            }
            sb.append(')');
        } else {
            sb.append(code.toString());
            sb.append('.');
            sb.append(name);
        }
    }
    return new SegmentCode(resultKlass, sb.toString(), ctx);
}
Also used : Field(java.lang.reflect.Field) TypedKlass(jetbrick.template.parser.support.TypedKlass) SegmentCode(jetbrick.template.parser.code.SegmentCode) Method(java.lang.reflect.Method) Member(java.lang.reflect.Member) Map(java.util.Map) HashMap(java.util.HashMap) Expr_identifierContext(jetbrick.template.parser.grammer.JetTemplateParser.Expr_identifierContext)

Aggregations

Method (java.lang.reflect.Method)2 SegmentCode (jetbrick.template.parser.code.SegmentCode)2 Expr_identifierContext (jetbrick.template.parser.grammer.JetTemplateParser.Expr_identifierContext)2 TypedKlass (jetbrick.template.parser.support.TypedKlass)2 Field (java.lang.reflect.Field)1 Member (java.lang.reflect.Member)1 HashMap (java.util.HashMap)1 Map (java.util.Map)1 SegmentListCode (jetbrick.template.parser.code.SegmentListCode)1 Expression_listContext (jetbrick.template.parser.grammer.JetTemplateParser.Expression_listContext)1