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;
}
}
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());
}
}
}
}
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;
}
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");
}
}
Aggregations