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);
}
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);
}
Aggregations