@@ -32,6 +32,7 @@ internal class ExpressionNodeVisitor : VBasic.VisualBasicSyntaxVisitor<Task<CSha
3232 public CommentConvertingVisitorWrapper TriviaConvertingExpressionVisitor { get ; }
3333 private readonly SemanticModel _semanticModel ;
3434 private readonly HashSet < string > _extraUsingDirectives ;
35+ private readonly IOperatorConverter _operatorConverter ;
3536 private readonly bool _optionCompareText = false ;
3637 private readonly VisualBasicEqualityComparison _visualBasicEqualityComparison ;
3738 private readonly Stack < ExpressionSyntax > _withBlockLhs = new Stack < ExpressionSyntax > ( ) ;
@@ -56,7 +57,7 @@ public ExpressionNodeVisitor(SemanticModel semanticModel,
5657 _csCompilation = csCompilation ;
5758 _typeContext = typeContext ;
5859 _extraUsingDirectives = extraUsingDirectives ;
59-
60+ _operatorConverter = VbOperatorConversion . Create ( TriviaConvertingExpressionVisitor , semanticModel , visualBasicEqualityComparison ) ;
6061 // If this isn't needed, the assembly with Conversions may not be referenced, so this must be done lazily
6162 _convertMethodsLookupByReturnType =
6263 new Lazy < IDictionary < ITypeSymbol , string > > ( ( ) => CreateConvertMethodsLookupByReturnType ( semanticModel ) ) ;
@@ -674,7 +675,7 @@ private ExpressionSyntax AsBool(VBSyntax.UnaryExpressionSyntax node, ExpressionS
674675
675676 private async Task < ExpressionSyntax > NegateAndSimplifyOrNullAsync ( VBSyntax . UnaryExpressionSyntax node , ExpressionSyntax expr )
676677 {
677- if ( await ConvertNothingComparisonOrNullAsync ( node . Operand , true ) is ExpressionSyntax nothingComparison ) {
678+ if ( await _operatorConverter . ConvertNothingComparisonOrNullAsync ( node . Operand , true ) is ExpressionSyntax nothingComparison ) {
678679 return nothingComparison ;
679680 } else if ( expr is BinaryExpressionSyntax bes && bes . OperatorToken . IsKind ( SyntaxKind . EqualsToken ) ) {
680681 return bes . WithOperatorToken ( SyntaxFactory . Token ( SyntaxKind . ExclamationEqualsToken ) ) ;
@@ -695,7 +696,9 @@ private CSharpSyntaxNode ConvertAddressOf(VBSyntax.UnaryExpressionSyntax node, E
695696
696697 public override async Task < CSharpSyntaxNode > VisitBinaryExpression ( VBasic . Syntax . BinaryExpressionSyntax node )
697698 {
698- if ( await ConvertNothingComparisonOrNullAsync ( node ) is CSharpSyntaxNode nothingComparison ) return nothingComparison ;
699+ if ( await _operatorConverter . ConvertRewrittenBinaryOperatorOrNullAsync ( node ) is ExpressionSyntax operatorNode ) {
700+ return operatorNode ;
701+ }
699702
700703 var lhsTypeInfo = _semanticModel . GetTypeInfo ( node . Left ) ;
701704 var rhsTypeInfo = _semanticModel . GetTypeInfo ( node . Right ) ;
@@ -731,78 +734,18 @@ public override async Task<CSharpSyntaxNode> VisitBinaryExpression(VBasic.Syntax
731734
732735 omitConversion |= lhsTypeInfo . Type != null && rhsTypeInfo . Type != null &&
733736 lhsTypeInfo . Type . IsEnumType ( ) && Equals ( lhsTypeInfo . Type , rhsTypeInfo . Type )
734- && ! node . IsKind ( VBasic . SyntaxKind . AddExpression , VBasic . SyntaxKind . SubtractExpression , VBasic . SyntaxKind . MultiplyExpression , VBasic . SyntaxKind . DivideExpression , VBasic . SyntaxKind . IntegerDivideExpression ) ;
737+ && ! node . IsKind ( VBasic . SyntaxKind . AddExpression , VBasic . SyntaxKind . SubtractExpression , VBasic . SyntaxKind . MultiplyExpression , VBasic . SyntaxKind . DivideExpression , VBasic . SyntaxKind . IntegerDivideExpression , VBasic . SyntaxKind . ModuloExpression ) ;
735738 lhs = omitConversion ? lhs : CommonConversions . TypeConversionAnalyzer . AddExplicitConversion ( node . Left , lhs , forceTargetType : forceLhsTargetType ) ;
736739 rhs = omitConversion || omitRightConversion ? rhs : CommonConversions . TypeConversionAnalyzer . AddExplicitConversion ( node . Right , rhs ) ;
737740
738741
739- if ( node . IsKind ( VBasic . SyntaxKind . ExponentiateExpression ,
740- VBasic . SyntaxKind . ExponentiateAssignmentStatement ) ) {
741- return SyntaxFactory . InvocationExpression (
742- ValidSyntaxFactory . MemberAccess ( nameof ( Math ) , nameof ( Math . Pow ) ) ,
743- ExpressionSyntaxExtensions . CreateArgList ( lhs , rhs ) ) ;
744- }
745-
746- if ( node . IsKind ( VBasic . SyntaxKind . LikeExpression ) ) {
747- var compareText = ValidSyntaxFactory . MemberAccess ( "CompareMethod" , _optionCompareText ? "Text" : "Binary" ) ;
748- var likeString = ValidSyntaxFactory . MemberAccess ( "LikeOperator" , "LikeString" ) ;
749- _extraUsingDirectives . Add ( "Microsoft.VisualBasic" ) ;
750- _extraUsingDirectives . Add ( "Microsoft.VisualBasic.CompilerServices" ) ;
751- return SyntaxFactory . InvocationExpression (
752- likeString ,
753- ExpressionSyntaxExtensions . CreateArgList ( lhs , rhs , compareText )
754- ) ;
755- }
756-
757742 var kind = VBasic . VisualBasicExtensions . Kind ( node ) . ConvertToken ( TokenContext . Local ) ;
758743 var op = SyntaxFactory . Token ( CSharpUtil . GetExpressionOperatorTokenKind ( kind ) ) ;
759744
760745 var csBinExp = SyntaxFactory . BinaryExpression ( kind , lhs , op , rhs ) ;
761746 return node . Parent . IsKind ( VBasic . SyntaxKind . SimpleArgument ) ? csBinExp : csBinExp . AddParens ( ) ;
762747 }
763748
764- private async Task < ExpressionSyntax > ConvertNothingComparisonOrNullAsync ( VBSyntax . ExpressionSyntax exprNode , bool negateExpression = false )
765- {
766- if ( ! ( exprNode is VBSyntax . BinaryExpressionSyntax node ) || ! node . IsKind ( VBasic . SyntaxKind . IsExpression , VBasic . SyntaxKind . EqualsExpression , VBasic . SyntaxKind . IsNotExpression , VBasic . SyntaxKind . NotEqualsExpression ) ) {
767- return null ;
768- }
769- ExpressionSyntax otherArgument ;
770- if ( node . Left . IsKind ( VBasic . SyntaxKind . NothingLiteralExpression ) ) {
771- otherArgument = ( ExpressionSyntax ) await ConvertIsOrIsNotExpressionArgAsync ( node . Right ) ;
772- } else if ( node . Right . IsKind ( VBasic . SyntaxKind . NothingLiteralExpression ) ) {
773- otherArgument = ( ExpressionSyntax ) await ConvertIsOrIsNotExpressionArgAsync ( node . Left ) ;
774- } else {
775- return null ;
776- }
777-
778- var isReference = node . IsKind ( VBasic . SyntaxKind . IsExpression , VBasic . SyntaxKind . IsNotExpression ) ;
779- var notted = node . IsKind ( VBasic . SyntaxKind . IsNotExpression , VBasic . SyntaxKind . NotEqualsExpression ) || negateExpression ;
780- return notted ? CommonConversions . NotNothingComparison ( otherArgument , isReference ) : CommonConversions . NothingComparison ( otherArgument , isReference ) ;
781- }
782-
783- private async Task < CSharpSyntaxNode > ConvertIsOrIsNotExpressionArgAsync ( VBSyntax . ExpressionSyntax binaryExpressionArg )
784- {
785- return await ConvertMyGroupCollectionPropertyGetWithUnderlyingFieldAsync ( binaryExpressionArg )
786- ?? await binaryExpressionArg . AcceptAsync ( TriviaConvertingExpressionVisitor ) ;
787- }
788-
789- private async Task < ExpressionSyntax > ConvertMyGroupCollectionPropertyGetWithUnderlyingFieldAsync ( SyntaxNode node )
790- {
791- var operation = _semanticModel . GetOperation ( node ) ;
792- switch ( operation )
793- {
794- case IConversionOperation co :
795- return await ConvertMyGroupCollectionPropertyGetWithUnderlyingFieldAsync ( co . Operand . Syntax ) ;
796- case IPropertyReferenceOperation pro when pro . Property . IsMyGroupCollectionProperty ( ) :
797- var associatedField = pro . Property . GetAssociatedField ( ) ;
798- var propertyReferenceOperation = ( ( IPropertyReferenceOperation ) pro . Instance ) ;
799- var qualification = ( ExpressionSyntax ) await propertyReferenceOperation . Syntax . AcceptAsync ( TriviaConvertingExpressionVisitor ) ;
800- return SyntaxFactory . MemberAccessExpression ( SyntaxKind . SimpleMemberAccessExpression , qualification , SyntaxFactory . IdentifierName ( associatedField . Name ) ) ;
801- default :
802- return null ;
803- }
804- }
805-
806749 private async Task < CSharpSyntaxNode > WithRemovedRedundantConversionOrNullAsync ( VBSyntax . InvocationExpressionSyntax conversionNode , ISymbol invocationSymbol )
807750 {
808751 if ( invocationSymbol . ContainingType . Name != nameof ( Conversions ) ||
@@ -1521,7 +1464,7 @@ private static CSharpSyntaxNode ReplaceRightmostIdentifierText(CSharpSyntaxNode
15211464 /// </summary>
15221465 private static bool ProbablyNotAMethodCall ( VBasic . Syntax . InvocationExpressionSyntax node , ISymbol symbol , ITypeSymbol symbolReturnType )
15231466 {
1524- return ! node . IsParentKind ( VBasic . SyntaxKind . CallStatement ) && ! ( symbol is IMethodSymbol ) && symbolReturnType . IsErrorType ( ) && node . Expression is VBasic . Syntax . IdentifierNameSyntax && node . ArgumentList ? . Arguments . Any ( ) == true ;
1467+ return ! node . IsParentKind ( VBasic . SyntaxKind . CallStatement ) && ! ( symbol is IMethodSymbol ) && symbolReturnType . IsErrorType ( ) && node . Expression is VBasic . Syntax . IdentifierNameSyntax && node . ArgumentList ? . Arguments . Count ( ) == 1 ;
15251468 }
15261469
15271470 private async Task < ArgumentListSyntax > ConvertArgumentListOrEmptyAsync ( SyntaxNode node , VBSyntax . ArgumentListSyntax argumentList )
0 commit comments