Example #1
0
            private async Task <ExpressionSyntax> ConvertToPowOperatorAsync(VBSyntax.BinaryExpressionSyntax node)
            {
                var(lhs, rhs) = await AcceptSidesAsync(node);

                return(new KnownMethod(nameof(System), nameof(Math), nameof(Math.Pow))
                       .Invoke(_visualBasicEqualityComparison.ExtraUsingDirectives, lhs, rhs));
            }
            private async Task <ExpressionSyntax> ConvertToLikeOperatorAsync(VBSyntax.BinaryExpressionSyntax node, KnownMethod member)
            {
                var(lhs, rhs) = await AcceptSidesAsync(node);

                var compareText = ValidSyntaxFactory.MemberAccess("CompareMethod", _visualBasicEqualityComparison.OptionCompareTextCaseInsensitive ? "Text" : "Binary");

                _visualBasicEqualityComparison.ExtraUsingDirectives.Add("Microsoft.VisualBasic");
                return(member.Invoke(_visualBasicEqualityComparison.ExtraUsingDirectives, lhs, rhs, compareText));
            }
        public RequiredType GetObjectEqualityType(VBSyntax.BinaryExpressionSyntax node, TypeInfo leftType, TypeInfo rightType)
        {
            var typeInfos = new[] { leftType, rightType };

            if (!node.IsKind(VBasic.SyntaxKind.EqualsExpression, VBasic.SyntaxKind.NotEqualsExpression))
            {
                return(RequiredType.None);
            }
            return(GetObjectEqualityType(typeInfos));
        }
        public ExpressionSyntax GetFullExpressionForVbObjectComparison(VBSyntax.BinaryExpressionSyntax node, ExpressionSyntax lhs, ExpressionSyntax rhs)
        {
            _extraUsingDirectives.Add("Microsoft.VisualBasic.CompilerServices");
            var optionCompareTextCaseInsensitive = SyntaxFactory.Argument(SyntaxFactory.LiteralExpression(OptionCompareTextCaseInsensitive ? SyntaxKind.TrueKeyword : SyntaxKind.FalseLiteralExpression));
            var compareObject = SyntaxFactory.InvocationExpression(ValidSyntaxFactory.MemberAccess(nameof(Operators), nameof(Operators.ConditionalCompareObjectEqual)),
                                                                   SyntaxFactory.ArgumentList(SyntaxFactory.SeparatedList(new[]
                                                                                                                          { SyntaxFactory.Argument(lhs), SyntaxFactory.Argument(rhs), optionCompareTextCaseInsensitive })));

            return(NegateIfNeeded(node, compareObject));
        }
            private static VBSyntax.ExpressionSyntax ArgComparedToNull(VBSyntax.BinaryExpressionSyntax node)
            {
                if (node.Left.IsKind(VBasic.SyntaxKind.NothingLiteralExpression))
                {
                    return(node.Right);
                }
                else if (node.Right.IsKind(VBasic.SyntaxKind.NothingLiteralExpression))
                {
                    return(node.Left);
                }

                return(null);
            }
        public RequiredType GetObjectEqualityType(VBSyntax.BinaryExpressionSyntax node, TypeInfo leftType, TypeInfo rightType)
        {
            var typeInfos = new[] { leftType, rightType };

            if (!node.IsKind(VBasic.SyntaxKind.EqualsExpression, VBasic.SyntaxKind.NotEqualsExpression))
            {
                return(RequiredType.None);
            }

            bool requiresVbEqualityCheck = typeInfos.Any(t => t.Type?.SpecialType == SpecialType.System_Object);

            if (typeInfos.All(t => t.Type != null) && typeInfos.All(
                    t => t.Type.SpecialType == SpecialType.System_String ||
                    t.Type.IsArrayOf(SpecialType.System_Char)))
            {
                return(RequiredType.StringOnly);
            }
            ;

            return(requiresVbEqualityCheck ? RequiredType.Object : RequiredType.None);
        }
        public bool TryConvertToNullOrEmptyCheck(VBSyntax.BinaryExpressionSyntax node, ExpressionSyntax lhs,
                                                 ExpressionSyntax rhs, out CSharpSyntaxNode visitBinaryExpression)
        {
            bool lhsEmpty = IsNothingOrEmpty(node.Left);
            bool rhsEmpty = IsNothingOrEmpty(node.Right);

            if (lhsEmpty || rhsEmpty)
            {
                var arg         = lhsEmpty ? rhs : lhs;
                var nullOrEmpty = SyntaxFactory.InvocationExpression(
                    SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                                         SyntaxFactory.IdentifierName("string"),
                                                         SyntaxFactory.IdentifierName("IsNullOrEmpty")),
                    SyntaxFactory.ArgumentList(SyntaxFactory.SeparatedList(new[]
                                                                           { SyntaxFactory.Argument(arg) })));
                {
                    visitBinaryExpression = NegateIfNeeded(node, nullOrEmpty);
                    return(true);
                }
            }

            visitBinaryExpression = null;
            return(false);
        }
 private async Task <ExpressionSyntax> ConvertToStringComparisonOperatorAsync(VBSyntax.BinaryExpressionSyntax node)
 {
     return(null);
 }
Example #9
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)));
            }
 private static ExpressionSyntax NegateIfNeeded(VBSyntax.BinaryExpressionSyntax node, InvocationExpressionSyntax positiveExpression)
 {
     return(node.IsKind(VBasic.SyntaxKind.EqualsExpression)
         ? (ExpressionSyntax)positiveExpression
         : SyntaxFactory.PrefixUnaryExpression(SyntaxKind.LogicalNotExpression, positiveExpression));
 }
Example #11
0
 public static bool HasOperandOfUnconvertedType(this Microsoft.CodeAnalysis.VisualBasic.Syntax.BinaryExpressionSyntax node, string operandType, SemanticModel semanticModel)
 {
     return(new[] { node.Left, node.Right }.Any(e => UnconvertedIsType(e, operandType, semanticModel)));
 }
            /// <summary>
            /// Started as a paste of:
            /// https://github.com/dotnet/roslyn/blob/master/src/Compilers/VisualBasic/Portable/Lowering/LocalConvertTor/LocalConvertTor_BinaryOperators.vb#L233-L464
            /// See file history to understand any changes
            /// </summary>
            public async Task <ExpressionSyntax> ConvertRewrittenBinaryOperatorOrNullAsync(VBSyntax.BinaryExpressionSyntax node, bool inExpressionLambda = false)
            {
                var opKind   = node.Kind();
                var nodeType = _semanticModel.GetTypeInfo(node).Type;
                var leftType = _semanticModel.GetTypeInfo(node.Left).Type;

                switch (opKind)
                {
                case BinaryOperatorKind.IsExpression:
                case BinaryOperatorKind.IsNotExpression: {
                    if (await ConvertReferenceOrNothingComparisonOrNullAsync(node) is { } nothingComparison)
                    {
                        return(nothingComparison);
                    }

                    break;
                }

                case BinaryOperatorKind.ConcatenateExpression:      // Concat needs to be done before expr trees, so in LocalConvertTor instead of VBSemanticsConvertTor
                {
                    if (nodeType.IsObjectType())
                    {
                        return(await ConvertToObjectBinaryOperatorAsync(node, (_compilerServices, _operators, "ConcatenateObject")));
                    }
                    else
                    {
                        return(await ConvertToConcatenateOperatorAsync(node));
                    }
                }

                case BinaryOperatorKind.LikeExpression: {
                    if (leftType.IsObjectType())
                    {
                        return(await ConvertToLikeOperatorAsync(node, (_compilerServices, "LikeOperator", "LikeObject")));
                    }
                    else
                    {
                        return(await ConvertToLikeOperatorAsync(node, (_compilerServices, "LikeOperator", "LikeString")));
                    }
                }

                case BinaryOperatorKind.EqualsExpression: {
                    // NOTE: For some reason Dev11 seems to still ignore inside the expression tree the fact that the target
                    // type of the binary operator is Boolean and used Object op Object => Object helpers even in this case
                    // despite what is said in comments in RuntimeMembers CodeGenerator::GetHelperForObjRelOp
                    // TODO: Recheck

                    if (nodeType.IsObjectType() || inExpressionLambda && leftType.IsObjectType())
                    {
                        return(await ConvertToObjectComparisonOperatorAsync(node, (_compilerServices, _operators, "CompareObjectEqual")));
                    }
                    else if (nodeType.IsBooleanType())
                    {
                        if (leftType.IsObjectType())
                        {
                            return(await ConvertToObjectComparisonOperatorAsync(node, (_compilerServices, _operators, "ConditionalCompareObjectEqual")));
                        }
                        else if (leftType.IsStringType())
                        {
                            return(await ConvertToStringComparisonOperatorAsync(node));
                        }
                        else if (leftType.IsDecimalType())
                        {
                            return(await ConvertToDecimalComparisonOperatorAsync(node));
                        }
                        else if (leftType.IsDateTimeType())
                        {
                            return(await ConvertToDateComparisonOperatorAsync(node));
                        }
                    }

                    break;
                }

                case BinaryOperatorKind.NotEqualsExpression: {
                    // NOTE: See comment above

                    if (nodeType.IsObjectType() || inExpressionLambda && leftType.IsObjectType())
                    {
                        return(await ConvertToObjectComparisonOperatorAsync(node, (_compilerServices, _operators, "CompareObjectNotEqual")));
                    }
                    else if (nodeType.IsBooleanType())
                    {
                        if (leftType.IsObjectType())
                        {
                            return(await ConvertToObjectComparisonOperatorAsync(node, (_compilerServices, _operators, "ConditionalCompareObjectNotEqual")));
                        }
                        else if (leftType.IsStringType())
                        {
                            return(await ConvertToStringComparisonOperatorAsync(node));
                        }
                        else if (leftType.IsDecimalType())
                        {
                            return(await ConvertToDecimalComparisonOperatorAsync(node));
                        }
                        else if (leftType.IsDateTimeType())
                        {
                            return(await ConvertToDateComparisonOperatorAsync(node));
                        }
                    }

                    break;
                }

                case BinaryOperatorKind.LessThanOrEqualExpression: {
                    // NOTE: See comment above

                    if (nodeType.IsObjectType() || inExpressionLambda && leftType.IsObjectType())
                    {
                        return(await ConvertToObjectComparisonOperatorAsync(node, (_compilerServices, _operators, "CompareObjectLessEqual")));
                    }
                    else if (nodeType.IsBooleanType())
                    {
                        if (leftType.IsObjectType())
                        {
                            return(await ConvertToObjectComparisonOperatorAsync(node, (_compilerServices, _operators, "ConditionalCompareObjectLessEqual")));
                        }
                        else if (leftType.IsStringType())
                        {
                            return(await ConvertToStringComparisonOperatorAsync(node));
                        }
                        else if (leftType.IsDecimalType())
                        {
                            return(await ConvertToDecimalComparisonOperatorAsync(node));
                        }
                        else if (leftType.IsDateTimeType())
                        {
                            return(await ConvertToDateComparisonOperatorAsync(node));
                        }
                    }

                    break;
                }

                case BinaryOperatorKind.GreaterThanOrEqualExpression: {
                    // NOTE: See comment above

                    if (nodeType.IsObjectType() || inExpressionLambda && leftType.IsObjectType())
                    {
                        return(await ConvertToObjectComparisonOperatorAsync(node, (_compilerServices, _operators, "CompareObjectGreaterEqual")));
                    }
                    else if (nodeType.IsBooleanType())
                    {
                        if (leftType.IsObjectType())
                        {
                            return(await ConvertToObjectComparisonOperatorAsync(node, (_compilerServices, _operators, "ConditionalCompareObjectGreaterEqual")));
                        }
                        else if (leftType.IsStringType())
                        {
                            return(await ConvertToStringComparisonOperatorAsync(node));
                        }
                        else if (leftType.IsDecimalType())
                        {
                            return(await ConvertToDecimalComparisonOperatorAsync(node));
                        }
                        else if (leftType.IsDateTimeType())
                        {
                            return(await ConvertToDateComparisonOperatorAsync(node));
                        }
                    }

                    break;
                }

                case BinaryOperatorKind.LessThanExpression: {
                    // NOTE: See comment above

                    if (nodeType.IsObjectType() || inExpressionLambda && leftType.IsObjectType())
                    {
                        return(await ConvertToObjectComparisonOperatorAsync(node, (_compilerServices, _operators, "CompareObjectLess")));
                    }
                    else if (nodeType.IsBooleanType())
                    {
                        if (leftType.IsObjectType())
                        {
                            return(await ConvertToObjectComparisonOperatorAsync(node, (_compilerServices, _operators, "ConditionalCompareObjectLess")));
                        }
                        else if (leftType.IsStringType())
                        {
                            return(await ConvertToStringComparisonOperatorAsync(node));
                        }
                        else if (leftType.IsDecimalType())
                        {
                            return(await ConvertToDecimalComparisonOperatorAsync(node));
                        }
                        else if (leftType.IsDateTimeType())
                        {
                            return(await ConvertToDateComparisonOperatorAsync(node));
                        }
                    }

                    break;
                }

                case BinaryOperatorKind.GreaterThanExpression: {
                    // NOTE: See comment above

                    if (nodeType.IsObjectType() || inExpressionLambda && leftType.IsObjectType())
                    {
                        return(await ConvertToObjectComparisonOperatorAsync(node, (_compilerServices, _operators, "CompareObjectGreater")));
                    }
                    else if (nodeType.IsBooleanType())
                    {
                        if (leftType.IsObjectType())
                        {
                            return(await ConvertToObjectComparisonOperatorAsync(node, (_compilerServices, _operators, "ConditionalCompareObjectGreater")));
                        }
                        else if (leftType.IsStringType())
                        {
                            return(await ConvertToStringComparisonOperatorAsync(node));
                        }
                        else if (leftType.IsDecimalType())
                        {
                            return(await ConvertToDecimalComparisonOperatorAsync(node));
                        }
                        else if (leftType.IsDateTimeType())
                        {
                            return(await ConvertToDateComparisonOperatorAsync(node));
                        }
                    }

                    break;
                }

                case BinaryOperatorKind.AddExpression: {
                    if (nodeType.IsObjectType() && !inExpressionLambda)
                    {
                        return(await ConvertToObjectBinaryOperatorAsync(node, (_compilerServices, _operators, "AddObject")));
                    }
                    else if (nodeType.IsDecimalType())
                    {
                        return(await ConvertToDecimalBinaryOperatorAsync(node, (nameof(System), nameof(Decimal), nameof(Decimal.Add))));
                    }
                    break;
                }

                case BinaryOperatorKind.SubtractExpression: {
                    if (nodeType.IsObjectType() && !inExpressionLambda)
                    {
                        return(await ConvertToObjectBinaryOperatorAsync(node, (_compilerServices, _operators, "SubtractObject")));
                    }
                    else if (nodeType.IsDecimalType())
                    {
                        return(await ConvertToDecimalBinaryOperatorAsync(node, (nameof(System), nameof(Decimal), nameof(Decimal.Subtract))));
                    }

                    break;
                }

                case BinaryOperatorKind.MultiplyExpression: {
                    if (nodeType.IsObjectType() && !inExpressionLambda)
                    {
                        return(await ConvertToObjectBinaryOperatorAsync(node, (_compilerServices, _operators, "MultiplyObject")));
                    }
                    else if (nodeType.IsDecimalType())
                    {
                        return(await ConvertToDecimalBinaryOperatorAsync(node, (nameof(System), nameof(Decimal), nameof(Decimal.Multiply))));
                    }

                    break;
                }

                case BinaryOperatorKind.ModuloExpression: {
                    if (nodeType.IsObjectType() && !inExpressionLambda)
                    {
                        return(await ConvertToObjectBinaryOperatorAsync(node, (_compilerServices, _operators, "ModObject")));
                    }
                    else if (nodeType.IsDecimalType())
                    {
                        return(await ConvertToDecimalBinaryOperatorAsync(node, (nameof(System), nameof(Decimal), nameof(Decimal.Remainder))));
                    }

                    break;
                }

                case BinaryOperatorKind.DivideExpression: {
                    if (nodeType.IsObjectType() && !inExpressionLambda)
                    {
                        return(await ConvertToObjectBinaryOperatorAsync(node, (_compilerServices, _operators, "DivideObject")));
                    }
                    else if (nodeType.IsDecimalType())
                    {
                        return(await ConvertToDecimalBinaryOperatorAsync(node, (nameof(System), nameof(Decimal), nameof(Decimal.Divide))));
                    }

                    break;
                }

                case BinaryOperatorKind.IntegerDivideExpression: {
                    if (nodeType.IsObjectType() && !inExpressionLambda)
                    {
                        return(await ConvertToObjectBinaryOperatorAsync(node, (_compilerServices, _operators, "IntDivideObject")));
                    }

                    break;
                }

                case BinaryOperatorKind.ExponentiateExpression: {
                    if (nodeType.IsObjectType() && !inExpressionLambda)
                    {
                        return(await ConvertToObjectBinaryOperatorAsync(node, (_compilerServices, _operators, "ExponentObject")));
                    }
                    else
                    {
                        return(await ConvertToPowOperatorAsync(node));
                    }
                }

                case BinaryOperatorKind.LeftShiftExpression: {
                    if (nodeType.IsObjectType() && !inExpressionLambda)
                    {
                        return(await ConvertToObjectBinaryOperatorAsync(node, (_compilerServices, _operators, "LeftShiftObject")));
                    }

                    break;
                }

                case BinaryOperatorKind.RightShiftExpression: {
                    if (nodeType.IsObjectType() && !inExpressionLambda)
                    {
                        return(await ConvertToObjectBinaryOperatorAsync(node, (_compilerServices, _operators, "RightShiftObject")));
                    }

                    break;
                }

                case BinaryOperatorKind.OrElseExpression:
                case BinaryOperatorKind.AndAlsoExpression: {
                    if (nodeType.IsObjectType() && !inExpressionLambda)
                    {
                        return(await ConvertToObjectShortCircuitOperatorAsync(node));
                    }

                    break;
                }

                case var _ when node.OperatorToken.IsKind(BinaryOperatorKind.XorKeyword): {
                    if (nodeType.IsObjectType() && !inExpressionLambda)
                    {
                        return(await ConvertToObjectBinaryOperatorAsync(node, (_compilerServices, _operators, "XorObject")));
                    }

                    break;
                }

                case BinaryOperatorKind.OrExpression: {
                    if (nodeType.IsObjectType() && !inExpressionLambda)
                    {
                        return(await ConvertToObjectBinaryOperatorAsync(node, (_compilerServices, _operators, "OrObject")));
                    }

                    break;
                }

                case BinaryOperatorKind.AndExpression: {
                    if (nodeType.IsObjectType() && !inExpressionLambda)
                    {
                        return(await ConvertToObjectBinaryOperatorAsync(node, (_compilerServices, _operators, "AndObject")));
                    }

                    break;
                }
                }

                return(null);
            }
 /// <remarks>No need to implement these since this is only called for things that are already decimal and hence will resolve operator in C#</remarks>
 private async Task <ExpressionSyntax> ConvertToDecimalBinaryOperatorAsync(VBSyntax.BinaryExpressionSyntax node, KnownMethod member) =>
 default;
            private async Task <ExpressionSyntax> ConvertToMethodAsync(VBSyntax.BinaryExpressionSyntax node, KnownMethod member)
            {
                var(lhs, rhs) = await AcceptSidesAsync(node);

                return(member.Invoke(_visualBasicEqualityComparison.ExtraUsingDirectives, lhs, rhs));
            }
 private async Task <(ExpressionSyntax, ExpressionSyntax)> AcceptSidesAsync(VBSyntax.BinaryExpressionSyntax node)
 {
     return(await _triviaConvertingVisitor.AcceptAsync <ExpressionSyntax>(node.Left, SourceTriviaMapKind.All), await _triviaConvertingVisitor.AcceptAsync <ExpressionSyntax>(node.Right, SourceTriviaMapKind.All));
 }
 private static ExpressionSyntax NegateIfNeeded(VBSyntax.BinaryExpressionSyntax node, InvocationExpressionSyntax positiveExpression)
 {
     return(node.IsKind(VBasic.SyntaxKind.NotEqualsExpression)
        ? Negate(positiveExpression)
        : (ExpressionSyntax)positiveExpression);
 }
 private async Task <ExpressionSyntax> ConvertToObjectShortCircuitOperatorAsync(VBSyntax.BinaryExpressionSyntax node)
 {
     return(null);
 }
 private async Task <ExpressionSyntax> ConvertToConcatenateOperatorAsync(VBSyntax.BinaryExpressionSyntax node)
 {
     return(null);
 }
            private async Task <ExpressionSyntax> ConvertToObjectComparisonOperatorAsync(VBSyntax.BinaryExpressionSyntax node, KnownMethod member)
            {
                var(lhs, rhs) = await AcceptSidesAsync(node);

                member = (member.Import, member.TypeName, "Conditional" + member.MethodName); //The VB compiler would late bind, but this should provide identical results in most cases I think
                var optionaCompareTextBoolLiteralExpression = _visualBasicEqualityComparison.OptionCompareTextCaseInsensitiveBoolExpression;

                return(member.Invoke(_visualBasicEqualityComparison.ExtraUsingDirectives, lhs, rhs, optionaCompareTextBoolLiteralExpression));
            }
 private async Task <ExpressionSyntax> ConvertToObjectBinaryOperatorAsync(VBSyntax.BinaryExpressionSyntax node, KnownMethod member) =>
 await ConvertToMethodAsync(node, member);