@@ -44,31 +44,58 @@ public BuiltInVisualBasicOperatorSubstitutions(CommentConvertingVisitorWrapper t
4444 _typeConversionAnalyzer = typeConversionAnalyzer ;
4545 }
4646
47- public async Task < ExpressionSyntax > ConvertNothingComparisonOrNullAsync ( VBSyntax . ExpressionSyntax exprNode , bool negateExpression = false )
47+ public async Task < ExpressionSyntax > ConvertReferenceOrNothingComparisonOrNullAsync ( VBSyntax . ExpressionSyntax exprNode , bool negateExpression = false )
4848 {
49- if ( ! ( exprNode is VBSyntax . BinaryExpressionSyntax node ) || ! node . IsKind ( VBasic . SyntaxKind . IsExpression , VBasic . SyntaxKind . EqualsExpression , VBasic . SyntaxKind . IsNotExpression , VBasic . SyntaxKind . NotEqualsExpression ) ) {
49+ if ( ! ( exprNode is VBSyntax . BinaryExpressionSyntax node ) ||
50+ ! node . IsKind ( VBasic . SyntaxKind . IsExpression , VBasic . SyntaxKind . EqualsExpression , VBasic . SyntaxKind . IsNotExpression , VBasic . SyntaxKind . NotEqualsExpression ) ) {
5051 return null ;
5152 }
53+
54+ var notted =
55+ node . IsKind ( VBasic . SyntaxKind . IsNotExpression , VBasic . SyntaxKind . NotEqualsExpression ) ||
56+ negateExpression ;
57+ var isReferenceComparison = node . IsKind ( VBasic . SyntaxKind . IsExpression , VBasic . SyntaxKind . IsNotExpression ) ;
58+
59+ if ( ArgComparedToNull ( node ) is { } vbOtherArg ) {
60+ var csOtherArg = await ConvertIsOrIsNotExpressionArgAsync ( vbOtherArg ) ;
61+ return notted
62+ ? CommonConversions . NotNothingComparison ( csOtherArg , isReferenceComparison )
63+ : CommonConversions . NothingComparison ( csOtherArg , isReferenceComparison ) ;
64+ }
5265
53- VBSyntax . ExpressionSyntax vbOtherArg ;
54- if ( node . Left . IsKind ( VBasic . SyntaxKind . NothingLiteralExpression ) ) {
55- vbOtherArg = node . Right ;
56- } else if ( node . Right . IsKind ( VBasic . SyntaxKind . NothingLiteralExpression ) ) {
57- vbOtherArg = node . Left ;
58- } else {
59- return null ;
66+ if ( isReferenceComparison ) {
67+
68+ var lhs = await ConvertIsOrIsNotExpressionArgAsync ( node . Left ) ;
69+ var rhs = await ConvertIsOrIsNotExpressionArgAsync ( node . Right ) ;
70+
71+ var equalityCheck = new KnownMethod ( nameof ( System ) , nameof ( Object ) , nameof ( object . ReferenceEquals ) )
72+ . Invoke ( _visualBasicEqualityComparison . ExtraUsingDirectives ,
73+ ConvertTo ( node . Left , lhs , SpecialType . System_Object ) , rhs ) ;
74+ return notted
75+ ? SyntaxFactory . PrefixUnaryExpression ( SyntaxKind . LogicalNotExpression , equalityCheck )
76+ : equalityCheck ;
77+ }
78+ return null ;
79+ }
80+
81+ private static VBSyntax . ExpressionSyntax ArgComparedToNull ( VBSyntax . BinaryExpressionSyntax node )
82+ {
83+ if ( node . Left . IsKind ( VBasic . SyntaxKind . NothingLiteralExpression ) )
84+ {
85+ return node . Right ;
6086 }
61- var csOtherArg = ( ExpressionSyntax ) await ConvertIsOrIsNotExpressionArgAsync ( vbOtherArg ) ;
62- var typeSymbol = _semanticModel . GetTypeInfo ( vbOtherArg ) . Type ;
63- var isReferenceComparison = typeSymbol ? . IsValueType != true || node . IsKind ( VBasic . SyntaxKind . IsExpression , VBasic . SyntaxKind . IsNotExpression ) ;
64- var notted = node . IsKind ( VBasic . SyntaxKind . IsNotExpression , VBasic . SyntaxKind . NotEqualsExpression ) || negateExpression ;
65- return notted ? CommonConversions . NotNothingComparison ( csOtherArg , isReferenceComparison ) : CommonConversions . NothingComparison ( csOtherArg , isReferenceComparison ) ;
87+ else if ( node . Right . IsKind ( VBasic . SyntaxKind . NothingLiteralExpression ) )
88+ {
89+ return node . Left ;
90+ }
91+
92+ return null ;
6693 }
6794
68- private async Task < CSharpSyntaxNode > ConvertIsOrIsNotExpressionArgAsync ( VBSyntax . ExpressionSyntax binaryExpressionArg )
95+ private async Task < ExpressionSyntax > ConvertIsOrIsNotExpressionArgAsync ( VBSyntax . ExpressionSyntax binaryExpressionArg )
6996 {
70- return await ConvertMyGroupCollectionPropertyGetWithUnderlyingFieldAsync ( binaryExpressionArg )
71- ?? await binaryExpressionArg . AcceptAsync ( _triviaConvertingVisitor ) ;
97+ return ( ExpressionSyntax ) ( await ConvertMyGroupCollectionPropertyGetWithUnderlyingFieldAsync ( binaryExpressionArg )
98+ ?? await binaryExpressionArg . AcceptAsync ( _triviaConvertingVisitor ) ) ;
7299 }
73100
74101 private async Task < ExpressionSyntax > ConvertMyGroupCollectionPropertyGetWithUnderlyingFieldAsync ( SyntaxNode node )
@@ -104,9 +131,9 @@ private async Task<ExpressionSyntax> ConvertToPowOperatorAsync(VBSyntax.BinaryEx
104131 . Invoke ( _visualBasicEqualityComparison . ExtraUsingDirectives , lhs , rhs ) ;
105132 }
106133
107- private ExpressionSyntax ConvertTo ( VBSyntax . ExpressionSyntax node , ExpressionSyntax lhs , SpecialType targetType )
134+ private ExpressionSyntax ConvertTo ( VBSyntax . ExpressionSyntax vbNode , ExpressionSyntax csNode , SpecialType targetType )
108135 {
109- return _typeConversionAnalyzer . AddExplicitConversion ( node , lhs , forceTargetType : _semanticModel . Compilation . GetSpecialType ( targetType ) ) ;
136+ return _typeConversionAnalyzer . AddExplicitConversion ( vbNode , csNode , forceTargetType : _semanticModel . Compilation . GetSpecialType ( targetType ) ) ;
110137 }
111138
112139 /// <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>
@@ -173,7 +200,8 @@ public async Task<ExpressionSyntax> ConvertRewrittenBinaryOperatorOrNullAsync(VB
173200 switch ( opKind ) {
174201 case BinaryOperatorKind . IsExpression :
175202 case BinaryOperatorKind . IsNotExpression : {
176- if ( await ConvertNothingComparisonOrNullAsync ( node ) is CSharpSyntaxNode nothingComparison ) return ( ExpressionSyntax ) nothingComparison ;
203+ if ( await ConvertReferenceOrNothingComparisonOrNullAsync ( node ) is { } nothingComparison ) return nothingComparison ;
204+
177205 break ;
178206 }
179207
0 commit comments