File tree Expand file tree Collapse file tree 3 files changed +64
-2
lines changed
Expand file tree Collapse file tree 3 files changed +64
-2
lines changed Original file line number Diff line number Diff line change 1+ using Microsoft . CodeAnalysis ;
2+
3+ namespace Semmle . Extraction . CSharp . Entities . Expressions
4+ {
5+ internal static class CompoundAssignment
6+ {
7+ public static Expression Create ( ExpressionNodeInfo info )
8+ {
9+ if ( info . SymbolInfo . Symbol is IMethodSymbol op &&
10+ op . MethodKind == MethodKind . UserDefinedOperator &&
11+ ! op . IsStatic )
12+ {
13+ // This is a user-defined instance operator such as `a += b` where `a` is of a type that defines an `operator +=`.
14+ // In this case, we want to extract the operator call rather than desugar it into `a = a + b`.
15+ return UserCompoundAssignmentInvocation . Create ( info ) ;
16+ }
17+ return Assignment . Create ( info ) ;
18+ }
19+ }
20+ }
Original file line number Diff line number Diff line change @@ -70,6 +70,9 @@ internal static Expression Create(ExpressionNodeInfo info)
7070 return NormalElementAccess . Create ( info ) ;
7171
7272 case SyntaxKind . SimpleAssignmentExpression :
73+ case SyntaxKind . CoalesceAssignmentExpression :
74+ return Assignment . Create ( info ) ;
75+
7376 case SyntaxKind . OrAssignmentExpression :
7477 case SyntaxKind . AndAssignmentExpression :
7578 case SyntaxKind . SubtractAssignmentExpression :
@@ -81,8 +84,7 @@ internal static Expression Create(ExpressionNodeInfo info)
8184 case SyntaxKind . UnsignedRightShiftAssignmentExpression :
8285 case SyntaxKind . DivideAssignmentExpression :
8386 case SyntaxKind . ModuloAssignmentExpression :
84- case SyntaxKind . CoalesceAssignmentExpression :
85- return Assignment . Create ( info ) ;
87+ return CompoundAssignment . Create ( info ) ;
8688
8789 case SyntaxKind . ObjectCreationExpression :
8890 return ExplicitObjectCreation . Create ( info ) ;
Original file line number Diff line number Diff line change 1+ using System . IO ;
2+ using Microsoft . CodeAnalysis . CSharp . Syntax ;
3+ using Semmle . Extraction . Kinds ;
4+
5+ namespace Semmle . Extraction . CSharp . Entities . Expressions
6+ {
7+ /// <summary>
8+ /// Represents a user-defined compound assignment operator such as `a += b` where `a` is of a type that defines an `operator +=`.
9+ /// In this case, we don't want to desugar it into `a = a + b`, but instead extract the operator call directly as it should
10+ /// be considered an instance method call on `a` with `b` as an argument.
11+ /// </summary>
12+ internal class UserCompoundAssignmentInvocation : Expression < AssignmentExpressionSyntax >
13+ {
14+ private readonly ExpressionNodeInfo info ;
15+
16+ protected UserCompoundAssignmentInvocation ( ExpressionNodeInfo info )
17+ : base ( info . SetKind ( ExprKind . OPERATOR_INVOCATION ) )
18+ {
19+ this . info = info ;
20+ }
21+
22+ public static Expression Create ( ExpressionNodeInfo info ) => new UserCompoundAssignmentInvocation ( info ) . TryPopulate ( ) ;
23+
24+ protected override void PopulateExpression ( TextWriter trapFile )
25+ {
26+ Create ( Context , Syntax . Left , this , 0 ) ;
27+ Create ( Context , Syntax . Right , this , 1 ) ;
28+
29+ var target = info . GetTargetSymbol ( Context ) ;
30+ if ( target is null )
31+ {
32+ Context . ModelError ( Syntax , "Unable to resolve target method for user-defined compound assignment operator" ) ;
33+ return ;
34+ }
35+
36+ var targetKey = Method . Create ( Context , target ) ;
37+ trapFile . expr_call ( this , targetKey ) ;
38+ }
39+ }
40+ }
You can’t perform that action at this time.
0 commit comments