use of jetbrick.template.parser.support.TypedKlass in project jetbrick-template-1x by subchen.
the class JetTemplateCodeVisitor method visitSet_expression.
@Override
public Code visitSet_expression(Set_expressionContext ctx) {
String name = assert_java_identifier(ctx.IDENTIFIER(), true);
SegmentCode code = (SegmentCode) ctx.expression().accept(this);
// 是否同时定义一个变量
boolean defining = false;
// 变量类型
TypedKlass lhs = null;
TypeContext type = ctx.type();
if (type != null) {
defining = true;
// 定义一个变量
SegmentCode c = (SegmentCode) type.accept(this);
lhs = c.getTypedKlass();
if (!scopeCode.define(name, lhs)) {
throw reportError("Duplicate local variable " + name, ctx.IDENTIFIER());
}
} else {
// 直接赋值,如果变量没有定义,则先定义
lhs = scopeCode.resolve(name, false);
defining = (lhs == null);
if (defining) {
lhs = code.getTypedKlass();
scopeCode.define(name, lhs);
}
}
// 进行赋值语句类型检查
if (!ClassUtils.isAssignable(lhs.getKlass(), code.getKlass())) {
// 是否支持正常赋值
if (!ClassUtils.isAssignable(code.getKlass(), lhs.getKlass())) {
// 是否支持强制类型转换
throw reportError("Type mismatch: cannot convert from " + code.getTypedKlass().toString() + " to " + lhs.toString(), ctx);
}
}
BlockCode c = scopeCode.createBlockCode(2);
String source = name + " = (" + lhs.getSource() + ") " + code.toString() + "; // line: " + ctx.getStart().getLine();
if (defining) {
source = lhs.getSource() + " " + source;
}
c.addLine(source);
c.addLine(Code.CONTEXT_NAME + ".put(\"" + name + "\", " + name + ");");
return c;
}
use of jetbrick.template.parser.support.TypedKlass in project jetbrick-template-1x by subchen.
the class JetTemplateCodeVisitor method visitExpr_new_array.
@Override
public Code visitExpr_new_array(Expr_new_arrayContext ctx) {
SegmentCode code = (SegmentCode) ctx.type().accept(this);
if (code.getKlass().isArray()) {
throw reportError("Cannot specify an array dimension after an empty dimension", ctx.type());
}
StringBuilder typeSource = new StringBuilder(code.toString());
// 生成代码
StringBuilder source = new StringBuilder(32);
source.append("(new ").append(code.toString());
for (ExpressionContext expression : ctx.expression()) {
SegmentCode c = (SegmentCode) expression.accept(this);
if (!ClassUtils.isAssignable(Integer.TYPE, c.getKlass())) {
throw reportError("Type mismatch: cannot convert from " + c.getKlassName() + " to int.", expression);
}
source.append('[').append(c.toString()).append(']');
typeSource.append("[]");
}
source.append(')');
TypedKlass resultKlass = resolver.resolveTypedKlass(typeSource.toString());
return new SegmentCode(resultKlass, source.toString(), ctx);
}
use of jetbrick.template.parser.support.TypedKlass in project jetbrick-template-1x by subchen.
the class JetTemplateCodeVisitor method visitExpr_array_get.
@Override
public Code visitExpr_array_get(Expr_array_getContext ctx) {
SegmentCode lhs = (SegmentCode) ctx.expression(0).accept(this);
SegmentCode rhs = (SegmentCode) ctx.expression(1).accept(this);
assert_not_null_constantContext(lhs.getNode());
assert_not_null_constantContext(rhs.getNode());
boolean isSafeCall = globalSafeCall || "?".equals(ctx.getChild(1).getText());
Class<?> lhsKlass = lhs.getKlass();
if (lhsKlass.isArray()) {
if (!ClassUtils.isAssignable(Integer.TYPE, rhs.getKlass())) {
throw reportError("Type mismatch: cannot convert from " + rhs.getKlassName() + " to int.", lhs.getNode());
}
TypedKlass resultKlass = TypedKlass.create(lhsKlass.getComponentType(), lhs.getTypeArgs());
boolean boxWhenSafeCall = resultKlass.isPrimitive();
if (isSafeCall) {
resultKlass = resultKlass.asBoxedTypedKlass();
}
StringBuilder sb = new StringBuilder();
if (isSafeCall) {
sb.append('(');
sb.append(lhs.toString());
sb.append("==null?(");
sb.append(resultKlass.getSource());
sb.append(")null:");
if (boxWhenSafeCall) {
sb.append(resultKlass.getSource()).append(".valueOf(");
}
sb.append(lhs.toString());
sb.append('[');
sb.append(rhs.toString());
sb.append(']');
if (boxWhenSafeCall) {
sb.append(')');
}
sb.append(')');
} else {
sb.append(lhs.toString());
sb.append('[');
sb.append(rhs.toString());
sb.append(']');
}
return new SegmentCode(resultKlass, sb.toString(), ctx);
} else {
TypedKlass resultKlass = null;
// try to List.get(index) or Map.get(name) or JetContext.get(name)
if (List.class.isAssignableFrom(lhsKlass)) {
if (!ClassUtils.isAssignable(Integer.TYPE, rhs.getKlass())) {
throw reportError("The method get(int) in the type List is not applicable for the arguments (" + rhs.getKlassName() + ")", rhs.getNode());
}
// 取出可能的List泛型
if (lhs.getTypeArgs() != null && lhs.getTypeArgs().length == 1) {
resultKlass = lhs.getTypeArgs()[0];
}
} else if (Map.class.isAssignableFrom(lhsKlass)) {
// 取出可能的Map泛型
if (lhs.getTypeArgs() != null && lhs.getTypeArgs().length == 2) {
// value 对应的泛型
resultKlass = lhs.getTypeArgs()[1];
}
} else if (JetContext.class.isAssignableFrom(lhsKlass)) {
if (!String.class.equals(rhs.getKlass())) {
throw reportError("The method get(String) in the type JetContext is not applicable for the arguments (" + rhs.getKlassName() + ")", rhs.getNode());
}
resultKlass = TypedKlass.Object;
} else {
throw reportError("Operator [] is not applicable for the object (" + lhs.getKlassName() + ").", ctx);
}
if (resultKlass == null) {
resultKlass = TypedKlass.Object;
}
boolean boxWhenSafeCall = resultKlass.isPrimitive();
if (isSafeCall) {
resultKlass = resultKlass.asBoxedTypedKlass();
}
StringBuilder sb = new StringBuilder();
if (isSafeCall) {
sb.append('(');
sb.append(lhs.toString());
sb.append("==null?(");
sb.append(resultKlass.getSource());
sb.append(")null:");
if (boxWhenSafeCall) {
sb.append(resultKlass.getSource()).append(".valueOf(");
}
sb.append(lhs.toString());
sb.append(".get(");
sb.append(rhs.toString());
sb.append(')');
if (boxWhenSafeCall) {
sb.append(')');
}
sb.append(')');
} else {
sb.append(lhs.toString());
sb.append(".get(");
sb.append(rhs.toString());
sb.append(')');
}
return new SegmentCode(resultKlass, sb.toString(), ctx);
}
}
use of jetbrick.template.parser.support.TypedKlass in project jetbrick-template-1x by subchen.
the class JetTemplateCodeVisitor method visitExpr_static_method_invocation.
@Override
public Code visitExpr_static_method_invocation(Expr_static_method_invocationContext 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
Class<?> beanClass = resolver.resolveClass(typeName);
if (beanClass == null) {
throw reportError("java.lang.ClassNotFoundException: " + typeName, static_type_name_code.getNode());
}
// 处理参数
Expression_listContext expression_list = ctx.expression_list();
SegmentListCode segmentListCode = (expression_list == null) ? SegmentListCode.EMPTY : (SegmentListCode) expression_list.accept(this);
Class<?>[] parameterTypes = segmentListCode.getParameterTypes();
Method method = resolver.resolveStaticMethod(beanClass, name, parameterTypes);
if (method == null) {
throw reportError("The static method " + getMethodSignature(name, parameterTypes) + " is undefined for the type " + beanClass.getName(), ctx.IDENTIFIER());
}
if (securityManager != null) {
securityManager.checkMemberAccess(method);
}
// 生成代码
StringBuilder sb = new StringBuilder();
sb.append(ClassUtils.getShortClassName(method.getDeclaringClass()));
sb.append('.');
sb.append(name);
sb.append('(');
sb.append(segmentListCode.toString());
sb.append(')');
TypedKlass resultKlass = TypedKlassUtils.getMethodReturnTypedKlass(method);
return new SegmentCode(resultKlass, sb.toString(), ctx);
}
use of jetbrick.template.parser.support.TypedKlass in project jetbrick-template-1x by subchen.
the class JetTemplateCodeVisitor method visitType.
@Override
public Code visitType(TypeContext ctx) {
StringBuilder name = new StringBuilder();
for (TerminalNode node : ctx.IDENTIFIER()) {
if (name.length() > 0) {
name.append('.');
}
name.append(node.getText());
}
// 查找 klass
Class<?> klass = resolver.resolveClass(name.toString());
if (klass == null) {
StringBuilder sb = new StringBuilder(128);
sb.append("java.lang.ClassNotFoundException: ").append(name);
sb.append("\n advise: Please define package in 'import.packages' or use full qualified class name.");
throw reportError(sb.toString(), ctx);
}
if (securityManager != null) {
securityManager.checkMemberAccess(klass);
}
// 查找泛型类型 typeArgs
TypedKlass[] typeArgs = TypedKlass.EMPTY_TYPE_ARGS;
Type_argumentsContext type_arguments = ctx.type_arguments();
if (type_arguments != null) {
SegmentListCode c = (SegmentListCode) type_arguments.accept(this);
typeArgs = new TypedKlass[c.size()];
for (int i = 0; i < typeArgs.length; i++) {
typeArgs[i] = c.getChild(i).getTypedKlass();
}
}
// 如果是数组类型,则把 klass 转成数组
String array_suffix = "";
List<Type_array_suffixContext> type_array_suffix = ctx.type_array_suffix();
for (Type_array_suffixContext c : type_array_suffix) {
Code code = c.accept(this);
array_suffix = array_suffix + code.toString();
}
if (array_suffix.length() > 0) {
// 转换成 Array Class, 重新 resolve
String klassName = name.toString() + array_suffix;
klass = resolver.resolveClass(klassName);
if (klass == null) {
throw reportError("java.lang.ClassNotFoundException: " + klassName, ctx);
}
}
// 返回带有的泛型信息的 Class
TypedKlass typedKlass = TypedKlass.create(klass, typeArgs);
return new SegmentCode(typedKlass, typedKlass.toString(), ctx);
}
Aggregations