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();
            }
        }
Example #2
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 IsCorrectType) GetConstantOrNull(VBSyntax.ExpressionSyntax vbNode, ITypeSymbol type, TypeConversionAnalyzer.TypeConversionKind analyzedConversionKind, ExpressionSyntax csNode)
        {
            var vbOperation = _semanticModel.GetOperation(vbNode).SkipParens(true);

            // Guideline tradeoff: Usually would aim for erring on the side of correct runtime behaviour. But making lots of simple constants unreadable for the sake of an edge case that will turn into an easily fixed compile error seems overkill.
            // See https://github.com/icsharpcode/CodeConverter/blob/master/.github/CONTRIBUTING.md#deciding-what-the-output-should-be
            bool isExactType = analyzedConversionKind == TypeConversionAnalyzer.TypeConversionKind.Identity;

            if ((isExactType || analyzedConversionKind == TypeConversionAnalyzer.TypeConversionKind.NonDestructiveCast) &&
                IsProbablyConstExpression(vbOperation))
            {
                return(csNode, isExactType);
            }

            if (TryCompileTimeEvaluate(vbOperation, out var result))
            {
                if (type.Name == "Char" && result is int resultInt)
                {
                    result = Strings.ChrW(resultInt);
                }
                else if (ConversionsTypeFullNames.TryGetValue(type.GetFullMetadataName(), out var method))
                {
                    result = method.Invoke(null, new[] { result });
                }
                return(LiteralConversions.GetLiteralExpression(result, convertedType: type), true);
            }

            return(null, false);
        }
Example #4
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");
        }
Example #5
0
            private async Task <ExpressionSyntax> ConvertToStringComparisonOperatorAsync(VBSyntax.BinaryExpressionSyntax node, SyntaxKind expressionKind)
            {
                var(lhs, rhs) = await AcceptSidesAsync(node);

                lhs = VisualBasicEqualityComparison.VbCoerceToString(lhs, _semanticModel.GetTypeInfo(node.Left));
                rhs = VisualBasicEqualityComparison.VbCoerceToString(rhs, _semanticModel.GetTypeInfo(node.Right));
                var member = new KnownMethod(_compilerServices, _operators, "CompareString");
                var optionaCompareTextBoolLiteralExpression = _visualBasicEqualityComparison.OptionCompareTextCaseInsensitiveBoolExpression;
                var comparedLhs = member.Invoke(_visualBasicEqualityComparison.ExtraUsingDirectives, lhs, rhs, optionaCompareTextBoolLiteralExpression);

                return(SyntaxFactory.BinaryExpression(expressionKind, comparedLhs, LiteralConversions.GetLiteralExpression(0)));
            }
Example #6
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();
            }
        }
        public ExpressionSyntax GetConstantOrNull(VBSyntax.ExpressionSyntax vbNode, ITypeSymbol type, ExpressionSyntax csNode)
        {
            var vbOperation = _semanticModel.GetOperation(vbNode).SkipParens(true);

            // Guideline tradeoff: Usually would aim for erring on the side of correct runtime behaviour. But making lots of simple constants unreadable for the sake of an edge case that will turn into an easily fixed compile error seems overkill.
            // See https://github.com/icsharpcode/CodeConverter/blob/master/.github/CONTRIBUTING.md#deciding-what-the-output-should-be
            if (Equals(vbOperation.Type, type) && IsProbablyConstExpression(vbOperation))
            {
                return(csNode);
            }

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

            return(null);
        }
Example #8
0
 public ExpressionSyntax Literal(object o, string textForUser = null, ITypeSymbol convertedType = null) => LiteralConversions.GetLiteralExpression(o, textForUser, convertedType);
 public ExpressionSyntax Literal(object o, string textForUser = null) => LiteralConversions.GetLiteralExpression(o, textForUser);