use of org.yinwang.pysonar.CallStackEntry 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.CallStackEntry in project pysonar2 by yinwang0.
the class TypeInferencer method visit.
@NotNull
@Override
public Type visit(Return node, State s) {
if (node.value == null) {
return Types.NoneInstance;
} else {
Type result = visit(node.value, s);
CallStackEntry entry = Analyzer.self.callStack.top();
if (entry != null) {
entry.fun.addMapping(entry.from, result);
}
return result;
}
}
Aggregations