@@ -211,9 +211,22 @@ public override async Task<SyntaxList<StatementSyntax>> VisitAssignmentStatement
211211 var lhs = await node . Left . AcceptAsync < ExpressionSyntax > ( _expressionVisitor ) ;
212212 var lOperation = _semanticModel . GetOperation ( node . Left ) ;
213213
214- //Already dealt with by call to the same method in ConvertInvocationExpression
215214 var ( parameterizedPropertyAccessMethod , _) = await CommonConversions . GetParameterizedPropertyAccessMethodAsync ( lOperation ) ;
216- if ( parameterizedPropertyAccessMethod != null ) return SingleStatement ( lhs ) ;
215+
216+ // If it's a simple assignment, we can return early as it's already handled by ConvertInvocationExpression
217+ if ( parameterizedPropertyAccessMethod != null && node . IsKind ( VBasic . SyntaxKind . SimpleAssignmentStatement ) ) {
218+ return SingleStatement ( lhs ) ;
219+ }
220+
221+ // For compound assignments, we want to expand it to the setter, but parameterizedPropertyAccessMethod above
222+ // returned 'get_Item' or 'set_Item' depending on operation context.
223+ // We know for sure the left-hand side is a getter invocation for compound assignments (e.g. this.get_Item(0) += 2),
224+ // but we need the setter name to build the final expression.
225+ string setMethodName = null ;
226+ if ( lOperation is IPropertyReferenceOperation pro && pro . Arguments . Any ( ) && ! Microsoft . CodeAnalysis . VisualBasic . VisualBasicExtensions . IsDefault ( pro . Property ) ) {
227+ setMethodName = pro . Property . SetMethod ? . Name ;
228+ }
229+
217230 var rhs = await node . Right . AcceptAsync < ExpressionSyntax > ( _expressionVisitor ) ;
218231
219232 if ( node . Left is VBSyntax . IdentifierNameSyntax id &&
@@ -241,18 +254,62 @@ _methodNode is VBSyntax.MethodBlockSyntax mb &&
241254
242255 var nonCompoundRhs = SyntaxFactory . BinaryExpression ( nonCompound , lhs , typeConvertedRhs ) ;
243256 var typeConvertedNonCompoundRhs = CommonConversions . TypeConversionAnalyzer . AddExplicitConversion ( node . Right , nonCompoundRhs , forceSourceType : rhsTypeInfo . ConvertedType , forceTargetType : lhsTypeInfo . Type ) ;
244- if ( nonCompoundRhs != typeConvertedNonCompoundRhs ) {
257+ if ( nonCompoundRhs != typeConvertedNonCompoundRhs || setMethodName != null ) {
245258 kind = SyntaxKind . SimpleAssignmentExpression ;
246259 typeConvertedRhs = typeConvertedNonCompoundRhs ;
247260 }
261+ } else if ( setMethodName != null && node . IsKind ( VBasic . SyntaxKind . ExponentiateAssignmentStatement ) ) {
262+ // ExponentiateAssignmentStatement evaluates to Math.Pow invocation which might need casting back to lhsType
263+ var typeConvertedNonCompoundRhs = CommonConversions . TypeConversionAnalyzer . AddExplicitConversion ( node . Right , typeConvertedRhs , forceSourceType : _semanticModel . Compilation . GetTypeByMetadataName ( "System.Double" ) , forceTargetType : lhsTypeInfo . Type ) ;
264+ kind = SyntaxKind . SimpleAssignmentExpression ;
265+ typeConvertedRhs = typeConvertedNonCompoundRhs ;
248266 }
249267
250268 rhs = typeConvertedRhs ;
251-
252- var assignment = SyntaxFactory . AssignmentExpression ( kind , lhs , rhs ) ;
253269
254- var postAssignment = GetPostAssignmentStatements ( node ) ;
255- return postAssignment . Insert ( 0 , SyntaxFactory . ExpressionStatement ( assignment ) ) ;
270+ if ( setMethodName != null ) {
271+ if ( lhs is InvocationExpressionSyntax ies ) {
272+ ExpressionSyntax exprToReplace = ies . Expression ;
273+ if ( exprToReplace is MemberAccessExpressionSyntax maes && maes . Name is IdentifierNameSyntax idn ) {
274+ var newName = SyntaxFactory . IdentifierName ( setMethodName ) . WithTriviaFrom ( idn ) ;
275+ exprToReplace = maes . WithName ( newName ) ;
276+
277+ var skipParens = node . Left . SkipIntoParens ( ) ;
278+ if ( maes . Expression is ThisExpressionSyntax ) {
279+ if ( skipParens is VBSyntax . InvocationExpressionSyntax inv && inv . Expression is VBSyntax . IdentifierNameSyntax ) {
280+ exprToReplace = newName . WithLeadingTrivia ( maes . GetLeadingTrivia ( ) ) . WithTrailingTrivia ( maes . GetTrailingTrivia ( ) ) ;
281+ } else if ( skipParens is VBSyntax . IdentifierNameSyntax ) {
282+ exprToReplace = newName . WithLeadingTrivia ( maes . GetLeadingTrivia ( ) ) . WithTrailingTrivia ( maes . GetTrailingTrivia ( ) ) ;
283+ } else if ( skipParens is VBSyntax . MemberAccessExpressionSyntax vbMaes && vbMaes . Expression is VBSyntax . MyClassExpressionSyntax == false && vbMaes . Expression is VBSyntax . MeExpressionSyntax == false ) {
284+ // keep it
285+ } else {
286+ exprToReplace = newName . WithLeadingTrivia ( maes . GetLeadingTrivia ( ) ) . WithTrailingTrivia ( maes . GetTrailingTrivia ( ) ) ;
287+ }
288+ }
289+ } else if ( exprToReplace is IdentifierNameSyntax idn2 ) {
290+ var newName = SyntaxFactory . IdentifierName ( setMethodName ) . WithTriviaFrom ( idn2 ) ;
291+ exprToReplace = newName ;
292+ }
293+ var newArg = SyntaxFactory . Argument ( rhs ) ;
294+ var newArgs = ies . ArgumentList . Arguments . Add ( newArg ) ;
295+ var newArgList = ies . ArgumentList . WithArguments ( newArgs ) ;
296+ var newLhs = ies . WithExpression ( exprToReplace ) . WithArgumentList ( newArgList ) ;
297+ var invokeAssignment = SyntaxFactory . ExpressionStatement ( newLhs ) ;
298+ var postAssign = GetPostAssignmentStatements ( node ) ;
299+ return postAssign . Insert ( 0 , invokeAssignment ) ;
300+ }
301+ return SingleStatement ( lhs ) ;
302+ }
303+
304+ if ( kind == SyntaxKind . SimpleAssignmentExpression ) {
305+ var assignment = SyntaxFactory . AssignmentExpression ( kind , lhs , rhs ) ;
306+ var postAssignment = GetPostAssignmentStatements ( node ) ;
307+ return postAssignment . Insert ( 0 , SyntaxFactory . ExpressionStatement ( assignment ) ) ;
308+ }
309+
310+ var compoundAssignment = SyntaxFactory . AssignmentExpression ( kind , lhs , rhs ) ;
311+ var compoundPostAssignment = GetPostAssignmentStatements ( node ) ;
312+ return compoundPostAssignment . Insert ( 0 , SyntaxFactory . ExpressionStatement ( compoundAssignment ) ) ;
256313 }
257314
258315 private async Task < SyntaxList < StatementSyntax > > ConvertMidAssignmentAsync ( VBSyntax . AssignmentStatementSyntax node , VBSyntax . MidExpressionSyntax mes )
0 commit comments