use of kalang.ast.AnnotationNode in project kalang by kasonyang.
the class Ast2Class method annotation.
protected void annotation(Object obj, AnnotationNode... annotations) {
for (AnnotationNode an : annotations) {
AnnotationVisitor av;
String desc = getTypeDescriptor(Types.getClassType(an.getAnnotationType()));
// TODO set annotation visible
boolean isVisible = true;
if (obj instanceof ClassWriter) {
av = ((ClassWriter) obj).visitAnnotation(desc, isVisible);
} else if (obj instanceof MethodVisitor) {
av = ((MethodVisitor) obj).visitAnnotation(desc, isVisible);
} else {
throw Exceptions.unsupportedTypeException(obj);
}
for (String v : an.values.keySet()) {
// TODO handle enum value
Object javaConst = getJavaConst(an.values.get(v));
av.visit(v, javaConst);
}
}
}
use of kalang.ast.AnnotationNode 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.AnnotationNode in project kalang by kasonyang.
the class ClassNodeMetaBuilder method visitMethodDecl.
@Override
public Object visitMethodDecl(KalangParser.MethodDeclContext ctx) {
String name;
Type type;
boolean isOverriding = ctx.OVERRIDE() != null;
if (ctx.prefix != null && ctx.prefix.getText().equals("constructor")) {
type = Types.VOID_TYPE;
name = "<init>";
} else {
if (ctx.type() == null) {
type = Types.VOID_TYPE;
} else {
type = astBuilder.parseType(ctx.returnType);
}
name = ctx.name.getText();
}
List<KalangParser.TypeContext> paramTypesCtx = ctx.paramTypes;
int modifier = astBuilder.parseModifier(ctx.varModifier());
Type[] paramTypes;
String[] paramNames;
if (paramTypesCtx != null) {
int paramSize = paramTypesCtx.size();
paramTypes = new Type[paramSize];
paramNames = new String[paramSize];
for (int i = 0; i < paramSize; i++) {
KalangParser.TypeContext t = paramTypesCtx.get(i);
paramTypes[i] = astBuilder.parseType(t);
paramNames[i] = ctx.paramIds.get(i).getText();
}
} else {
paramTypes = new Type[0];
paramNames = new String[0];
}
// check method duplicated before generate java stub
String mStr = MethodUtil.getDeclarationKey(name, paramTypes);
boolean existed = Arrays.asList(thisClazz.getDeclaredMethodNodes()).stream().anyMatch((m) -> {
return MethodUtil.getDeclarationKey(m).equals(mStr);
});
if (existed) {
// TODO should remove the duplicated method
diagnosisReporter.report(Diagnosis.Kind.ERROR, "declare method duplicately:" + mStr, ctx);
return null;
}
KalangParser.BlockStmtContext blockStmt = ctx.blockStmt();
if (blockStmt == null) {
if (ModifierUtil.isInterface(thisClazz.modifier)) {
modifier |= Modifier.ABSTRACT;
} else if (!Modifier.isAbstract(modifier)) {
diagnosisReporter.report(Diagnosis.Kind.ERROR, "method body required", ctx);
} else if (!Modifier.isAbstract(thisClazz.modifier)) {
diagnosisReporter.report(Diagnosis.Kind.ERROR, "declare abstract method in non-abstract class", ctx);
}
}
method = thisClazz.createMethodNode(type, name, modifier);
for (int i = 0; i < paramTypes.length; i++) {
method.createParameter(paramTypes[i], paramNames[i]);
}
for (AnnotationNode a : astBuilder.getAnnotations(ctx.annotation())) method.addAnnotation(a);
ObjectType superType = thisClazz.getSuperType();
if (superType == null) {
// the superType of interface may be null
superType = Types.getRootType();
}
MethodDescriptor overriddenMd = ClassTypeUtil.getMethodDescriptor(superType, mStr, thisClazz, true, true);
if (overriddenMd == null) {
overriddenMd = ClassTypeUtil.getMethodDescriptor(thisClazz.getInterfaces(), mStr, thisClazz, true, true);
}
if (isOverriding && overriddenMd == null) {
diagnosisReporter.report(Diagnosis.Kind.ERROR, "method does not override or implement a method from a supertype", ctx);
}
if (!isOverriding && overriddenMd != null) {
diagnosisReporter.report(Diagnosis.Kind.ERROR, "method overrides or implements a method from a supertype", ctx);
}
this.methodContexts.put(method, ctx);
KalangParser.BlockStmtContext bstm = ctx.blockStmt();
if (bstm != null) {
List<KalangParser.StatContext> stats = bstm.stat();
if (stats != null)
this.methodStatsContexts.put(method, stats.toArray(new KalangParser.StatContext[stats.size()]));
}
if (ctx.exceptionTypes != null) {
for (Token et : ctx.exceptionTypes) {
ObjectType exType = astBuilder.requireClassType(et);
if (exType != null) {
method.addExceptionType(exType);
}
}
}
astBuilder.mapAst(method, ctx);
MethodNode m = method;
method = null;
return m;
}
Aggregations