/// <summary> /// Determines if the use of <paramref name="variable"/> in <paramref name="useExpression"/> requires a cast. /// </summary> /// <param name="useExpression">The expression being checked.</param> /// <param name="variable">The variable that might need to be casted.</param> private void AddCastIfNeeded(Expression useExpression, VariableReference variable) { switch (useExpression.CodeNodeType) { case CodeNodeType.MethodInvocationExpression: MethodInvocationExpression miEx = useExpression as MethodInvocationExpression; Expression argument = miEx.Arguments.FirstOrDefault(x => x.CodeNodeType == CodeNodeType.VariableReferenceExpression && (x as VariableReferenceExpression).Variable == variable); if (argument != null) { ///The variable is passed as argument to the method. int argumentIndex = miEx.Arguments.IndexOf(argument); TypeReference argumentType = miEx.MethodExpression.Method.Parameters[argumentIndex].ResolveParameterType(miEx.MethodExpression.Method); if (!IsSubtype(argumentType, variable.VariableType)) { if (argumentType.IsPrimitive && variable.VariableType.IsPrimitive) { ///Integer values are not in inheritance relations. Some of them, however, can be expanded to bigger types ///automatically, without the addition of a cast, i.e. Byte variable can be passed as int parameter without the ///need to include a cast. TypeReference containingType = ExpressionTypeInferer.GetContainingType(argumentType.Resolve(), variable.VariableType.Resolve()); if (containingType.FullName == argumentType.FullName) { ///Then the type of the argument contains the type of the variable, thus no cast is needed. return; } } ///Then a cast is needed. miEx.Arguments[argumentIndex] = new CastExpression(argument, argumentType, null); ///This should be enough to update the expression everywhere it is seen. } } else { /// Then the variable is the object from which the method is called /// variable.SomeMethod(...); Expression target = miEx.MethodExpression.Target; if (target.CodeNodeType == CodeNodeType.VariableReferenceExpression && (target as VariableReferenceExpression).Variable == variable) { TypeReference targetType = miEx.MethodExpression.Method.DeclaringType; if (!IsSubtype(targetType, variable.VariableType)) { miEx.MethodExpression.Target = new CastExpression(target, targetType, null); } } else { ///This should not be reachable, but anyway. AddCastIfNeeded(target, variable); } } break; case CodeNodeType.BinaryExpression: BinaryExpression binEx = useExpression as BinaryExpression; if (binEx.Operator == BinaryOperator.Assign) { if (binEx.Right.CodeNodeType == CodeNodeType.VariableReferenceExpression && (binEx.Right as VariableReferenceExpression).Variable == variable) { TypeReference assignedAs = binEx.Left.ExpressionType; ///binex.Right should be VariableReferenceExpression to 'variable'. if (!IsSubtype(assignedAs, variable.VariableType)) { binEx.Right = new CastExpression(binEx.Right, assignedAs, null); } } } break; //default: //throw new NotSupportedException("Not supported cast expression."); } }
private void AddCastIfNeeded(Expression useExpression, VariableReference variable) { V_0 = new TypeInferer.u003cu003ec__DisplayClass8_0(); V_0.variable = variable; V_4 = useExpression.get_CodeNodeType(); if (V_4 == 19) { V_1 = useExpression as MethodInvocationExpression; V_2 = V_1.get_Arguments().FirstOrDefault <Expression>(new Func <Expression, bool>(V_0.u003cAddCastIfNeededu003eb__0)); if (V_2 == null) { V_7 = V_1.get_MethodExpression().get_Target(); if (V_7.get_CodeNodeType() != 26 || (object)(V_7 as VariableReferenceExpression).get_Variable() != (object)V_0.variable) { this.AddCastIfNeeded(V_7, V_0.variable); return; } V_8 = V_1.get_MethodExpression().get_Method().get_DeclaringType(); if (!this.IsSubtype(V_8, V_0.variable.get_VariableType())) { V_1.get_MethodExpression().set_Target(new ExplicitCastExpression(V_7, V_8, null)); return; } } else { V_5 = V_1.get_Arguments().IndexOf(V_2); V_6 = V_1.get_MethodExpression().get_Method().get_Parameters().get_Item(V_5).ResolveParameterType(V_1.get_MethodExpression().get_Method()); if (!this.IsSubtype(V_6, V_0.variable.get_VariableType())) { if (V_6.get_IsPrimitive() && V_0.variable.get_VariableType().get_IsPrimitive() && String.op_Equality(ExpressionTypeInferer.GetContainingType(V_6.Resolve(), V_0.variable.get_VariableType().Resolve()).get_FullName(), V_6.get_FullName())) { return; } V_1.get_Arguments().set_Item(V_5, new ExplicitCastExpression(V_2, V_6, null)); return; } } } else { if (V_4 != 24) { return; } V_3 = useExpression as BinaryExpression; if (V_3.get_Operator() == 26 && V_3.get_Right().get_CodeNodeType() == 26 && (object)(V_3.get_Right() as VariableReferenceExpression).get_Variable() == (object)V_0.variable) { V_9 = V_3.get_Left().get_ExpressionType(); if (!this.IsSubtype(V_9, V_0.variable.get_VariableType())) { V_3.set_Right(new ExplicitCastExpression(V_3.get_Right(), V_9, null)); } } } return; }