*/
private void tighten(JVariable x) {
if (!(x.getType() instanceof JReferenceType)) {
return;
}
JReferenceType refType = (JReferenceType) x.getType();
if (refType == typeNull) {
return;
}
// tighten based on non-instantiability
if (!program.typeOracle.isInstantiatedType(refType)) {
x.setType(typeNull);
myDidChange = true;
return;
}
// tighten based on leaf types
JClassType leafType = getSingleConcreteType(refType);
if (leafType != null) {
x.setType(leafType);
myDidChange = true;
return;
}
// tighten based on assignment
List<JReferenceType> typeList = new ArrayList<JReferenceType>();
/*
* For non-parameters, always assume at least one null assignment; if
* there really aren't any other assignments, then this variable will get
* the null type. If there are, it won't hurt anything because null type
* will always lose.
*
* For parameters, don't perform any tightening if we can't find any
* actual assignments. The method should eventually get pruned.
*/
if (!(x instanceof JParameter)) {
typeList.add(typeNull);
}
Set<JExpression> myAssignments = assignments.get(x);
if (myAssignments != null) {
for (JExpression expr : myAssignments) {
JType type = expr.getType();
if (!(type instanceof JReferenceType)) {
return; // something fishy is going on, just abort
}
typeList.add((JReferenceType) type);
}
}
if (x instanceof JParameter) {
Set<JParameter> myParams = paramUpRefs.get(x);
if (myParams != null) {
for (JParameter param : myParams) {
typeList.add((JReferenceType) param.getType());
}
}
}
if (typeList.isEmpty()) {
return;
}
JReferenceType resultType = program.generalizeTypes(typeList);
resultType = program.strongerType(refType, resultType);
if (refType != resultType) {
x.setType(resultType);
myDidChange = true;
}