Search in sources :

Example 1 with FunType

use of org.yinwang.pysonar.types.FunType in project pysonar2 by yinwang0.

the class Analyzer method applyUncalled.

public void applyUncalled() {
    Progress progress = new Progress(uncalled.size(), 50);
    while (!uncalled.isEmpty()) {
        List<FunType> uncalledDup = new ArrayList<>(uncalled);
        for (FunType cl : uncalledDup) {
            progress.tick();
            inferencer.apply(cl, null, null, null, null, null, null);
        }
    }
}
Also used : ArrayList(java.util.ArrayList) FunType(org.yinwang.pysonar.types.FunType)

Example 2 with FunType

use of org.yinwang.pysonar.types.FunType in project pysonar2 by yinwang0.

the class JSONDump method writeSymJson.

private static void writeSymJson(Binding binding, JsonGenerator json) throws IOException {
    if (binding.start < 0) {
        return;
    }
    String name = binding.name;
    boolean isExported = !(Binding.Kind.VARIABLE == binding.kind || Binding.Kind.PARAMETER == binding.kind || Binding.Kind.SCOPE == binding.kind || Binding.Kind.ATTRIBUTE == binding.kind || (name.length() == 0 || name.charAt(0) == '_' || name.startsWith("lambda%")));
    String path = binding.qname.replace('.', '/').replace("%20", ".");
    if (!seenDef.contains(path)) {
        seenDef.add(path);
        json.writeStartObject();
        json.writeStringField("name", name);
        json.writeStringField("path", path);
        json.writeStringField("file", binding.fileOrUrl);
        json.writeNumberField("identStart", binding.start);
        json.writeNumberField("identEnd", binding.end);
        json.writeNumberField("defStart", binding.bodyStart);
        json.writeNumberField("defEnd", binding.bodyEnd);
        json.writeBooleanField("exported", isExported);
        json.writeStringField("kind", binding.kind.toString());
        if (Binding.Kind.FUNCTION == binding.kind || Binding.Kind.METHOD == binding.kind || Binding.Kind.CONSTRUCTOR == binding.kind) {
            json.writeObjectFieldStart("funcData");
            // get args expression
            String argExpr = null;
            Type t = binding.type;
            if (t instanceof UnionType) {
                t = ((UnionType) t).firstUseful();
            }
            if (t != null && t instanceof FunType) {
                FunctionDef func = ((FunType) t).func;
                if (func != null) {
                    argExpr = func.getArgumentExpr();
                }
            }
            String typeExpr = binding.type.toString();
            json.writeNullField("params");
            String signature = argExpr == null ? "" : argExpr + "\n" + typeExpr;
            json.writeStringField("signature", signature);
            json.writeEndObject();
        }
        json.writeEndObject();
    }
}
Also used : UnionType(org.yinwang.pysonar.types.UnionType) Type(org.yinwang.pysonar.types.Type) UnionType(org.yinwang.pysonar.types.UnionType) FunType(org.yinwang.pysonar.types.FunType) FunType(org.yinwang.pysonar.types.FunType) FunctionDef(org.yinwang.pysonar.ast.FunctionDef)

Example 3 with FunType

use of org.yinwang.pysonar.types.FunType in project pysonar2 by yinwang0.

the class TypeInferencer method apply.

@NotNull
public Type apply(@NotNull FunType func, @Nullable Type selfType, @Nullable List<Type> positional, @Nullable Map<String, Type> kwTypes, @Nullable Type kwArg, @Nullable Type starArg, @Nullable Node call) {
    if (call instanceof Call && ((Call) call).func instanceof Attribute && ((Attribute) ((Call) call).func).attr.id.equals("append")) {
        if (selfType instanceof ListType) {
            ListType listType = (ListType) selfType;
            if (positional != null && positional.size() == 1) {
                listType.add(positional.get(0));
            } else {
                Analyzer.self.putProblem(call, "Calling append with wrong argument types");
            }
        }
    }
    if (call instanceof Call && ((Call) call).func instanceof Attribute && ((Attribute) ((Call) call).func).attr.id.equals("update")) {
        if (selfType instanceof DictType) {
            DictType dict = (DictType) selfType;
            if (positional != null && positional.size() == 1) {
                Type argType = positional.get(0);
                if (argType instanceof DictType) {
                    dict.keyType = UnionType.union(dict.keyType, ((DictType) argType).keyType);
                    dict.valueType = UnionType.union(dict.valueType, ((DictType) argType).valueType);
                }
            } else {
                Analyzer.self.putProblem(call, "Calling update with wrong argument types");
            }
        }
    }
    Analyzer.self.removeUncalled(func);
    if (func.func != null && !func.func.called) {
        Analyzer.self.nCalled++;
        func.func.called = true;
    }
    if (func.func == null) {
        // func without definition (possibly builtins)
        return func.getReturnType();
    }
    List<Type> argTypes = new ArrayList<>();
    // Add class or object as first argument if it is not static method
    if (!func.func.isStaticMethod()) {
        if (func.func.isClassMethod()) {
            if (func.cls != null) {
                argTypes.add(func.cls);
            } else if (selfType != null && selfType instanceof InstanceType) {
                argTypes.add(((InstanceType) selfType).classType);
            }
        } else {
            // usual method
            if (selfType != null) {
                argTypes.add(selfType);
            } else {
                if (func.cls != null) {
                    if (!func.func.name.id.equals("__init__")) {
                        argTypes.add(func.cls.getInstance(null, this, call));
                    } else {
                        argTypes.add(func.cls.getInstance());
                    }
                }
            }
        }
    }
    // Put in positional arguments
    if (positional != null) {
        argTypes.addAll(positional);
    }
    bindMethodAttrs(func);
    State callState = new State(func.env, State.StateType.FUNCTION);
    if (func.table.parent != null) {
        callState.setPath(func.table.parent.extendPath(func.func.name.id));
    } else {
        callState.setPath(func.func.name.id);
    }
    Type fromType = bindParams(callState, func.func, argTypes, func.defaultTypes, kwTypes, kwArg, starArg);
    Type cachedTo = func.getMapping(fromType);
    if (cachedTo != null) {
        return cachedTo;
    } else if (func.oversized()) {
        return Types.UNKNOWN;
    } else {
        func.addMapping(fromType, Types.UNKNOWN);
        Analyzer.self.callStack.push(new CallStackEntry(func, fromType));
        Type toType = visit(func.func.body, callState);
        Analyzer.self.callStack.pop();
        if (missingReturn(toType)) {
            addWarningToNode(func.func.name, "Function not always return a value");
            if (call != null) {
                addWarningToNode(call, "Call not always return a value");
            }
        }
        toType = UnionType.remove(toType, Types.CONT);
        if (!func.func.name.id.equals("__init__")) {
            func.addMapping(fromType, toType);
        } else {
            func.removeMapping(fromType);
        }
        return toType;
    }
}
Also used : ClassType(org.yinwang.pysonar.types.ClassType) ListType(org.yinwang.pysonar.types.ListType) DictType(org.yinwang.pysonar.types.DictType) InstanceType(org.yinwang.pysonar.types.InstanceType) Type(org.yinwang.pysonar.types.Type) UnionType(org.yinwang.pysonar.types.UnionType) TupleType(org.yinwang.pysonar.types.TupleType) FunType(org.yinwang.pysonar.types.FunType) ModuleType(org.yinwang.pysonar.types.ModuleType) State(org.yinwang.pysonar.State) ListType(org.yinwang.pysonar.types.ListType) DictType(org.yinwang.pysonar.types.DictType) ArrayList(java.util.ArrayList) CallStackEntry(org.yinwang.pysonar.CallStackEntry) InstanceType(org.yinwang.pysonar.types.InstanceType) NotNull(org.jetbrains.annotations.NotNull)

Example 4 with FunType

use of org.yinwang.pysonar.types.FunType in project pysonar2 by yinwang0.

the class TypeInferencer method visit.

@NotNull
@Override
public Type visit(Call node, State s) {
    Type fun;
    Type selfType = null;
    if (node.func instanceof Attribute) {
        Node target = ((Attribute) node.func).target;
        Name attr = ((Attribute) node.func).attr;
        selfType = visit(target, s);
        Set<Binding> b = selfType.table.lookupAttr(attr.id);
        if (b != null) {
            Analyzer.self.putRef(attr, b);
            fun = State.makeUnion(b);
        } else {
            Analyzer.self.putProblem(attr, "Attribute is not found in type: " + attr.id);
            fun = Types.UNKNOWN;
        }
    } else {
        fun = visit(node.func, s);
    }
    // Infer positional argument types
    List<Type> positional = visit(node.args, s);
    // Infer keyword argument types
    Map<String, Type> kwTypes = new HashMap<>();
    if (node.keywords != null) {
        for (Keyword k : node.keywords) {
            kwTypes.put(k.arg, visit(k.value, s));
        }
    }
    Type kwArg = node.kwargs == null ? null : visit(node.kwargs, s);
    Type starArg = node.starargs == null ? null : visit(node.starargs, s);
    if (fun instanceof UnionType) {
        Set<Type> types = ((UnionType) fun).types;
        Type resultType = Types.UNKNOWN;
        for (Type funType : types) {
            Type returnType = resolveCall(funType, selfType, positional, kwTypes, kwArg, starArg, node);
            resultType = UnionType.union(resultType, returnType);
        }
        return resultType;
    } else {
        return resolveCall(fun, selfType, positional, kwTypes, kwArg, starArg, node);
    }
}
Also used : Binding(org.yinwang.pysonar.Binding) UnionType(org.yinwang.pysonar.types.UnionType) HashMap(java.util.HashMap) ClassType(org.yinwang.pysonar.types.ClassType) ListType(org.yinwang.pysonar.types.ListType) DictType(org.yinwang.pysonar.types.DictType) InstanceType(org.yinwang.pysonar.types.InstanceType) Type(org.yinwang.pysonar.types.Type) UnionType(org.yinwang.pysonar.types.UnionType) TupleType(org.yinwang.pysonar.types.TupleType) FunType(org.yinwang.pysonar.types.FunType) ModuleType(org.yinwang.pysonar.types.ModuleType) NotNull(org.jetbrains.annotations.NotNull)

Example 5 with FunType

use of org.yinwang.pysonar.types.FunType in project pysonar2 by yinwang0.

the class FunTypeEqualFunction method equals.

public boolean equals(Object x, Object y) {
    if (x instanceof FunType && y instanceof FunType) {
        FunType xx = (FunType) x;
        FunType yy = (FunType) y;
        return xx == yy || xx.table.path.equals(yy.table.path);
    } else {
        return x.equals(y);
    }
}
Also used : FunType(org.yinwang.pysonar.types.FunType)

Aggregations

FunType (org.yinwang.pysonar.types.FunType)7 Type (org.yinwang.pysonar.types.Type)5 UnionType (org.yinwang.pysonar.types.UnionType)5 ClassType (org.yinwang.pysonar.types.ClassType)4 DictType (org.yinwang.pysonar.types.DictType)4 InstanceType (org.yinwang.pysonar.types.InstanceType)4 ListType (org.yinwang.pysonar.types.ListType)4 ModuleType (org.yinwang.pysonar.types.ModuleType)4 TupleType (org.yinwang.pysonar.types.TupleType)4 NotNull (org.jetbrains.annotations.NotNull)3 ArrayList (java.util.ArrayList)2 Binding (org.yinwang.pysonar.Binding)2 State (org.yinwang.pysonar.State)2 HashMap (java.util.HashMap)1 CallStackEntry (org.yinwang.pysonar.CallStackEntry)1 FunctionDef (org.yinwang.pysonar.ast.FunctionDef)1