private async Task <EqualsValueClauseSyntax> ConvertEqualsValueClauseSyntax(
            VariableDeclaratorSyntax vbDeclarator, ModifiedIdentifierSyntax vbName,
            VBSyntax.ExpressionSyntax vbInitValue,
            ITypeSymbol declaredSymbolType,
            ISymbol declaredSymbol, CSharpSyntaxNode initializerOrMethodDecl)
        {
            var csTypeSyntax = GetTypeSyntax(declaredSymbolType);

            bool isField = vbDeclarator.Parent.IsKind(SyntaxKind.FieldDeclaration);
            bool isConst = declaredSymbol is IFieldSymbol fieldSymbol && fieldSymbol.IsConst ||
                           declaredSymbol is ILocalSymbol localSymbol && localSymbol.IsConst;

            EqualsValueClauseSyntax equalsValueClauseSyntax;

            if (await GetInitializerFromNameAndType(declaredSymbolType, vbName, initializerOrMethodDecl) is ExpressionSyntax
                adjustedInitializerExpr)
            {
                var convertedInitializer = vbInitValue != null
                    ? TypeConversionAnalyzer.AddExplicitConversion(vbInitValue, adjustedInitializerExpr, isConst : isConst)
                    : adjustedInitializerExpr;

                equalsValueClauseSyntax = SyntaxFactory.EqualsValueClause(convertedInitializer);
            }
            else if (isField || declaredSymbol != null && _semanticModel.IsDefinitelyAssignedBeforeRead(declaredSymbol, vbName))
            {
                equalsValueClauseSyntax = null;
            }
            else
            {
                // VB initializes variables to their default
                equalsValueClauseSyntax = SyntaxFactory.EqualsValueClause(SyntaxFactory.DefaultExpression(csTypeSyntax));
            }

            return(equalsValueClauseSyntax);
        }
Exemplo n.º 2
0
        public ExpressionSyntax AddExplicitConvertTo(Microsoft.CodeAnalysis.VisualBasic.Syntax.ExpressionSyntax vbNode, ExpressionSyntax csNode, ITypeSymbol type)
        {
            var displayType = type.ToMinimalDisplayString(_semanticModel, vbNode.SpanStart);

            if (csNode is InvocationExpressionSyntax invoke &&
                invoke.Expression is MemberAccessExpressionSyntax expr &&
                expr.Expression is IdentifierNameSyntax name && name.Identifier.ValueText == "Conversions" &&
                expr.Name.Identifier.ValueText == $"To{displayType}")
            {
                return(csNode);
            }

            var method = typeof(Conversions).GetMethod($"To{displayType}");

            if (method == null)
            {
                throw new NotImplementedException($"Unimplemented conversion for {displayType}");
            }

            // Need to use Conversions rather than Convert to match what VB does, eg. True -> -1
            _extraUsingDirectives.Add("Microsoft.VisualBasic.CompilerServices");
            var memberAccess = SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                                                    SyntaxFactory.IdentifierName("Conversions"), SyntaxFactory.IdentifierName($"To{displayType}"));
            var arguments = SyntaxFactory.ArgumentList(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Argument(csNode)));

            return(SyntaxFactory.InvocationExpression(memberAccess, arguments));
        }
Exemplo n.º 3
0
        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:
                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();
            }
        }
        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();
            }
        }
Exemplo n.º 5
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();
            }
        }
        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);
        }
Exemplo n.º 7
0
        public ExpressionSyntax AddExplicitConvertTo(Microsoft.CodeAnalysis.VisualBasic.Syntax.ExpressionSyntax vbNode, ExpressionSyntax csNode, ITypeSymbol type)
        {
            var displayType = type.ToMinimalDisplayString(_semanticModel, vbNode.SpanStart);

            if (csNode is InvocationExpressionSyntax invoke &&
                invoke.Expression is MemberAccessExpressionSyntax expr &&
                expr.Expression is IdentifierNameSyntax name && name.Identifier.ValueText == "Conversions" &&
                expr.Name.Identifier.ValueText == $"To{displayType}")
            {
                return(csNode);
            }

            if (!ConversionsTypeFullNames.TryGetValue(type.GetFullMetadataName(), out var methodId))
            {
                return(CreateCast(csNode, type));
            }

            // Need to use Conversions rather than Convert to match what VB does, eg. True -> -1
            _extraUsingDirectives.Add("Microsoft.VisualBasic.CompilerServices");
            var memberAccess = SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                                                    SyntaxFactory.IdentifierName("Conversions"), SyntaxFactory.IdentifierName(methodId.Name));
            var arguments = SyntaxFactory.ArgumentList(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Argument(csNode)));

            return(SyntaxFactory.InvocationExpression(memberAccess, arguments));
        }
        public ExpressionSyntax AddExplicitConversion(Microsoft.CodeAnalysis.VisualBasic.Syntax.ExpressionSyntax vbNode, ExpressionSyntax csNode, bool addParenthesisIfNeeded = true, bool defaultToCast = false, bool isConst = false, ITypeSymbol forceTargetType = null)
        {
            var conversionKind = AnalyzeConversion(vbNode, defaultToCast, isConst, forceTargetType);

            csNode = addParenthesisIfNeeded && (conversionKind == TypeConversionKind.DestructiveCast || conversionKind == TypeConversionKind.NonDestructiveCast)
                ? VbSyntaxNodeExtensions.ParenthesizeIfPrecedenceCouldChange(vbNode, csNode)
                : csNode;
            return(AddExplicitConversion(vbNode, csNode, conversionKind, addParenthesisIfNeeded, forceTargetType: forceTargetType));
        }
        public ExpressionSyntax AddExplicitConversion(Microsoft.CodeAnalysis.VisualBasic.Syntax.ExpressionSyntax vbNode, ExpressionSyntax csNode, bool addParenthesisIfNeeded = true, bool alwaysExplicit = false)
        {
            var conversionKind = AnalyzeConversion(vbNode, alwaysExplicit);

            csNode = addParenthesisIfNeeded && (conversionKind == TypeConversionKind.DestructiveCast || conversionKind == TypeConversionKind.NonDestructiveCast)
                ? VbSyntaxNodeExtensions.ParenthesizeIfPrecedenceCouldChange(vbNode, csNode)
                : csNode;
            return(AddExplicitConversion(vbNode, csNode, conversionKind, addParenthesisIfNeeded));
        }
Exemplo n.º 10
0
        public IEnumerable <ExpressionSyntax> ConvertArrayBounds(ArgumentListSyntax argumentListSyntax)
        {
            return(argumentListSyntax.Arguments.Select(a => {
                VBSyntax.ExpressionSyntax upperBoundExpression = a is SimpleArgumentSyntax sas ? sas.Expression
                    : a is RangeArgumentSyntax ras ? ras.UpperBound
                    : throw new ArgumentOutOfRangeException(nameof(a), a, null);

                return IncreaseArrayUpperBoundExpression(upperBoundExpression);
            }));
        }
        public TypeConversionKind AnalyzeConversion(VBSyntax.ExpressionSyntax vbNode, bool alwaysExplicit = false, bool isConst = false, ITypeSymbol forceSourceType = null, ITypeSymbol forceTargetType = null)
        {
            var(vbType, vbConvertedType) = GetTypeInfo(vbNode, forceSourceType, forceTargetType);

            if (vbConvertedType is null)
            {
                return(TypeConversionKind.Unknown);
            }

            if (vbType is null)
            {
                return(GetCommonDelegateTypeOrNull(vbNode, vbConvertedType) is {} ? TypeConversionKind.DelegateConstructor : TypeConversionKind.Unknown);
Exemplo n.º 12
0
        private ExpressionSyntax ConstantFold(VBSyntax.ExpressionSyntax vbNode, ITypeSymbol type)
        {
            var vbOperation = _semanticModel.GetOperation(vbNode);

            if (TryCompileTimeEvaluate(vbOperation, out var result) && ConversionsTypeFullNames.TryGetValue(type.GetFullMetadataName(), out var method))
            {
                result = method.Invoke(null, new[] { result });
                return(LiteralConversions.GetLiteralExpression(result));
            }

            throw new NotImplementedException("Cannot generate constant C# expression");
        }
Exemplo n.º 13
0
        private async Task <EqualsValueClauseSyntax> ConvertEqualsValueClauseSyntaxAsync(
            VariableDeclaratorSyntax vbDeclarator, VBSyntax.ModifiedIdentifierSyntax vbName,
            VBSyntax.ExpressionSyntax vbInitValue,
            ITypeSymbol declaredSymbolType,
            ISymbol declaredSymbol, CSharpSyntaxNode initializerOrMethodDecl)
        {
            var csTypeSyntax = GetTypeSyntax(declaredSymbolType);

            bool isField       = vbDeclarator.Parent.IsKind(SyntaxKind.FieldDeclaration);
            bool declaredConst = declaredSymbol is IFieldSymbol fieldSymbol && fieldSymbol.IsConst ||
                                 declaredSymbol is ILocalSymbol localSymbol && localSymbol.IsConst;

            EqualsValueClauseSyntax equalsValueClauseSyntax;

            if (await GetInitializerFromNameAndTypeAsync(declaredSymbolType, vbName, initializerOrMethodDecl) is ExpressionSyntax
                adjustedInitializerExpr)
            {
                var convertedInitializer = vbInitValue != null
                    ? TypeConversionAnalyzer.AddExplicitConversion(vbInitValue, adjustedInitializerExpr, isConst : declaredConst)
                    : adjustedInitializerExpr;

                if (isField && !declaredSymbol.IsStatic && !_semanticModel.IsDefinitelyStatic(vbName, vbInitValue))
                {
                    if (_typeContext.Initializers.ShouldAddTypeWideInitToThisPart)
                    {
                        var lhs = SyntaxFactory.IdentifierName(ConvertIdentifier(vbName.Identifier, sourceTriviaMapKind: SourceTriviaMapKind.None));
                        _typeContext.Initializers.AdditionalInstanceInitializers.Add((lhs, CSSyntaxKind.SimpleAssignmentExpression, adjustedInitializerExpr));
                        equalsValueClauseSyntax = null;
                    }
                    else
                    {
                        var returnBlock = SyntaxFactory.Block(SyntaxFactory.ReturnStatement(adjustedInitializerExpr));
                        _typeContext.HoistedState.Hoist <HoistedParameterlessFunction>(new HoistedParameterlessFunction(GetInitialValueFunctionName(vbName), csTypeSyntax, returnBlock));
                        equalsValueClauseSyntax = null;
                    }
                }
                else
                {
                    equalsValueClauseSyntax = SyntaxFactory.EqualsValueClause(convertedInitializer);
                }
            }
            else if (isField || declaredSymbol != null && _semanticModel.IsDefinitelyAssignedBeforeRead(declaredSymbol, vbName))
            {
                equalsValueClauseSyntax = null;
            }
            else
            {
                // VB initializes variables to their default
                equalsValueClauseSyntax = SyntaxFactory.EqualsValueClause(SyntaxFactory.DefaultExpression(csTypeSyntax));
            }

            return(equalsValueClauseSyntax);
        }
        public ExpressionSyntax AddExplicitConversion(VBSyntax.ExpressionSyntax vbNode, ExpressionSyntax csNode, bool addParenthesisIfNeeded = true, bool defaultToCast = false, bool isConst = false, ITypeSymbol forceSourceType = null, ITypeSymbol forceTargetType = null)
        {
            if (csNode == null)
            {
                return(null);
            }
            var conversionKind = AnalyzeConversion(vbNode, defaultToCast, isConst, forceSourceType, forceTargetType);

            csNode = addParenthesisIfNeeded && (conversionKind == TypeConversionKind.DestructiveCast || conversionKind == TypeConversionKind.NonDestructiveCast)
                ? VbSyntaxNodeExtensions.ParenthesizeIfPrecedenceCouldChange(vbNode, csNode)
                : csNode;
            return(AddExplicitConversion(vbNode, csNode, conversionKind, addParenthesisIfNeeded, isConst, forceSourceType: forceSourceType, forceTargetType: forceTargetType).Expr);
        }
Exemplo n.º 15
0
        private ExpressionSyntax IncreaseArrayUpperBoundExpression(VBSyntax.ExpressionSyntax expr)
        {
            var constant = _semanticModel.GetConstantValue(expr);

            if (constant.HasValue && constant.Value is int)
            {
                return(SyntaxFactory.LiteralExpression(Microsoft.CodeAnalysis.CSharp.SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal((int)constant.Value + 1)));
            }

            return(SyntaxFactory.BinaryExpression(
                       Microsoft.CodeAnalysis.CSharp.SyntaxKind.SubtractExpression,
                       (ExpressionSyntax)expr.Accept(_nodesVisitor), SyntaxFactory.Token(Microsoft.CodeAnalysis.CSharp.SyntaxKind.PlusToken), SyntaxFactory.LiteralExpression(Microsoft.CodeAnalysis.CSharp.SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(1))));
        }
Exemplo n.º 16
0
        public bool ShouldPreferExplicitType(VBSyntax.ExpressionSyntax exp,
                                             ITypeSymbol expConvertedType,
                                             out bool isNothingLiteral)
        {
            var op = _semanticModel.GetExpressionOperation(exp);

            exp = op.Syntax as VBSyntax.ExpressionSyntax;
            var vbInitConstantValue = _semanticModel.GetConstantValue(exp);

            isNothingLiteral = vbInitConstantValue.HasValue && vbInitConstantValue.Value == null || exp is VBSyntax.LiteralExpressionSyntax les && les.IsKind(SyntaxKind.NothingLiteralExpression);
            bool shouldPreferExplicitType = expConvertedType != null && (expConvertedType.HasCsKeyword() || !expConvertedType.Equals(op.Type));

            return(shouldPreferExplicitType);
        }
Exemplo n.º 17
0
        private ITypeSymbol GetCSType(ITypeSymbol vbType, VBSyntax.ExpressionSyntax vbNode = null)
        {
            // C# does not have literals for short/ushort, so the actual type here is integer
            if (vbNode is VBSyntax.LiteralExpressionSyntax literal &&
                literal.IsKind(Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.NumericLiteralExpression) &&
                literal.Token.Text.EndsWith("S"))
            {
                return(_csCompilation.GetSpecialType(SpecialType.System_Int32));
            }

            var csType = SymbolFinder.FindSimilarSymbols(vbType, _csCompilation).FirstOrDefault() ?? _csCompilation.GetTypeByMetadataName(vbType.GetFullMetadataName());

            return(csType);
        }
        public TypeConversionKind AnalyzeConversion(Microsoft.CodeAnalysis.VisualBasic.Syntax.ExpressionSyntax vbNode, bool alwaysExplicit = false, bool isConst = false, ITypeSymbol forceSourceType = null, ITypeSymbol forceTargetType = null)
        {
            var typeInfo        = ModelExtensions.GetTypeInfo(_semanticModel, vbNode);
            var vbType          = forceSourceType ?? typeInfo.Type;
            var vbConvertedType = forceTargetType ?? typeInfo.ConvertedType;

            if (vbConvertedType is null)
            {
                return(TypeConversionKind.Unknown);
            }

            if (vbType is null)
            {
                return(GetCommonDelegateTypeOrNull(vbNode, vbConvertedType) is {} ? TypeConversionKind.DelegateConstructor : TypeConversionKind.Unknown);
        public TypeConversionKind AnalyzeConversion(Microsoft.CodeAnalysis.VisualBasic.Syntax.ExpressionSyntax vbNode, bool alwaysExplicit = false, bool isConst = false, ITypeSymbol forceSourceType = null, ITypeSymbol forceTargetType = null)
        {
            var typeInfo        = ModelExtensions.GetTypeInfo(_semanticModel, vbNode);
            var vbType          = forceSourceType ?? typeInfo.Type;
            var vbConvertedType = forceTargetType ?? typeInfo.ConvertedType;

            if (vbType is null || vbConvertedType is null)
            {
                return(TypeConversionKind.Unknown);
            }

            if (vbType.IsEnumType())
            {
                if (vbConvertedType.IsNumericType())
                {
                    return(TypeConversionKind.NonDestructiveCast);
                }
                else if (vbType.Equals(vbConvertedType) ||
                         (vbConvertedType.IsNullable() && vbType.Equals(vbConvertedType.GetNullableUnderlyingType())) ||
                         vbConvertedType.SpecialType == SpecialType.System_Object)
                {
                    return(TypeConversionKind.Identity);
                }
                else if (vbConvertedType.SpecialType == SpecialType.System_String)
                {
                    return(TypeConversionKind.EnumCastThenConversion);
                }
                else
                {
                    return(TypeConversionKind.Conversion);
                }
            }

            var vbCompilation   = (VBasic.VisualBasicCompilation)_semanticModel.Compilation;
            var vbConversion    = vbCompilation.ClassifyConversion(vbType, vbConvertedType);
            var csType          = GetCSType(vbType, vbNode);
            var csConvertedType = GetCSType(vbConvertedType);

            if (csType != null && csConvertedType != null &&
                TryAnalyzeCsConversion(vbNode, csType, csConvertedType, vbConversion, vbConvertedType, vbType, vbCompilation, isConst, out TypeConversionKind analyzeConversion))
            {
                return(analyzeConversion);
            }

            return(AnalyzeVbConversion(alwaysExplicit, vbType, vbConvertedType, vbConversion));
        }
Exemplo n.º 20
0
        private ExpressionSyntax AddTypeConversion(VBSyntax.ExpressionSyntax vbNode, ExpressionSyntax csNode, TypeConversionKind conversionKind, bool addParenthesisIfNeeded, ITypeSymbol vbType, ITypeSymbol vbConvertedType)
        {
            switch (conversionKind)
            {
            case TypeConversionKind.FractionalNumberRoundThenCast:
                csNode = AddRoundInvocation(vbNode, csNode, vbType, vbConvertedType);
                return(AddTypeConversion(vbNode, csNode, TypeConversionKind.NonDestructiveCast, addParenthesisIfNeeded, vbType, vbConvertedType));

            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();
            }
        }
Exemplo n.º 21
0
        public static bool ConvertStringToCharLiteral(Microsoft.CodeAnalysis.VisualBasic.Syntax.ExpressionSyntax node,
                                                      ITypeSymbol convertedType,
                                                      out char chr)
        {
            var preferChar = node.Parent is VBSyntax.PredefinedCastExpressionSyntax pces &&
                             pces.Keyword.IsKind(Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.CCharKeyword) ||
                             convertedType?.SpecialType == SpecialType.System_Char;

            if (preferChar && node.SkipParens() is VBSyntax.LiteralExpressionSyntax les &&
                les.Token.Value is string str &&
                str.Length == 1)
            {
                chr = str.Single();
                return(true);
            }

            chr = default;
            return(false);
        }
Exemplo n.º 22
0
        public TypeConversionKind AnalyzeConversion(Microsoft.CodeAnalysis.VisualBasic.Syntax.ExpressionSyntax vbNode, bool alwaysExplicit = false)
        {
            var typeInfo        = ModelExtensions.GetTypeInfo(_semanticModel, vbNode);
            var vbType          = typeInfo.Type;
            var vbConvertedType = typeInfo.ConvertedType;

            if (vbType is null || vbConvertedType is null)
            {
                return(TypeConversionKind.Unknown);
            }

            if (vbType.IsEnumType())
            {
                if (vbConvertedType.IsNumericType())
                {
                    return(TypeConversionKind.NonDestructiveCast);
                }
                else if (vbType.Equals(vbConvertedType) ||
                         (vbConvertedType.IsNullable() && vbType.Equals(vbConvertedType.GetNullableUnderlyingType())) ||
                         vbConvertedType.SpecialType == SpecialType.System_Object)
                {
                    return(TypeConversionKind.Identity);
                }
                else
                {
                    return(TypeConversionKind.Conversion);
                }
            }

            var vbCompilation   = _semanticModel.Compilation as VisualBasicCompilation;
            var vbConversion    = vbCompilation.ClassifyConversion(vbType, vbConvertedType);
            var csType          = _csCompilation.GetTypeByMetadataName(vbType.GetFullMetadataName());
            var csConvertedType = _csCompilation.GetTypeByMetadataName(vbConvertedType.GetFullMetadataName());

            if (csType != null && csConvertedType != null &&
                TryAnalyzeCsConversion(vbNode, csType, csConvertedType, vbConversion, vbConvertedType, vbType, vbCompilation, out TypeConversionKind analyzeConversion))
            {
                return(analyzeConversion);
            }

            return(AnalyzeVbConversion(alwaysExplicit, vbType, vbConvertedType, vbConversion));
        }
Exemplo n.º 23
0
        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();
            }
        }
        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);
        }
Exemplo n.º 25
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);
        }
Exemplo n.º 26
0
 private bool IsImplicitConstantConversion(VBSyntax.ExpressionSyntax vbNode)
 {
     return(_semanticModel.GetOperation(vbNode).Parent is IConversionOperation co && co.IsImplicit && co.Operand.ConstantValue.HasValue);
 }