use of kalang.ast.ClassNode in project kalang by kasonyang.
the class ClassType method isAssignableFrom.
@Override
public boolean isAssignableFrom(Type type) {
if (super.isAssignableFrom(type))
return true;
if (type instanceof ClassType) {
ClassType other = (ClassType) type;
if (!nullable.isAssignableFrom(other.getNullable()))
return false;
ClassNode otherClazz = other.getClassNode();
if (!clazz.equals(otherClazz))
return false;
GenericType[] gts = clazz.getGenericTypes();
if (gts.length == 0)
return true;
// handle parameterizedType
Type[] typeArgs = getTypeArguments();
Type[] otherTypeArgs = other.getTypeArguments();
if (typeArgs.length == 0 || otherTypeArgs.length == 0)
return true;
if (typeArgs.length != otherTypeArgs.length)
return false;
for (int i = 0; i < typeArgs.length; i++) {
Type a = typeArgs[i];
Type oa = otherTypeArgs[i];
if (a.equals(oa))
continue;
if (a instanceof WildcardType) {
WildcardType wt = (WildcardType) a;
if (!wt.containsType((ObjectType) oa))
return false;
}
}
return true;
}
return false;
}
use of kalang.ast.ClassNode in project kalang by kasonyang.
the class Ast2Class method visitClassNode.
@Override
public Object visitClassNode(ClassNode node) {
ClassNode oldClass = this.clazz;
this.clazz = node;
String oldClassInternalName = this.classInternalName;
this.classInternalName = internalName(clazz);
ClassWriter oldClassWriter = this.classWriter;
this.classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
annotation(classWriter, clazz.getAnnotations());
String parentName = "java.lang.Object";
ObjectType superType = node.getSuperType();
if (superType != null) {
parentName = superType.getName();
}
String[] interfaces = null;
if (node.getInterfaces().length > 0) {
interfaces = internalName(node.getInterfaces());
}
int access = node.modifier;
classWriter.visit(V1_6, access, internalName(node.name), classSignature(node), internalName(parentName), interfaces);
String fileName = node.fileName;
if (fileName != null && !fileName.isEmpty()) {
classWriter.visitSource(fileName, null);
}
visitChildren(node);
// clinit
if (!node.staticInitStmts.isEmpty()) {
md = classWriter.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null);
visitAll(node.staticInitStmts);
md.visitInsn(RETURN);
md.visitMaxs(1, 1);
}
if (node.enclosingClass != null) {
this.classWriter.visitInnerClass(this.internalName(node), this.internalName(node.enclosingClass), NameUtil.getSimpleClassName(node.name), node.modifier);
}
for (ClassNode ic : node.classes) {
classWriter.visitInnerClass(internalName(ic), internalName(node), NameUtil.getSimpleClassName(ic.name), ic.modifier);
}
classWriter.visitEnd();
if (outputManager != null) {
try {
try (OutputStream os = outputManager.createOutputStream(node.name)) {
os.write(this.classWriter.toByteArray());
}
} catch (IOException ex) {
throw new RuntimeException(ex);
}
} else {
LOG.log(Level.WARNING, "outputManager is null");
}
this.clazz = oldClass;
this.classInternalName = oldClassInternalName;
this.classWriter = oldClassWriter;
return null;
}
use of kalang.ast.ClassNode in project kalang by kasonyang.
the class AstBuilder method parseClassType.
@Nullable
protected ObjectType parseClassType(KalangParser.ClassTypeContext ctx) {
NullableKind nullable = ctx.nullable == null ? NullableKind.NONNULL : NullableKind.NULLABLE;
Token rawTypeToken = ctx.rawClass;
List<String> classNameParts = new LinkedList();
for (Token p : ctx.paths) {
classNameParts.add(p.getText());
}
if (ctx.innerClass != null) {
classNameParts.add(rawTypeToken.getText() + "$" + ctx.innerClass.getText());
} else {
classNameParts.add(rawTypeToken.getText());
}
String rawType = String.join(".", classNameParts);
for (GenericType gt : thisClazz.getGenericTypes()) {
if (rawType.equals(gt.getName()))
return gt;
}
ObjectType clazzType = requireClassType(rawType, rawTypeToken);
if (clazzType == null)
return null;
ClassNode clazzNode = clazzType.getClassNode();
GenericType[] clzDeclaredGenericTypes = clazzNode.getGenericTypes();
List<KalangParser.ParameterizedElementTypeContext> parameterTypes = ctx.parameterTypes;
if (parameterTypes != null && !parameterTypes.isEmpty()) {
Type[] typeArguments = new Type[parameterTypes.size()];
if (parameterTypes != null && parameterTypes.size() > 0) {
if (clzDeclaredGenericTypes.length != parameterTypes.size()) {
diagnosisReporter.report(Diagnosis.Kind.ERROR, "wrong number of type arguments", ctx);
return null;
}
for (int i = 0; i < typeArguments.length; i++) {
typeArguments[i] = parseParameterizedElementType(parameterTypes.get(i));
// TODO should return null?
if (typeArguments[i] == null)
return null;
}
}
return Types.getClassType(clazzType.getClassNode(), typeArguments, nullable);
} else {
return Types.getClassType(clazzType.getClassNode(), nullable);
}
}
use of kalang.ast.ClassNode in project kalang by kasonyang.
the class AstBuilder method visitAnnotation.
@Override
@Nullable
public AnnotationNode visitAnnotation(KalangParser.AnnotationContext ctx) {
ClassNode anType = requireAst(ctx.annotationType);
if (anType == null)
return null;
List<Token> vk = ctx.annotationValueKey;
LiteralContext dv = ctx.annotationDefaultValue;
AnnotationNode anNode = new AnnotationNode(anType);
if (vk != null && vk.size() > 0) {
List<LiteralContext> anValues = ctx.annotationValue;
int ksize = vk.size();
for (int i = 0; i < ksize; i++) {
String kname = vk.get(i).getText();
ConstExpr value = visitLiteral(anValues.get(i));
anNode.values.put(kname, value);
}
} else if (dv != null) {
ConstExpr defaultValue = visitLiteral(dv);
anNode.values.put("value", defaultValue);
}
if (!semanticAnalyzer.validateAnnotation(anNode))
return null;
// TODO validate annotation's values
return anNode;
}
use of kalang.ast.ClassNode in project kalang by kasonyang.
the class AstLoader method loadAst.
@Nonnull
public ClassNode loadAst(@Nonnull String className) throws AstNotFoundException {
ClassNode ast = cachedAsts.get(className);
if (ast != null)
return ast;
if (parent != null) {
try {
return parent.loadAst(className);
} catch (AstNotFoundException ex) {
}
}
if (className.endsWith("[]")) {
String name = className;
name = name.substring(0, name.length() - 2);
ast = AstUtil.createArrayAst(loadAst(name).name);
} else {
ast = findAst(className);
if (ast == null)
throw new AstNotFoundException(className);
}
cachedAsts.put(className, ast);
return ast;
}
Aggregations