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