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); }
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)); }
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);