Search in sources :

Example 1 with MethodNode

use of kalang.ast.MethodNode in project kalang by kasonyang.

the class AstBuilder method visitMethods.

private void visitMethods(ClassNode clazz) {
    thisClazz = clazz;
    for (MethodNode m : thisClazz.getDeclaredMethodNodes()) {
        BlockStmt mbody = m.getBody();
        StatContext[] stats = classNodeMetaBuilder.getStatContexts(m);
        if (stats != null) {
            method = m;
            returned = false;
            visitBlockStmt(stats, mbody);
            boolean needReturn = (m.getType() != null && !m.getType().equals(Types.VOID_TYPE));
            if (m.getBody() != null && needReturn && !returned) {
                this.diagnosisReporter.report(Diagnosis.Kind.ERROR, "Missing return statement in method:" + MethodUtil.toString(method), classNodeMetaBuilder.getMethodDeclContext(m));
            }
            new InitializationAnalyzer(compilationUnit, astLoader).check(clazz, m);
        }
        if (AstUtil.isConstructor(m)) {
            @SuppressWarnings("null") List<Statement> bodyStmts = mbody.statements;
            if (!AstUtil.hasConstructorCallStatement(bodyStmts)) {
                try {
                    bodyStmts.add(0, AstUtil.createDefaultSuperConstructorCall(thisClazz));
                } catch (MethodNotFoundException | AmbiguousMethodException ex) {
                    diagnosisReporter.report(Diagnosis.Kind.ERROR, "default constructor not found", classNodeMetaBuilder.getMethodDeclContext(m));
                }
            }
            // check super()
            int stmtsSize = mbody.statements.size();
            assert stmtsSize > 0;
            Statement firstStmt = mbody.statements.get(0);
            if (!AstUtil.isConstructorCallStatement(firstStmt)) {
                // TODO handle error
                throw new RuntimeException("missing constructor call");
            }
            mbody.statements.addAll(1, this.thisClazz.initStmts);
        }
    }
    for (ClassNode c : clazz.classes) {
        this.visitMethods(c);
    }
}
Also used : ClassNode(kalang.ast.ClassNode) Statement(kalang.ast.Statement) BlockStmt(kalang.ast.BlockStmt) IfStatContext(kalang.antlr.KalangParser.IfStatContext) ContinueStatContext(kalang.antlr.KalangParser.ContinueStatContext) ExprStatContext(kalang.antlr.KalangParser.ExprStatContext) WhileStatContext(kalang.antlr.KalangParser.WhileStatContext) BreakStatContext(kalang.antlr.KalangParser.BreakStatContext) StatContext(kalang.antlr.KalangParser.StatContext) TryStatContext(kalang.antlr.KalangParser.TryStatContext) ForStatContext(kalang.antlr.KalangParser.ForStatContext) ReturnStatContext(kalang.antlr.KalangParser.ReturnStatContext) VarDeclStatContext(kalang.antlr.KalangParser.VarDeclStatContext) DoWhileStatContext(kalang.antlr.KalangParser.DoWhileStatContext) MethodNode(kalang.ast.MethodNode) MethodNotFoundException(kalang.MethodNotFoundException) AmbiguousMethodException(kalang.AmbiguousMethodException)

Example 2 with MethodNode

use of kalang.ast.MethodNode in project kalang by kasonyang.

the class ClassNodeMetaBuilder method visitClassDef.

@Override
public Object visitClassDef(KalangParser.ClassDefContext ctx) {
    thisClazz.annotations.addAll(astBuilder.getAnnotations(ctx.annotation()));
    thisClazz.modifier = astBuilder.parseModifier(ctx.varModifier());
    List<Token> gnrTypes = ctx.genericTypes;
    if (gnrTypes != null && !gnrTypes.isEmpty()) {
        for (Token g : gnrTypes) {
            // TODO suport generic type bounds in syntax
            GenericType gt = new GenericType(g.getText(), Types.getRootType(), null, NullableKind.NONNULL);
            thisClazz.declareGenericType(gt);
        }
    }
    ObjectType superType = null;
    if (ctx.parentClass != null) {
        ObjectType parentClass = astBuilder.parseClassType(ctx.parentClass);
        if (parentClass != null) {
            superType = parentClass;
        }
    } else {
        superType = Types.getRootType();
    }
    if (Modifier.isInterface(thisClazz.modifier)) {
        // TODO update syntax to support:interface extends T1,T2...
        thisClazz.addInterface(superType);
    } else {
        thisClazz.setSuperType(superType);
    }
    if (ctx.interfaces != null && ctx.interfaces.size() > 0) {
        for (KalangParser.ClassTypeContext itf : ctx.interfaces) {
            ObjectType itfClz = astBuilder.parseClassType(itf);
            if (itfClz != null) {
                thisClazz.addInterface(itfClz);
            }
        }
    }
    if (this.isDeclaringNonStaticInnerClass()) {
        ClassNode parentClass = thisClazz.enclosingClass;
        if (parentClass == null) {
            throw Exceptions.unexceptedValue(parentClass);
        }
        thisClazz.createField(Types.getClassType(parentClass), "this$0", Modifier.PRIVATE | ModifierConstant.SYNTHETIC);
    }
    visit(ctx.classBody());
    if (!ModifierUtil.isInterface(thisClazz.modifier) && !AstUtil.containsConstructor(thisClazz) && !AstUtil.createEmptyConstructor(thisClazz)) {
        this.diagnosisReporter.report(Diagnosis.Kind.ERROR, "failed to create constructor with no parameters", ctx);
    }
    MethodNode[] methods = thisClazz.getDeclaredMethodNodes();
    for (int i = 0; i < methods.length; i++) {
        MethodNode node = methods[i];
        BlockStmt body = node.getBody();
        if (body != null) {
            if (AstUtil.isConstructor(node)) {
                // constructor
                if (this.isDeclaringNonStaticInnerClass()) {
                    ClassNode enclosingClass = thisClazz.enclosingClass;
                    if (enclosingClass == null) {
                        throw Exceptions.unexceptedValue(enclosingClass);
                    }
                    ParameterNode outerInstanceParam = node.createParameter(0, Types.getClassType(enclosingClass), "this$0");
                    ExprNode parentFieldExpr = astBuilder.getObjectFieldExpr(new ThisExpr(Types.getClassType(thisClazz)), "this$0", ParserRuleContext.EMPTY);
                    if (parentFieldExpr == null) {
                        throw Exceptions.unexceptedValue(parentFieldExpr);
                    }
                    body.statements.add(1, new ExprStmt(new AssignExpr((AssignableExpr) parentFieldExpr, new ParameterExpr(outerInstanceParam))));
                }
            }
        }
    }
    for (FieldNode fieldNode : thisClazz.getFields()) {
        int mdf = fieldNode.modifier;
        if (!AstUtil.hasGetter(thisClazz, fieldNode)) {
            AstUtil.createGetter(thisClazz, fieldNode, mdf);
        }
        if (!AstUtil.hasSetter(thisClazz, fieldNode)) {
            AstUtil.createSetter(thisClazz, fieldNode, mdf);
        }
        fieldNode.modifier = ModifierUtil.setPrivate(mdf);
    }
    return null;
}
Also used : ClassNode(kalang.ast.ClassNode) GenericType(kalang.core.GenericType) FieldNode(kalang.ast.FieldNode) ParameterExpr(kalang.ast.ParameterExpr) BlockStmt(kalang.ast.BlockStmt) Token(org.antlr.v4.runtime.Token) AssignExpr(kalang.ast.AssignExpr) ExprNode(kalang.ast.ExprNode) ObjectType(kalang.core.ObjectType) KalangParser(kalang.antlr.KalangParser) MethodNode(kalang.ast.MethodNode) ParameterNode(kalang.ast.ParameterNode) ExprStmt(kalang.ast.ExprStmt) ThisExpr(kalang.ast.ThisExpr)

Example 3 with MethodNode

use of kalang.ast.MethodNode in project kalang by kasonyang.

the class JvmClassNode method getDeclaredMethodNodes.

@Override
public MethodNode[] getDeclaredMethodNodes() {
    if (!this.methodsInitialized) {
        this.methodsInitialized = true;
        List<Executable> methods = new LinkedList();
        methods.addAll(Arrays.asList(clazz.getDeclaredMethods()));
        methods.addAll(Arrays.asList(clazz.getDeclaredConstructors()));
        for (Executable m : methods) {
            NullableKind nullable = getNullable(m.getAnnotations());
            Type mType;
            String mName;
            int mModifier;
            if (m instanceof Method) {
                mType = getType(((Method) m).getGenericReturnType(), getGenericTypeMap(), ((Method) m).getReturnType(), nullable);
                mName = m.getName();
                mModifier = m.getModifiers();
            } else if (m instanceof Constructor) {
                mName = "<init>";
                // getType(clz);
                mType = Types.VOID_TYPE;
                // | Modifier.STATIC;
                mModifier = m.getModifiers();
            } else {
                throw Exceptions.unexceptedValue(m);
            }
            MethodNode methodNode = createMethodNode(mType, mName, mModifier);
            for (Parameter p : m.getParameters()) {
                NullableKind pnullable = getNullable(p.getAnnotations());
                methodNode.createParameter(getType(p.getParameterizedType(), getGenericTypeMap(), p.getType(), pnullable), p.getName());
            }
            for (Class e : m.getExceptionTypes()) {
                methodNode.addExceptionType(getType(e, getGenericTypeMap(), e, NullableKind.NONNULL));
            }
        }
    }
    return super.getDeclaredMethodNodes();
}
Also used : GenericArrayType(java.lang.reflect.GenericArrayType) Type(kalang.core.Type) ObjectType(kalang.core.ObjectType) GenericType(kalang.core.GenericType) WildcardType(kalang.core.WildcardType) ClassType(kalang.core.ClassType) MethodNode(kalang.ast.MethodNode) NullableKind(kalang.core.NullableKind) Constructor(java.lang.reflect.Constructor) Parameter(java.lang.reflect.Parameter) Method(java.lang.reflect.Method) Executable(java.lang.reflect.Executable) LinkedList(java.util.LinkedList)

Example 4 with MethodNode

use of kalang.ast.MethodNode in project kalang by kasonyang.

the class AstUtil method createSetter.

public static void createSetter(ClassNode clazz, FieldDescriptor field, int accessModifier) {
    String fn = field.getName();
    String setterName = "set" + NameUtil.firstCharToUpperCase(fn);
    boolean isStatic = isStatic(field.getModifier());
    if (isStatic) {
        accessModifier |= Modifier.STATIC;
    }
    MethodNode setter = clazz.createMethodNode(Types.VOID_TYPE, setterName, accessModifier);
    // setter.offset = field.offset;
    ParameterNode param = setter.createParameter(field.getType(), field.getName());
    BlockStmt body = setter.getBody();
    FieldExpr fe;
    ExprNode paramVal = new ParameterExpr(param);
    ClassReference cr = new ClassReference(clazz);
    if (isStatic) {
        fe = new StaticFieldExpr(cr, field);
    } else {
        fe = new ObjectFieldExpr(new ThisExpr(Types.getClassType(clazz)), field);
    }
    body.statements.add(new ExprStmt(new AssignExpr(fe, paramVal)));
}
Also used : ParameterExpr(kalang.ast.ParameterExpr) BlockStmt(kalang.ast.BlockStmt) AssignExpr(kalang.ast.AssignExpr) ExprNode(kalang.ast.ExprNode) StaticFieldExpr(kalang.ast.StaticFieldExpr) ObjectFieldExpr(kalang.ast.ObjectFieldExpr) MethodNode(kalang.ast.MethodNode) ParameterNode(kalang.ast.ParameterNode) ExprStmt(kalang.ast.ExprStmt) ClassReference(kalang.ast.ClassReference) StaticFieldExpr(kalang.ast.StaticFieldExpr) FieldExpr(kalang.ast.FieldExpr) ObjectFieldExpr(kalang.ast.ObjectFieldExpr) ThisExpr(kalang.ast.ThisExpr)

Example 5 with MethodNode

use of kalang.ast.MethodNode in project kalang by kasonyang.

the class AstUtil method createEmptyConstructor.

public static boolean createEmptyConstructor(ClassNode clazzNode) {
    ObjectType supType = clazzNode.getSuperType();
    if (supType == null) {
        throw new RuntimeException("super type is null:" + clazzNode.name);
    }
    ConstructorDescriptor[] constructors = supType.getConstructorDescriptors(clazzNode);
    ConstructorDescriptor m = MethodUtil.getConstructorDescriptor(constructors, null);
    if (m != null) {
        MethodNode mm = clazzNode.createMethodNode(Types.VOID_TYPE, m.getName(), m.getModifier());
        for (Type e : m.getExceptionTypes()) mm.addExceptionType(e);
        ParameterDescriptor[] pds = m.getParameterDescriptors();
        for (ParameterDescriptor pd : pds) {
            ParameterNode p = mm.createParameter(pd.getType(), pd.getName());
            // TODO update mm.createParameter
            p.modifier = pd.getModifier();
        }
        BlockStmt body = mm.getBody();
        ParameterNode[] parameters = mm.getParameters();
        ExprNode[] params = new ExprNode[parameters.length];
        for (int i = 0; i < params.length; i++) {
            params[i] = new ParameterExpr(parameters[i]);
        }
        body.statements.add(new ExprStmt(new ObjectInvokeExpr(new SuperExpr(clazzNode), m, params)));
        return true;
    } else {
        return false;
    }
}
Also used : SuperExpr(kalang.ast.SuperExpr) ParameterExpr(kalang.ast.ParameterExpr) ParameterDescriptor(kalang.core.ParameterDescriptor) BlockStmt(kalang.ast.BlockStmt) ConstructorDescriptor(kalang.core.ConstructorDescriptor) ExprNode(kalang.ast.ExprNode) ObjectType(kalang.core.ObjectType) ArrayType(kalang.core.ArrayType) Type(kalang.core.Type) ObjectType(kalang.core.ObjectType) GenericType(kalang.core.GenericType) ClassType(kalang.core.ClassType) MethodNode(kalang.ast.MethodNode) ParameterNode(kalang.ast.ParameterNode) ExprStmt(kalang.ast.ExprStmt) ObjectInvokeExpr(kalang.ast.ObjectInvokeExpr)

Aggregations

MethodNode (kalang.ast.MethodNode)10 BlockStmt (kalang.ast.BlockStmt)6 GenericType (kalang.core.GenericType)5 ObjectType (kalang.core.ObjectType)5 ExprStmt (kalang.ast.ExprStmt)4 ParameterExpr (kalang.ast.ParameterExpr)4 ParameterNode (kalang.ast.ParameterNode)4 Type (kalang.core.Type)4 ExprNode (kalang.ast.ExprNode)3 ThisExpr (kalang.ast.ThisExpr)3 ClassType (kalang.core.ClassType)3 LinkedList (java.util.LinkedList)2 AmbiguousMethodException (kalang.AmbiguousMethodException)2 MethodNotFoundException (kalang.MethodNotFoundException)2 KalangParser (kalang.antlr.KalangParser)2 AssignExpr (kalang.ast.AssignExpr)2 ClassNode (kalang.ast.ClassNode)2 ClassReference (kalang.ast.ClassReference)2 FieldExpr (kalang.ast.FieldExpr)2 ObjectFieldExpr (kalang.ast.ObjectFieldExpr)2