Search in sources :

Example 1 with ListType

use of org.yinwang.pysonar.types.ListType 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 2 with ListType

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

the class ImportFrom method importStar.

public void importStar(@NotNull State s, @Nullable Type mt) {
    if (mt == null || mt.file == null) {
        return;
    }
    Node node = Analyzer.self.getAstForFile(mt.file);
    if (node == null) {
        return;
    }
    List<String> names = new ArrayList<>();
    Type allType = mt.table.lookupType("__all__");
    if (allType != null && allType instanceof ListType) {
        ListType lt = (ListType) allType;
        for (Object o : lt.values) {
            if (o instanceof String) {
                names.add((String) o);
            }
        }
    }
    if (!names.isEmpty()) {
        int start = this.start;
        int col = this.col;
        for (String name : names) {
            Set<Binding> b = mt.table.lookupLocal(name);
            if (b != null) {
                s.update(name, b);
            } else {
                List<Name> m2 = new ArrayList<>(module);
                Name fakeName = new Name(name, this.file, start, start + name.length(), this.line, col);
                m2.add(fakeName);
                Type type = Analyzer.self.loadModule(m2, s);
                if (type != null) {
                    start += name.length();
                    col += name.length();
                    s.insert(name, fakeName, type, Binding.Kind.VARIABLE);
                }
            }
        }
    } else {
        // Fall back to importing all names not starting with "_".
        for (Entry<String, Set<Binding>> e : mt.table.entrySet()) {
            if (!e.getKey().startsWith("_")) {
                s.update(e.getKey(), e.getValue());
            }
        }
    }
}
Also used : Binding(org.yinwang.pysonar.Binding) Set(java.util.Set) ArrayList(java.util.ArrayList) Type(org.yinwang.pysonar.types.Type) ListType(org.yinwang.pysonar.types.ListType) ListType(org.yinwang.pysonar.types.ListType)

Example 3 with ListType

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

the class TypeInferencer method bindParams.

@NotNull
private Type bindParams(@NotNull State state, @NotNull FunctionDef func, @Nullable List<Type> pTypes, @Nullable List<Type> dTypes, @Nullable Map<String, Type> hash, @Nullable Type kw, @Nullable Type star) {
    List<Node> args = func.args;
    Name rest = func.vararg;
    Name restKw = func.kwarg;
    TupleType fromType = new TupleType();
    int pSize = args == null ? 0 : args.size();
    int aSize = pTypes == null ? 0 : pTypes.size();
    int dSize = dTypes == null ? 0 : dTypes.size();
    int nPos = pSize - dSize;
    if (star != null && star instanceof ListType) {
        star = ((ListType) star).toTupleType();
    }
    for (int i = 0, j = 0; i < pSize; i++) {
        Node arg = args.get(i);
        Type aType;
        if (i < aSize) {
            aType = pTypes.get(i);
        } else if (i - nPos >= 0 && i - nPos < dSize) {
            aType = dTypes.get(i - nPos);
        } else {
            if (hash != null && args.get(i) instanceof Name && hash.containsKey(((Name) args.get(i)).id)) {
                aType = hash.get(((Name) args.get(i)).id);
                hash.remove(((Name) args.get(i)).id);
            } else {
                if (star != null && star instanceof TupleType && j < ((TupleType) star).eltTypes.size()) {
                    aType = ((TupleType) star).get(j++);
                } else {
                    aType = Types.UNKNOWN;
                    addWarningToNode(args.get(i), "unable to bind argument:" + args.get(i));
                }
            }
        }
        bind(state, arg, aType, PARAMETER);
        fromType.add(aType);
    }
    if (restKw != null) {
        if (hash != null && !hash.isEmpty()) {
            Type hashType = UnionType.newUnion(hash.values());
            bind(state, restKw, new DictType(Types.StrInstance, hashType), PARAMETER);
        } else {
            bind(state, restKw, Types.UNKNOWN, PARAMETER);
        }
    }
    if (rest != null) {
        if (pTypes.size() > pSize) {
            if (func.afterRest != null) {
                int nAfter = func.afterRest.size();
                for (int i = 0; i < nAfter; i++) {
                    bind(state, func.afterRest.get(i), pTypes.get(pTypes.size() - nAfter + i), PARAMETER);
                }
                if (pTypes.size() - nAfter > 0) {
                    Type restType = new TupleType(pTypes.subList(pSize, pTypes.size() - nAfter));
                    bind(state, rest, restType, PARAMETER);
                }
            } else {
                Type restType = new TupleType(pTypes.subList(pSize, pTypes.size()));
                bind(state, rest, restType, PARAMETER);
            }
        } else {
            bind(state, rest, Types.UNKNOWN, PARAMETER);
        }
    }
    return fromType;
}
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) ListType(org.yinwang.pysonar.types.ListType) TupleType(org.yinwang.pysonar.types.TupleType) DictType(org.yinwang.pysonar.types.DictType) NotNull(org.jetbrains.annotations.NotNull)

Example 4 with ListType

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

the class TypeInferencer method bind.

public void bind(@NotNull State s, Node target, @NotNull Type rvalue, Binding.Kind kind) {
    if (target instanceof Name) {
        bind(s, (Name) target, rvalue, kind);
    } else if (target instanceof Tuple) {
        bind(s, ((Tuple) target).elts, rvalue, kind);
    } else if (target instanceof PyList) {
        bind(s, ((PyList) target).elts, rvalue, kind);
    } else if (target instanceof Attribute) {
        setAttr(((Attribute) target), s, rvalue);
    } else if (target instanceof Subscript) {
        Subscript sub = (Subscript) target;
        Type sliceType = sub.slice == null ? null : visit(sub.slice, s);
        Type valueType = visit(sub.value, s);
        if (valueType instanceof ListType) {
            ListType t = (ListType) valueType;
            t.setElementType(UnionType.union(t.eltType, rvalue));
        } else if (valueType instanceof DictType) {
            DictType t = (DictType) valueType;
            if (sliceType != null) {
                t.setKeyType(UnionType.union(t.keyType, sliceType));
            }
            t.setValueType(UnionType.union(t.valueType, rvalue));
        }
    } else if (target != null) {
        addWarningToNode(target, "invalid location for assignment");
    }
}
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) ListType(org.yinwang.pysonar.types.ListType) DictType(org.yinwang.pysonar.types.DictType)

Aggregations

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