C# 14: User defined compound assignment operators.#21372
C# 14: User defined compound assignment operators.#21372michaelnebel wants to merge 10 commits intogithub:mainfrom
Conversation
07345fe to
a9a8936
Compare
76f65d5 to
fafe360
Compare
|
DCA looks good
|
There was a problem hiding this comment.
Pull request overview
This PR adds C# 14 support for user-defined compound assignment operators (for example a += b where operator += is declared) by extracting them as operator invocations rather than desugaring them into a = a + b, and updates QL dispatch/dataflow plus tests accordingly.
Changes:
- Add new extractor handling for compound assignment expressions to emit direct operator-call extraction for user-defined (instance) compound assignment operators.
- Extend the C# QL library to represent and dispatch
CompoundAssignmentOperatorCalldistinctly from ordinaryOperatorCall. - Update/extend AST and dataflow library tests and expected outputs for compound assignment operator declarations and invocations (including extension-based operators).
Reviewed changes
Copilot reviewed 19 out of 20 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| csharp/ql/test/library-tests/operators/operators.cs | Adds user-defined compound assignment operator declarations and invocations for AST coverage. |
| csharp/ql/test/library-tests/operators/PrintAst.expected | Updates AST expectations to include compound assignment operators/calls. |
| csharp/ql/test/library-tests/operators/Operators1.expected | Updates operator location expectations after AST shifts. |
| csharp/ql/test/library-tests/operators/Operators2.expected | Updates operator location expectations after AST shifts. |
| csharp/ql/test/library-tests/operators/Operators3.expected | Updates conversion-operator location expectations after AST shifts. |
| csharp/ql/test/library-tests/operators/Operators4.expected | Updates conversion-operator location expectations after AST shifts. |
| csharp/ql/test/library-tests/dataflow/operators/Operator.cs | Adds a dataflow test for user-defined compound assignment operator calls. |
| csharp/ql/test/library-tests/dataflow/operators/operatorFlow.expected | Updates expected dataflow graph to reflect compound assignment operator modeling. |
| csharp/ql/test/library-tests/dataflow/extensions/extensions.cs | Adds an extension-based compound assignment operator and a flow test covering it. |
| csharp/ql/test/library-tests/dataflow/extensions/ExtensionFlow.expected | Updates expected dataflow output for the new extension compound assignment test. |
| csharp/ql/lib/semmle/code/csharp/exprs/Call.qll | Introduces CompoundAssignmentOperatorCall in the QL expression hierarchy. |
| csharp/ql/lib/semmle/code/csharp/dispatch/Dispatch.qll | Adjusts dispatch to treat compound assignment operator calls as dispatchable calls with a qualifier. |
| csharp/ql/lib/semmle/code/csharp/Callable.qll | Adds QL operator classes for compound assignment operator declarations. |
| csharp/ql/lib/change-notes/2026-03-06-compound-assignment-operations.md | Adds changelog entry for the new C# 14 support. |
| csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/UserCompoundAssignmentInvocation.cs | New extractor expression node for user-defined compound assignment operator invocations. |
| csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Invocation.cs | Refactors call target resolution to use a shared helper. |
| csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Factory.cs | Routes compound assignment syntax kinds through new compound-assignment extraction logic. |
| csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/CompoundAssignment.cs | New helper to decide between desugaring vs direct operator-call extraction for compound assignments. |
| csharp/extractor/Semmle.Extraction.CSharp/CodeAnalysisExtensions/SymbolExtensions.cs | Adds ExpressionNodeInfo.GetTargetSymbol helper for consistent target resolution. |
| csharp/extractor/Semmle.Extraction.CSharp.Util/SymbolExtensions.cs | Extends operator-symbol parsing to recognize checked and assignment operator method names. |
You can also share your feedback on Copilot code review. Take the survey.
hvitved
left a comment
There was a problem hiding this comment.
LGTM, some trivial comments.
| return symbol.CanBeReferencedByName ? name : name.Substring(symbol.Name.LastIndexOf('.') + 1); | ||
| } | ||
|
|
||
| private static readonly Dictionary<string, string> methodToOperator = new Dictionary<string, string> |
There was a problem hiding this comment.
Nit: Can be a ReadOnlyDictionary.
| * A user-defined compound assignment operator. | ||
| * | ||
| * Either an addition operator (`AddCompoundAssignmentOperator`), a checked addition operator | ||
| * (`CheckedAddCompoundAssignmentOperator`) a subtraction operator (`SubCompoundAssignmentOperator`), a checked |
|
|
||
| override Expr getArgument(int i) { | ||
| exists(int j | result = this.getChildExpr(j) | | ||
| if this.isOrdinaryStaticCall() then (j = i and j >= 0) else (j = i - 1 and j >= -1) |
There was a problem hiding this comment.
Alternatively i >=0 and if this.isOrdinaryStaticCall() then j = i else j = i - 1
|
Putting this back in Draft as there has been significant changes in main (removal of expanded assignments). |
4018db1 to
e3caea6
Compare
…ht operator symbol (operators can also be declared in extensions).
…s can be considered qualifiable expressions.
…ssignable definition).
e3caea6 to
f3f3ee6
Compare
In this PR we introduce support for user-defined compound assignment operators.
Compound assignment operator calls are not implicit assignments, but instead the left hand side of the compound assignment is updated. That is, user-defined compound operator calls behave more like instance method calls than static operator calls.
Had we instead declared
then
a1 += a2is also valid, but instead it meansa1 + a2and assign the result toa1.Notes on the implementation