Esempio n. 1
0
        private ExpressionSyntax AddExplicitConversion(Microsoft.CodeAnalysis.VisualBasic.Syntax.ExpressionSyntax vbNode, ExpressionSyntax csNode,
                                                       ITypeSymbol vbConvertedType, TypeConversionKind conversionKind, bool addParenthesisIfNeeded)
        {
            switch (conversionKind)
            {
            case TypeConversionKind.Unknown:
            case TypeConversionKind.Identity:
                return(addParenthesisIfNeeded ? VbSyntaxNodeExtensions.ParenthesizeIfPrecedenceCouldChange(vbNode, csNode) : csNode);

            case TypeConversionKind.Implicit:
                return(ValidSyntaxFactory.CastExpression(_semanticModel.GetCsTypeSyntax(vbConvertedType, vbNode), csNode));

            case TypeConversionKind.Explicit:
                return(AddExplicitConvertTo(vbNode, csNode, vbConvertedType));

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
        private ExpressionSyntax AddTypeConversion(VBSyntax.ExpressionSyntax vbNode, ExpressionSyntax csNode, TypeConversionKind conversionKind, bool addParenthesisIfNeeded, ITypeSymbol vbType, ITypeSymbol vbConvertedType)
        {
            switch (conversionKind)
            {
            case TypeConversionKind.EnumConversionThenCast:
                var underlyingType = ((INamedTypeSymbol)vbConvertedType).EnumUnderlyingType;
                csNode = AddTypeConversion(vbNode, csNode, TypeConversionKind.Conversion, addParenthesisIfNeeded, vbType, underlyingType);
                return(AddTypeConversion(vbNode, csNode, TypeConversionKind.NonDestructiveCast, addParenthesisIfNeeded, underlyingType, vbConvertedType));

            case TypeConversionKind.EnumCastThenConversion:
                var enumUnderlyingType = ((INamedTypeSymbol)vbType).EnumUnderlyingType;
                csNode = AddTypeConversion(vbNode, csNode, TypeConversionKind.NonDestructiveCast, addParenthesisIfNeeded, vbType, enumUnderlyingType);
                return(AddTypeConversion(vbNode, csNode, TypeConversionKind.Conversion, addParenthesisIfNeeded, enumUnderlyingType, vbConvertedType));

            case TypeConversionKind.Unknown:
            case TypeConversionKind.Identity:
                return(addParenthesisIfNeeded ? vbNode.ParenthesizeIfPrecedenceCouldChange(csNode) : csNode);

            case TypeConversionKind.DestructiveCast:
            case TypeConversionKind.NonDestructiveCast:
                return(CreateCast(csNode, vbConvertedType));

            case TypeConversionKind.Conversion:
                return(AddExplicitConvertTo(vbNode, csNode, vbType, vbConvertedType));;

            case TypeConversionKind.NullableBool:
                return(SyntaxFactory.BinaryExpression(SyntaxKind.EqualsExpression, csNode,
                                                      LiteralConversions.GetLiteralExpression(true)));

            case TypeConversionKind.StringToCharArray:
                var memberAccessExpressionSyntax = SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, csNode, SyntaxFactory.IdentifierName(nameof(string.ToCharArray)));
                return(SyntaxFactory.InvocationExpression(memberAccessExpressionSyntax,
                                                          SyntaxFactory.ArgumentList()));

            case TypeConversionKind.DelegateConstructor:
                return(SyntaxFactory.ObjectCreationExpression(GetCommonDelegateTypeOrNull(vbNode, vbConvertedType)).WithArgumentList(new[] { csNode }.CreateCsArgList()));

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
        public (ExpressionSyntax Expr, bool IsConst) AddExplicitConversion(VBSyntax.ExpressionSyntax vbNode, ExpressionSyntax csNode, TypeConversionKind conversionKind, bool addParenthesisIfNeeded = false, bool requiresConst = false, ITypeSymbol forceSourceType = null, ITypeSymbol forceTargetType = null)
        {
            var(vbType, vbConvertedType) = GetTypeInfo(vbNode, forceSourceType, forceTargetType);
            bool resultConst = false;

            if (requiresConst)
            {
                var(constExpression, isCorrectType) = _expressionEvaluator.GetConstantOrNull(vbNode, vbConvertedType, conversionKind, csNode);
                if (isCorrectType)
                {
                    return(constExpression, true);
                }
                if (constExpression != null)
                {
                    csNode      = constExpression ?? csNode;
                    resultConst = true;
                }
            }

            var typeConvertedResult = AddTypeConversion(vbNode, csNode, conversionKind, addParenthesisIfNeeded, vbType, vbConvertedType);

            return(typeConvertedResult, resultConst);
        }
Esempio n. 4
0
        public ExpressionSyntax AddExplicitConversion(Microsoft.CodeAnalysis.VisualBasic.Syntax.ExpressionSyntax vbNode, ExpressionSyntax csNode, TypeConversionKind conversionKind, bool addParenthesisIfNeeded = false, ITypeSymbol forceTargetType = null)
        {
            var vbConvertedType = forceTargetType ?? ModelExtensions.GetTypeInfo(_semanticModel, vbNode).ConvertedType;

            switch (conversionKind)
            {
            case TypeConversionKind.Unknown:
            case TypeConversionKind.Identity:
                return(addParenthesisIfNeeded ? VbSyntaxNodeExtensions.ParenthesizeIfPrecedenceCouldChange(vbNode, csNode) : csNode);

            case TypeConversionKind.DestructiveCast:
            case TypeConversionKind.NonDestructiveCast:
                return(CreateCast(csNode, vbConvertedType));

            case TypeConversionKind.Conversion:
                return(AddExplicitConvertTo(vbNode, csNode, vbConvertedType));

            case TypeConversionKind.ConstConversion:
                return(ConstantFold(vbNode, vbConvertedType));

            case TypeConversionKind.NullableBool:
                return(SyntaxFactory.BinaryExpression(SyntaxKind.EqualsExpression, csNode,
                                                      LiteralConversions.GetLiteralExpression(true)));

            case TypeConversionKind.StringToCharArray:
                var memberAccessExpressionSyntax = SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, csNode, SyntaxFactory.IdentifierName(nameof(string.ToCharArray)));
                return(SyntaxFactory.InvocationExpression(memberAccessExpressionSyntax,
                                                          SyntaxFactory.ArgumentList()));

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
Esempio n. 5
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);
        }
        public ExpressionSyntax AddExplicitConversion(Microsoft.CodeAnalysis.VisualBasic.Syntax.ExpressionSyntax vbNode, ExpressionSyntax csNode, TypeConversionKind conversionKind, bool addParenthesisIfNeeded = false)
        {
            var vbConvertedType = ModelExtensions.GetTypeInfo(_semanticModel, vbNode).ConvertedType;

            switch (conversionKind)
            {
            case TypeConversionKind.Unknown:
            case TypeConversionKind.Identity:
                return(addParenthesisIfNeeded ? VbSyntaxNodeExtensions.ParenthesizeIfPrecedenceCouldChange(vbNode, csNode) : csNode);

            case TypeConversionKind.DestructiveCast:
            case TypeConversionKind.NonDestructiveCast:
                return(CreateCast(csNode, vbConvertedType));

            case TypeConversionKind.Conversion:
                return(AddExplicitConvertTo(vbNode, csNode, vbConvertedType));

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
        private ExpressionSyntax AddTypeConversion(VBSyntax.ExpressionSyntax vbNode, ExpressionSyntax csNode, TypeConversionKind conversionKind, bool addParenthesisIfNeeded, ITypeSymbol vbType, ITypeSymbol vbConvertedType)
        {
            switch (conversionKind)
            {
            case TypeConversionKind.Unknown:
            case TypeConversionKind.Identity:
                return(addParenthesisIfNeeded ? VbSyntaxNodeExtensions.ParenthesizeIfPrecedenceCouldChange(vbNode, csNode) : csNode);

            case TypeConversionKind.DestructiveCast:
            case TypeConversionKind.NonDestructiveCast:
                return(CreateCast(csNode, vbConvertedType));

            case TypeConversionKind.Conversion:
                return(AddExplicitConvertTo(vbNode, csNode, vbType, vbConvertedType));;

            case TypeConversionKind.NullableBool:
                return(SyntaxFactory.BinaryExpression(SyntaxKind.EqualsExpression, csNode,
                                                      LiteralConversions.GetLiteralExpression(true)));

            case TypeConversionKind.StringToCharArray:
                var memberAccessExpressionSyntax = SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, csNode, SyntaxFactory.IdentifierName(nameof(string.ToCharArray)));
                return(SyntaxFactory.InvocationExpression(memberAccessExpressionSyntax,
                                                          SyntaxFactory.ArgumentList()));

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
        public (ExpressionSyntax Expr, bool IsConst) AddExplicitConversion(Microsoft.CodeAnalysis.VisualBasic.Syntax.ExpressionSyntax vbNode, ExpressionSyntax csNode, TypeConversionKind conversionKind, bool addParenthesisIfNeeded = false, bool requiresConst = false, ITypeSymbol forceSourceType = null, ITypeSymbol forceTargetType = null)
        {
            var  typeInfo        = ModelExtensions.GetTypeInfo(_semanticModel, vbNode);
            var  vbType          = forceSourceType ?? typeInfo.Type;
            var  vbConvertedType = forceTargetType ?? typeInfo.ConvertedType;
            bool resultConst     = false;

            if (requiresConst)
            {
                var(constExpression, isCorrectType) = _expressionEvaluator.GetConstantOrNull(vbNode, vbConvertedType, conversionKind, csNode);
                if (isCorrectType)
                {
                    return(constExpression, true);
                }
                if (constExpression != null)
                {
                    csNode      = constExpression ?? csNode;
                    resultConst = true;
                }
            }

            var typeConvertedResult = AddTypeConversion(vbNode, csNode, conversionKind, addParenthesisIfNeeded, vbType, vbConvertedType);

            return(typeConvertedResult, resultConst);
        }
Esempio n. 9
0
        private ExpressionSyntax AddExplicitConversion(Microsoft.CodeAnalysis.VisualBasic.Syntax.ExpressionSyntax vbNode, ExpressionSyntax csNode, TypeConversionKind conversionKind, bool addParenthesisIfNeeded)
        {
            var vbConvertedType = _semanticModel.GetTypeInfo(vbNode).ConvertedType;

            switch (conversionKind)
            {
            case TypeConversionKind.Unknown:
            case TypeConversionKind.Identity:
                return(addParenthesisIfNeeded ? VbSyntaxNodeExtensions.ParenthesizeIfPrecedenceCouldChange(vbNode, csNode) : csNode);

            case TypeConversionKind.DestructiveCast:
            case TypeConversionKind.NonDestructiveCast:
                var typeName = (TypeSyntax)_csSyntaxGenerator.TypeExpression(vbConvertedType);
                if (csNode is CastExpressionSyntax cast && cast.Type.IsEquivalentTo(typeName))
                {
                    return(csNode);
                }
                return(ValidSyntaxFactory.CastExpression(typeName, csNode));

            case TypeConversionKind.Conversion:
                return(AddExplicitConvertTo(vbNode, csNode, vbConvertedType));

            default:
                throw new ArgumentOutOfRangeException();
            }
        }