Search in sources :

Example 1 with AnnotationNode

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);
        }
    }
}
Also used : AnnotationNode(kalang.ast.AnnotationNode) AnnotationVisitor(org.objectweb.asm.AnnotationVisitor) VarObject(kalang.ast.VarObject) ClassWriter(org.objectweb.asm.ClassWriter) MethodVisitor(org.objectweb.asm.MethodVisitor)

Example 2 with AnnotationNode

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;
}
Also used : LiteralContext(kalang.antlr.KalangParser.LiteralContext) ClassNode(kalang.ast.ClassNode) ConstExpr(kalang.ast.ConstExpr) AnnotationNode(kalang.ast.AnnotationNode) Token(org.antlr.v4.runtime.Token) Nullable(javax.annotation.Nullable)

Example 3 with AnnotationNode

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;
}
Also used : Token(org.antlr.v4.runtime.Token) MethodDescriptor(kalang.core.MethodDescriptor) ObjectType(kalang.core.ObjectType) Type(kalang.core.Type) ObjectType(kalang.core.ObjectType) GenericType(kalang.core.GenericType) KalangParser(kalang.antlr.KalangParser) MethodNode(kalang.ast.MethodNode) AnnotationNode(kalang.ast.AnnotationNode)

Aggregations

AnnotationNode (kalang.ast.AnnotationNode)3 Token (org.antlr.v4.runtime.Token)2 Nullable (javax.annotation.Nullable)1 KalangParser (kalang.antlr.KalangParser)1 LiteralContext (kalang.antlr.KalangParser.LiteralContext)1 ClassNode (kalang.ast.ClassNode)1 ConstExpr (kalang.ast.ConstExpr)1 MethodNode (kalang.ast.MethodNode)1 VarObject (kalang.ast.VarObject)1 GenericType (kalang.core.GenericType)1 MethodDescriptor (kalang.core.MethodDescriptor)1 ObjectType (kalang.core.ObjectType)1 Type (kalang.core.Type)1 AnnotationVisitor (org.objectweb.asm.AnnotationVisitor)1 ClassWriter (org.objectweb.asm.ClassWriter)1 MethodVisitor (org.objectweb.asm.MethodVisitor)1