Skip to content

Commit 5daa8b9

Browse files
committed
C#: Add compound assignment operator QL classes.
1 parent eca0fed commit 5daa8b9

2 files changed

Lines changed: 255 additions & 4 deletions

File tree

csharp/ql/lib/semmle/code/csharp/Callable.qll

Lines changed: 254 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -611,7 +611,8 @@ class ExtensionOperator extends ExtensionCallableImpl, Operator {
611611
class UnaryOperator extends Operator {
612612
UnaryOperator() {
613613
this.getNumberOfParameters() = 1 and
614-
not this instanceof ConversionOperator
614+
not this instanceof ConversionOperator and
615+
not this instanceof CompoundAssignmentOperator
615616
}
616617
}
617618

@@ -784,7 +785,7 @@ class TrueOperator extends UnaryOperator {
784785
* A user-defined binary operator.
785786
*
786787
* Either an addition operator (`AddOperator`), a checked addition operator
787-
* (`CheckedAddOperator`) a subtraction operator (`SubOperator`), a checked
788+
* (`CheckedAddOperator`), a subtraction operator (`SubOperator`), a checked
788789
* subtraction operator (`CheckedSubOperator`), a multiplication operator
789790
* (`MulOperator`), a checked multiplication operator (`CheckedMulOperator`),
790791
* a division operator (`DivOperator`), a checked division operator
@@ -795,10 +796,16 @@ class TrueOperator extends UnaryOperator {
795796
* operator(`UnsignedRightShiftOperator`), an equals operator (`EQOperator`),
796797
* a not equals operator (`NEOperator`), a lesser than operator (`LTOperator`),
797798
* a greater than operator (`GTOperator`), a less than or equals operator
798-
* (`LEOperator`), or a greater than or equals operator (`GEOperator`).
799+
* (`LEOperator`), a greater than or equals operator (`GEOperator`), or
800+
* a compound assignment operator (`CompoundAssignmentOperator`).
799801
*/
800802
class BinaryOperator extends Operator {
801-
BinaryOperator() { this.getNumberOfParameters() = 2 }
803+
BinaryOperator() {
804+
this.getNumberOfParameters() = 2
805+
or
806+
// Instance compound assignment operators only have one parameter.
807+
this.getNumberOfParameters() = 1 and not this.isStatic()
808+
}
802809
}
803810

804811
/**
@@ -1184,6 +1191,249 @@ class CheckedExplicitConversionOperator extends ConversionOperator {
11841191
override string getAPrimaryQlClass() { result = "CheckedExplicitConversionOperator" }
11851192
}
11861193

1194+
abstract private class CompoundAssignmentOperatorImpl extends BinaryOperator { }
1195+
1196+
/**
1197+
* A user-defined compound assignment operator.
1198+
*
1199+
* Either an addition operator (`AddCompoundAssignmentOperator`), a checked addition operator
1200+
* (`CheckedAddCompoundAssignmentOperator`), a subtraction operator (`SubCompoundAssignmentOperator`), a checked
1201+
* subtraction operator (`CheckedSubCompoundAssignmentOperator`), a multiplication operator
1202+
* (`MulCompoundAssignmentOperator`), a checked multiplication operator (`CheckedMulCompoundAssignmentOperator`),
1203+
* a division operator (`DivCompoundAssignmentOperator`), a checked division operator
1204+
* (`CheckedDivCompoundAssignmentOperator`), a remainder operator (`RemCompoundAssignmentOperator`), an and
1205+
* operator (`AndCompoundAssignmentOperator`), an or operator (`OrCompoundAssignmentOperator`), an xor
1206+
* operator (`XorCompoundAssignmentOperator`), a left shift operator (`LeftShiftCompoundAssignmentOperator`),
1207+
* a right shift operator (`RightShiftCompoundAssignmentOperator`), or an unsigned right shift
1208+
* operator(`UnsignedRightShiftCompoundAssignmentOperator`).
1209+
*/
1210+
final class CompoundAssignmentOperator = CompoundAssignmentOperatorImpl;
1211+
1212+
/**
1213+
* A user-defined compound assignment addition operator (`+=`), for example
1214+
*
1215+
* ```csharp
1216+
* public void operator checked +=(Widget w) {
1217+
* ...
1218+
* }
1219+
* ```
1220+
*/
1221+
class AddCompoundAssignmentOperator extends CompoundAssignmentOperatorImpl {
1222+
AddCompoundAssignmentOperator() { this.getName() = "+=" }
1223+
1224+
override string getAPrimaryQlClass() { result = "AddCompoundAssignmentOperator" }
1225+
}
1226+
1227+
/**
1228+
* A user-defined checked compound assignment addition operator (`checked +=`), for example
1229+
*
1230+
* ```csharp
1231+
* public void operator checked +=(Widget w) {
1232+
* ...
1233+
* }
1234+
* ```
1235+
*/
1236+
class CheckedAddCompoundAssignmentOperator extends CompoundAssignmentOperatorImpl {
1237+
CheckedAddCompoundAssignmentOperator() { this.getName() = "checked +=" }
1238+
1239+
override string getAPrimaryQlClass() { result = "CheckedAddCompoundAssignmentOperator" }
1240+
}
1241+
1242+
/**
1243+
* A user-defined compound assignment subtraction operator (`-=`), for example
1244+
*
1245+
* ```csharp
1246+
* public void operator -=(Widget w) {
1247+
* ...
1248+
* }
1249+
* ```
1250+
*/
1251+
class SubCompoundAssignmentOperator extends CompoundAssignmentOperatorImpl {
1252+
SubCompoundAssignmentOperator() { this.getName() = "-=" }
1253+
1254+
override string getAPrimaryQlClass() { result = "SubCompoundAssignmentOperator" }
1255+
}
1256+
1257+
/**
1258+
* A user-defined checked compound assignment subtraction operator (`checked -=`), for example
1259+
*
1260+
* ```csharp
1261+
* public void operator checked -=(Widget w) {
1262+
* ...
1263+
* }
1264+
* ```
1265+
*/
1266+
class CheckedSubCompoundAssignmentOperator extends CompoundAssignmentOperatorImpl {
1267+
CheckedSubCompoundAssignmentOperator() { this.getName() = "checked -=" }
1268+
1269+
override string getAPrimaryQlClass() { result = "CheckedSubCompoundAssignmentOperator" }
1270+
}
1271+
1272+
/**
1273+
* A user-defined compound assignment multiplication operator (`*=`), for example
1274+
*
1275+
* ```csharp
1276+
* public void operator *=(Widget w) {
1277+
* ...
1278+
* }
1279+
* ```
1280+
*/
1281+
class MulCompoundAssignmentOperator extends CompoundAssignmentOperatorImpl {
1282+
MulCompoundAssignmentOperator() { this.getName() = "*=" }
1283+
1284+
override string getAPrimaryQlClass() { result = "MulCompoundAssignmentOperator" }
1285+
}
1286+
1287+
/**
1288+
* A user-defined checked compound assignment multiplication operator (`checked *=`), for example
1289+
*
1290+
* ```csharp
1291+
* public void operator checked *=(Widget w) {
1292+
* ...
1293+
* }
1294+
* ```
1295+
*/
1296+
class CheckedMulCompoundAssignmentOperator extends CompoundAssignmentOperatorImpl {
1297+
CheckedMulCompoundAssignmentOperator() { this.getName() = "checked *=" }
1298+
1299+
override string getAPrimaryQlClass() { result = "CheckedMulCompoundAssignmentOperator" }
1300+
}
1301+
1302+
/**
1303+
* A user-defined compound assignment division operator (`/=`), for example
1304+
*
1305+
* ```csharp
1306+
* public void operator /=(Widget w) {
1307+
* ...
1308+
* }
1309+
* ```
1310+
*/
1311+
class DivCompoundAssignmentOperator extends CompoundAssignmentOperatorImpl {
1312+
DivCompoundAssignmentOperator() { this.getName() = "/=" }
1313+
1314+
override string getAPrimaryQlClass() { result = "DivCompoundAssignmentOperator" }
1315+
}
1316+
1317+
/**
1318+
* A user-defined checked compound assignment division operator (`checked /=`), for example
1319+
*
1320+
* ```csharp
1321+
* public void operator checked /=(Widget w) {
1322+
* ...
1323+
* }
1324+
* ```
1325+
*/
1326+
class CheckedDivCompoundAssignmentOperator extends CompoundAssignmentOperatorImpl {
1327+
CheckedDivCompoundAssignmentOperator() { this.getName() = "checked /=" }
1328+
1329+
override string getAPrimaryQlClass() { result = "CheckedDivCompoundAssignmentOperator" }
1330+
}
1331+
1332+
/**
1333+
* A user-defined compound assignment remainder operator (`%=`), for example
1334+
*
1335+
* ```csharp
1336+
* public void operator %=(Widget w) {
1337+
* ...
1338+
* }
1339+
* ```
1340+
*/
1341+
class RemCompoundAssignmentOperator extends CompoundAssignmentOperatorImpl {
1342+
RemCompoundAssignmentOperator() { this.getName() = "%=" }
1343+
1344+
override string getAPrimaryQlClass() { result = "RemCompoundAssignmentOperator" }
1345+
}
1346+
1347+
/**
1348+
* A user-defined compound assignment and operator (`&=`), for example
1349+
*
1350+
* ```csharp
1351+
* public void operator &=(Widget w) {
1352+
* ...
1353+
* }
1354+
* ```
1355+
*/
1356+
class AndCompoundAssignmentOperator extends CompoundAssignmentOperatorImpl {
1357+
AndCompoundAssignmentOperator() { this.getName() = "&=" }
1358+
1359+
override string getAPrimaryQlClass() { result = "AndCompoundAssignmentOperator" }
1360+
}
1361+
1362+
/**
1363+
* A user-defined compound assignment or operator (`|=`), for example
1364+
*
1365+
* ```csharp
1366+
* public void operator |=(Widget w) {
1367+
* ...
1368+
* }
1369+
* ```
1370+
*/
1371+
class OrCompoundAssignmentOperator extends CompoundAssignmentOperatorImpl {
1372+
OrCompoundAssignmentOperator() { this.getName() = "|=" }
1373+
1374+
override string getAPrimaryQlClass() { result = "OrCompoundAssignmentOperator" }
1375+
}
1376+
1377+
/**
1378+
* A user-defined compound assignment xor operator (`^=`), for example
1379+
*
1380+
* ```csharp
1381+
* public void operator ^=(Widget w) {
1382+
* ...
1383+
* }
1384+
* ```
1385+
*/
1386+
class XorCompoundAssignmentOperator extends CompoundAssignmentOperatorImpl {
1387+
XorCompoundAssignmentOperator() { this.getName() = "^=" }
1388+
1389+
override string getAPrimaryQlClass() { result = "XorCompoundAssignmentOperator" }
1390+
}
1391+
1392+
/**
1393+
* A user-defined compound assignment left shift operator (`<<=`), for example
1394+
*
1395+
* ```csharp
1396+
* public void operator <<=(Widget w) {
1397+
* ...
1398+
* }
1399+
* ```
1400+
*/
1401+
class LeftShiftCompoundAssignmentOperator extends CompoundAssignmentOperatorImpl {
1402+
LeftShiftCompoundAssignmentOperator() { this.getName() = "<<=" }
1403+
1404+
override string getAPrimaryQlClass() { result = "LeftShiftCompoundAssignmentOperator" }
1405+
}
1406+
1407+
/**
1408+
* A user-defined compound assignment right shift operator (`>>=`), for example
1409+
*
1410+
* ```csharp
1411+
* public void operator >>=(Widget w) {
1412+
* ...
1413+
* }
1414+
* ```
1415+
*/
1416+
class RightShiftCompoundAssignmentOperator extends CompoundAssignmentOperatorImpl {
1417+
RightShiftCompoundAssignmentOperator() { this.getName() = ">>=" }
1418+
1419+
override string getAPrimaryQlClass() { result = "RightShiftCompoundAssignmentOperator" }
1420+
}
1421+
1422+
/**
1423+
* A user-defined compound assignment unsigned right shift operator (`>>>=`), for example
1424+
*
1425+
* ```csharp
1426+
* public void operator >>>=(Widget w) {
1427+
* ...
1428+
* }
1429+
* ```
1430+
*/
1431+
class UnsignedRightShiftCompoundAssignmentOperator extends CompoundAssignmentOperatorImpl {
1432+
UnsignedRightShiftCompoundAssignmentOperator() { this.getName() = ">>>=" }
1433+
1434+
override string getAPrimaryQlClass() { result = "UnsignedRightShiftCompoundAssignmentOperator" }
1435+
}
1436+
11871437
/**
11881438
* A local function, defined within the scope of another callable.
11891439
* For example, `Fac` on lines 2--4 in

csharp/ql/lib/semmle/code/csharp/Type.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1334,6 +1334,7 @@ class TypeMention extends @type_mention {
13341334
* ```csharp
13351335
* static class MyExtensions {
13361336
* extension(string s) { ... }
1337+
* }
13371338
* ```
13381339
*/
13391340
class ExtensionType extends Parameterizable, @extension_type {

0 commit comments

Comments
 (0)