Beispiel #1
0
        private bool TryAnalyzeCsConversion(Microsoft.CodeAnalysis.VisualBasic.Syntax.ExpressionSyntax vbNode, ITypeSymbol csType,
                                            ITypeSymbol csConvertedType, Conversion vbConversion, ITypeSymbol vbConvertedType, ITypeSymbol vbType,
                                            VisualBasicCompilation vbCompilation, bool isConst, out TypeConversionKind typeConversionKind)
        {
            var csConversion = _csCompilation.ClassifyConversion(csType, csConvertedType);

            bool isConvertToString =
                (vbConversion.IsString || vbConversion.IsReference && vbConversion.IsNarrowing) && vbConvertedType.SpecialType == SpecialType.System_String;
            bool isArithmetic = vbNode.IsKind(Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.AddExpression,
                                              Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.SubtractExpression,
                                              Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.MultiplyExpression,
                                              Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.DivideExpression,
                                              Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.IntegerDivideExpression);

            if (!csConversion.Exists || csConversion.IsUnboxing)
            {
                if (ConvertStringToCharLiteral(vbNode, vbConvertedType, out _))
                {
                    typeConversionKind =
                        TypeConversionKind.Identity; // Already handled elsewhere by other usage of method
                    return(true);
                }

                if (vbType.SpecialType == SpecialType.System_String && vbConvertedType.IsArrayOf(SpecialType.System_Char))
                {
                    typeConversionKind = TypeConversionKind.StringToCharArray;
                    return(true);
                }
                if (isConvertToString || vbConversion.IsNarrowing)
                {
                    typeConversionKind = isConst ? TypeConversionKind.ConstConversion : TypeConversionKind.Conversion;
                    return(true);
                }
            }
            else if (vbConversion.IsWidening && vbConversion.IsNumeric && csConversion.IsImplicit &&
                     csConversion.IsNumeric)
            {
                // Safe overapproximation: A cast is really only needed to help resolve the overload for the operator/method used.
                // e.g. When VB "&" changes to C# "+", there are lots more overloads available that implicit casts could match.
                // e.g. sbyte * ulong uses the decimal * operator in VB. In C# it's ambiguous - see ExpressionTests.vb "TestMul".
                typeConversionKind = TypeConversionKind.NonDestructiveCast;
                return(true);
            }
            else if (csConversion.IsExplicit && csConversion.IsEnumeration)
            {
                typeConversionKind = TypeConversionKind.NonDestructiveCast;
                return(true);
            }
            else if (isArithmetic)
            {
                var arithmeticConversion =
                    vbCompilation.ClassifyConversion(vbConvertedType,
                                                     vbCompilation.GetTypeByMetadataName("System.Int32"));
                if (arithmeticConversion.IsWidening && !arithmeticConversion.IsIdentity)
                {
                    typeConversionKind = isConst ? TypeConversionKind.ConstConversion : TypeConversionKind.Conversion;
                    return(true);
                }
            }
            else if (csConversion.IsExplicit && csConversion.IsNumeric && vbConversion.IsNarrowing && isConst)
            {
                typeConversionKind = IsImplicitConstantConversion(vbNode) ? TypeConversionKind.Identity : TypeConversionKind.NonDestructiveCast;
                return(true);
            }
            else if (csConversion.IsExplicit && vbConversion.IsNumeric && vbType.TypeKind != TypeKind.Enum)
            {
                typeConversionKind = IsImplicitConstantConversion(vbNode) ? TypeConversionKind.Identity :
                                     isConst ? TypeConversionKind.ConstConversion : TypeConversionKind.Conversion;
                return(true);
            }
            else if (csConversion.IsExplicit && vbConversion.IsIdentity && csConversion.IsNumeric && vbType.TypeKind != TypeKind.Enum)
            {
                typeConversionKind = isConst ? TypeConversionKind.ConstConversion : TypeConversionKind.Conversion;
                return(true);
            }
            else if (isConvertToString && vbType.SpecialType == SpecialType.System_Object)
            {
                typeConversionKind = isConst ? TypeConversionKind.ConstConversion : TypeConversionKind.Conversion;
                return(true);
            }
            else if (csConversion.IsNullable && csConvertedType.SpecialType == SpecialType.System_Boolean)
            {
                typeConversionKind = TypeConversionKind.NullableBool;
                return(true);
            }
            else if (csConversion.IsExplicit)
            {
                typeConversionKind = TypeConversionKind.DestructiveCast;
                return(true);
            }

            typeConversionKind = csConversion.IsIdentity ? TypeConversionKind.Identity : TypeConversionKind.Unknown;
            return(false);
        }