コード例 #1
0
        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));
        }
コード例 #2
0
        private async Task <ExpressionSyntax> ConvertToPowOperatorAsync(VBSyntax.BinaryExpressionSyntax node)
        {
            var(lhs, rhs) = await AcceptSidesAsync(node);

            lhs = ConvertTo(node.Left, lhs, SpecialType.System_Double);
            rhs = ConvertTo(node.Right, rhs, SpecialType.System_Double);
            return(new KnownMethod(nameof(System), nameof(Math), nameof(Math.Pow))
                   .Invoke(_visualBasicEqualityComparison.ExtraUsingDirectives, lhs, rhs));
        }
コード例 #3
0
        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));
        }
コード例 #4
0
    public static 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));
    }
コード例 #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)));
        }
コード例 #6
0
        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);
        }
コード例 #7
0
        /// <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).ConvertedType;

            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(null);    //Handled elsewhere
                    }
                    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(null);     //Handled elsewhere
                    }
                    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, SyntaxKind.LessThanOrEqualExpression));
                    }
                    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, SyntaxKind.GreaterThanOrEqualExpression));
                    }
                    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, SyntaxKind.LessThanExpression));
                    }
                    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, SyntaxKind.GreaterThanExpression));
                    }
                    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);
        }
コード例 #8
0
 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));
 }
コード例 #9
0
        private async Task <ExpressionSyntax> ConvertToMethodAsync(VBSyntax.BinaryExpressionSyntax node, KnownMethod member)
        {
            var(lhs, rhs) = await AcceptSidesAsync(node);

            return(member.Invoke(_visualBasicEqualityComparison.ExtraUsingDirectives, lhs, rhs));
        }
コード例 #10
0
 private static async Task <ExpressionSyntax> ConvertToDecimalComparisonOperatorAsync(VBSyntax.BinaryExpressionSyntax node)
 {
     return(null);
 }
コード例 #11
0
 private static async Task <ExpressionSyntax> ConvertToObjectShortCircuitOperatorAsync(VBSyntax.BinaryExpressionSyntax node)
 {
     return(null);
 }
コード例 #12
0
 private static async Task <ExpressionSyntax> ConvertToConcatenateOperatorAsync(VBSyntax.BinaryExpressionSyntax node)
 {
     return(null);
 }
コード例 #13
0
 private async Task <ExpressionSyntax> ConvertToObjectBinaryOperatorAsync(VBSyntax.BinaryExpressionSyntax node, KnownMethod member) =>
 await ConvertToMethodAsync(node, member);
コード例 #14
0
 /// <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 static async Task <ExpressionSyntax> ConvertToDecimalBinaryOperatorAsync(VBSyntax.BinaryExpressionSyntax node, KnownMethod member) =>
 default;