in modules/asc/src/java/macromedia/asc/embedding/LintEvaluator.java [1107:1245]
public Value evaluate( Context cx, BinaryExpressionNode node )
{
Value lhsType = null;
Value rhsType = null;
if (first_pass)
{
if (node.lhs != null)
node.lhs.evaluate(cx,this);
if (node.rhs != null)
node.rhs.evaluate(cx,this);
return (node.slot != null) ? node.slot.getType().getTypeValue() : cx.voidType();
}
if( node.lhs != null)
lhsType = node.lhs.evaluate(cx,this); // do lhs first, then potentially modify operand, then rhs. Output buffer can't back up
switch( node.op )
{
case LESSTHAN_TOKEN:
case GREATERTHAN_TOKEN:
case LESSTHANOREQUALS_TOKEN:
case GREATERTHANOREQUALS_TOKEN:
case STRICTEQUALS_TOKEN:
case STRICTNOTEQUALS_TOKEN:
case EQUALS_TOKEN:
case NOTEQUALS_TOKEN:
if( node.rhs != null)
rhsType = node.rhs.evaluate(cx,this);
// if lhsType or rhsType is void, it means its the result of an undefined prop access or function call
// Don't warn twice about it.
if ( (lhsType != rhsType) && (lhsType != cx.voidType()) && (rhsType != cx.voidType()) )
{
if ( (lhsType == undefinedLiteral && rhsType != cx.noType()) ||
(lhsType != cx.noType() && rhsType == undefinedLiteral) )
{
String typeName = (lhsType == undefinedLiteral ? getSimpleTypeName((TypeValue )rhsType)
: getSimpleTypeName((TypeValue )lhsType));
warning(node.getPosition(), cx.input, kWarning_BadUndefinedComparision, typeName, typeName);
}
else if ( (lhsType == cx.nullType()) || (rhsType == cx.nullType()) )
{
TypeValue nonVoidType = (lhsType == cx.nullType() ? (TypeValue)rhsType : (TypeValue)lhsType);
switch( nonVoidType.getTypeId() )
{
case TYPE_boolean:
case TYPE_int:
case TYPE_uint:
case TYPE_double:
case TYPE_decimal:
warning(node.getPosition(), cx.input, kWarning_BadNullComparision, getSimpleTypeName(nonVoidType));
break;
}
}
}
if (lhsType == cx.doubleType() || (cx.statics.es4_numerics && (lhsType == cx.decimalType())))
{
MemberExpressionNode mem = (node.lhs instanceof MemberExpressionNode) ? (MemberExpressionNode)(node.lhs) : null;
if (mem != null)
{
GetExpressionNode getter = (mem.selector instanceof GetExpressionNode) ? (GetExpressionNode)(mem.selector) : null;
if (getter != null && "NaN".equals(getter.ref.name))
warning(node.getPosition(), cx.input, kWarning_BadNaNComparision);
}
}
if (rhsType == cx.doubleType() || (cx.statics.es4_numerics && (lhsType == cx.decimalType())))
{
MemberExpressionNode mem = (node.rhs instanceof MemberExpressionNode) ? (MemberExpressionNode)(node.rhs) : null;
if (mem != null)
{
GetExpressionNode getter = (mem.selector instanceof GetExpressionNode) ? (GetExpressionNode)(mem.selector) : null;
if (getter != null && "NaN".equals(getter.ref.name))
warning(node.getPosition(), cx.input, kWarning_BadNaNComparision);
}
}
break;
case INSTANCEOF_TOKEN:
// yes, I do mean position-11; we don't know the position of the word instanceof
// so we start from rhs and go back 11 spaces
warning(node.rhs.getPosition() - 11, cx.input, kWarning_InstanceOfChanges);
if( node.rhs != null )
node.rhs.evaluate(cx,this);
break;
case MULT_TOKEN:
case DIV_TOKEN:
case MODULUS_TOKEN:
case MINUS_TOKEN:
case LEFTSHIFT_TOKEN:
case RIGHTSHIFT_TOKEN:
case UNSIGNEDRIGHTSHIFT_TOKEN:
case BITWISEAND_TOKEN:
case BITWISEXOR_TOKEN:
case BITWISEOR_TOKEN:
case LOGICALAND_TOKEN:
case LOGICALOR_TOKEN:
if( node.rhs != null )
rhsType = node.rhs.evaluate(cx,this);
if (lhsType == cx.functionType())
{
if (node.lhs instanceof MemberExpressionNode)
{
MemberExpressionNode memb = (MemberExpressionNode)(node.lhs);
String funcName = memb.ref.name;
warning(node.lhs.pos(), cx.input, kWarning_UnlikelyFunctionValue, cx.objectType().toString(),
funcName);
}
}
if (rhsType == cx.functionType())
{
if (node.rhs instanceof MemberExpressionNode)
{
MemberExpressionNode memb = (MemberExpressionNode)(node.rhs);
String funcName = memb.ref.name;
warning(node.rhs.pos(), cx.input, kWarning_UnlikelyFunctionValue, cx.objectType().toString(),
funcName);
}
}
break;
case PLUS_TOKEN:
case IN_TOKEN:
default:
if( node.rhs != null )
rhsType = node.rhs.evaluate(cx,this);
break;
}
// Return the result type of the slot
return (node.slot!= null) ? node.slot.getType().getTypeValue() : cx.voidType();
}