//////////////////////////////////////////////////////////////////////////////
private EnvTypePair analyzePropAccessFwd(Node receiver, String pname,
TypeEnv inEnv, JSType requiredType, JSType specializedType) {
QualifiedName propQname = new QualifiedName(pname);
Node propAccessNode = receiver.getParent();
EnvTypePair pair;
JSType objWithProp = pickReqObjType(receiver)
.withLoose().withProperty(propQname, requiredType);
JSType recvReqType, recvSpecType, recvType;
// First, analyze the receiver object.
if (specializedType.isTruthy() || specializedType.isFalsy()) {
recvReqType = JSType.UNKNOWN;
recvSpecType = objWithProp;
} else {
recvReqType = recvSpecType = objWithProp;
}
pair = analyzeExprFwd(receiver, inEnv, recvReqType, recvSpecType);
recvType = pair.type;
if (recvType.isUnknown() ||
mayWarnAboutNonObject(receiver, pname, recvType, specializedType)) {
return new EnvTypePair(pair.env, requiredType);
}
if (propAccessNode.isGetProp() &&
mayWarnAboutDictPropAccess(receiver, recvType)) {
return new EnvTypePair(pair.env, requiredType);
}
// Then, analyze the property access.
QualifiedName getterPname = new QualifiedName(GETTER_PREFIX + pname);
if (recvType.hasProp(getterPname)) {
return new EnvTypePair(pair.env, recvType.getProp(getterPname));
}
JSType resultType = recvType.getProp(propQname);
if (!propAccessNode.getParent().isExprResult() &&