@@ -1214,81 +1214,6 @@ module ClassNode {
1214
1214
DataFlow:: Node getADecorator ( ) { none ( ) }
1215
1215
}
1216
1216
1217
- /**
1218
- * An ES6 class as a `ClassNode` instance.
1219
- */
1220
- private class ES6Class extends Range , DataFlow:: ValueNode {
1221
- override ClassDefinition astNode ;
1222
-
1223
- override string getName ( ) { result = astNode .getName ( ) }
1224
-
1225
- override string describe ( ) { result = astNode .describe ( ) }
1226
-
1227
- override FunctionNode getConstructor ( ) { result = astNode .getConstructor ( ) .getBody ( ) .flow ( ) }
1228
-
1229
- override FunctionNode getInstanceMember ( string name , MemberKind kind ) {
1230
- exists ( MethodDeclaration method |
1231
- method = astNode .getMethod ( name ) and
1232
- not method .isStatic ( ) and
1233
- kind = MemberKind:: of ( method ) and
1234
- result = method .getBody ( ) .flow ( )
1235
- )
1236
- or
1237
- kind = MemberKind:: method ( ) and
1238
- result = this .getConstructor ( ) .getReceiver ( ) .getAPropertySource ( name )
1239
- }
1240
-
1241
- override FunctionNode getAnInstanceMember ( MemberKind kind ) {
1242
- exists ( MethodDeclaration method |
1243
- method = astNode .getAMethod ( ) and
1244
- not method .isStatic ( ) and
1245
- kind = MemberKind:: of ( method ) and
1246
- result = method .getBody ( ) .flow ( )
1247
- )
1248
- or
1249
- kind = MemberKind:: method ( ) and
1250
- result = this .getConstructor ( ) .getReceiver ( ) .getAPropertySource ( )
1251
- }
1252
-
1253
- override FunctionNode getStaticMember ( string name , MemberKind kind ) {
1254
- exists ( MethodDeclaration method |
1255
- method = astNode .getMethod ( name ) and
1256
- method .isStatic ( ) and
1257
- kind = MemberKind:: of ( method ) and
1258
- result = method .getBody ( ) .flow ( )
1259
- )
1260
- or
1261
- kind .isMethod ( ) and
1262
- result = this .getAPropertySource ( name )
1263
- }
1264
-
1265
- override FunctionNode getAStaticMember ( MemberKind kind ) {
1266
- exists ( MethodDeclaration method |
1267
- method = astNode .getAMethod ( ) and
1268
- method .isStatic ( ) and
1269
- kind = MemberKind:: of ( method ) and
1270
- result = method .getBody ( ) .flow ( )
1271
- )
1272
- or
1273
- kind .isMethod ( ) and
1274
- result = this .getAPropertySource ( )
1275
- }
1276
-
1277
- override DataFlow:: Node getASuperClassNode ( ) { result = astNode .getSuperClass ( ) .flow ( ) }
1278
-
1279
- override TypeAnnotation getFieldTypeAnnotation ( string fieldName ) {
1280
- exists ( FieldDeclaration field |
1281
- field .getDeclaringClass ( ) = astNode and
1282
- fieldName = field .getName ( ) and
1283
- result = field .getTypeAnnotation ( )
1284
- )
1285
- }
1286
-
1287
- override DataFlow:: Node getADecorator ( ) {
1288
- result = astNode .getADecorator ( ) .getExpression ( ) .flow ( )
1289
- }
1290
- }
1291
-
1292
1217
private DataFlow:: PropRef getAPrototypeReferenceInFile ( string name , File f ) {
1293
1218
result .getBase ( ) = AccessPath:: getAReferenceOrAssignmentTo ( name ) and
1294
1219
result .getPropertyName ( ) = "prototype" and
@@ -1313,12 +1238,18 @@ module ClassNode {
1313
1238
1314
1239
/**
1315
1240
* A function definition, targeted by a `new`-call or with prototype manipulation, seen as a `ClassNode` instance.
1241
+ * Or An ES6 class as a `ClassNode` instance.
1316
1242
*/
1317
1243
class FunctionStyleClass extends Range , DataFlow:: ValueNode {
1318
- override Function astNode ;
1244
+ override AST :: ValueNode astNode ;
1319
1245
AbstractFunction function ;
1320
1246
1321
1247
FunctionStyleClass ( ) {
1248
+ // ES6 class case
1249
+ astNode instanceof ClassDefinition
1250
+ or
1251
+ // Function-style class case
1252
+ astNode instanceof Function and
1322
1253
function .getFunction ( ) = astNode and
1323
1254
(
1324
1255
exists ( getAFunctionValueWithPrototype ( function ) )
@@ -1333,13 +1264,30 @@ module ClassNode {
1333
1264
)
1334
1265
}
1335
1266
1336
- override string getName ( ) { result = astNode .getName ( ) }
1267
+ override string getName ( ) {
1268
+ astNode instanceof ClassDefinition and result = astNode .( ClassDefinition ) .getName ( )
1269
+ or
1270
+ astNode instanceof Function and result = astNode .( Function ) .getName ( )
1271
+ }
1337
1272
1338
- override string describe ( ) { result = astNode .describe ( ) }
1273
+ override string describe ( ) {
1274
+ astNode instanceof ClassDefinition and result = astNode .( ClassDefinition ) .describe ( )
1275
+ or
1276
+ astNode instanceof Function and result = astNode .( Function ) .describe ( )
1277
+ }
1339
1278
1340
- override FunctionNode getConstructor ( ) { result = this }
1279
+ override FunctionNode getConstructor ( ) {
1280
+ // For ES6 classes
1281
+ astNode instanceof ClassDefinition and
1282
+ result = astNode .( ClassDefinition ) .getConstructor ( ) .getBody ( ) .flow ( )
1283
+ or
1284
+ // For function-style classes
1285
+ astNode instanceof Function and result = this
1286
+ }
1341
1287
1342
1288
private PropertyAccessor getAnAccessor ( MemberKind kind ) {
1289
+ // Only applies to function-style classes
1290
+ astNode instanceof Function and
1343
1291
result .getObjectExpr ( ) = this .getAPrototypeReference ( ) .asExpr ( ) and
1344
1292
(
1345
1293
kind = MemberKind:: getter ( ) and
@@ -1351,12 +1299,41 @@ module ClassNode {
1351
1299
}
1352
1300
1353
1301
override FunctionNode getInstanceMember ( string name , MemberKind kind ) {
1302
+ // ES6 class methods
1303
+ exists ( MethodDeclaration method |
1304
+ astNode instanceof ClassDefinition and
1305
+ method = astNode .( ClassDefinition ) .getMethod ( name ) and
1306
+ not method .isStatic ( ) and
1307
+ kind = MemberKind:: of ( method ) and
1308
+ result = method .getBody ( ) .flow ( )
1309
+ )
1310
+ or
1311
+ // ES6 class property in constructor
1312
+ astNode instanceof ClassDefinition and
1354
1313
kind = MemberKind:: method ( ) and
1355
- result = this .getAPrototypeReference ( ) .getAPropertySource ( name )
1314
+ exists ( ThisNode receiver |
1315
+ receiver = this .getConstructor ( ) .getReceiver ( ) and
1316
+ receiver .hasPropertyWrite ( name , result )
1317
+ )
1318
+ or
1319
+ // Function-style class methods via prototype
1320
+ astNode instanceof Function and
1321
+ kind = MemberKind:: method ( ) and
1322
+ exists ( DataFlow:: SourceNode proto |
1323
+ proto = this .getAPrototypeReference ( ) and
1324
+ proto .hasPropertyWrite ( name , result )
1325
+ )
1356
1326
or
1327
+ // Function-style class methods via constructor
1328
+ astNode instanceof Function and
1357
1329
kind = MemberKind:: method ( ) and
1358
- result = this .getConstructor ( ) .getReceiver ( ) .getAPropertySource ( name )
1330
+ exists ( ThisNode receiver |
1331
+ receiver = this .getConstructor ( ) .getReceiver ( ) and
1332
+ receiver .hasPropertyWrite ( name , result )
1333
+ )
1359
1334
or
1335
+ // Function-style class accessors
1336
+ astNode instanceof Function and
1360
1337
exists ( PropertyAccessor accessor |
1361
1338
accessor = this .getAnAccessor ( kind ) and
1362
1339
accessor .getName ( ) = name and
@@ -1365,73 +1342,143 @@ module ClassNode {
1365
1342
}
1366
1343
1367
1344
override FunctionNode getAnInstanceMember ( MemberKind kind ) {
1345
+ // ES6 class methods
1346
+ exists ( MethodDeclaration method |
1347
+ astNode instanceof ClassDefinition and
1348
+ method = astNode .( ClassDefinition ) .getAMethod ( ) and
1349
+ not method .isStatic ( ) and
1350
+ kind = MemberKind:: of ( method ) and
1351
+ result = method .getBody ( ) .flow ( )
1352
+ )
1353
+ or
1354
+ // ES6 class property in constructor
1355
+ astNode instanceof ClassDefinition and
1356
+ kind = MemberKind:: method ( ) and
1357
+ exists ( ThisNode receiver |
1358
+ receiver = this .getConstructor ( ) .getReceiver ( ) and
1359
+ result = receiver .getAPropertySource ( )
1360
+ )
1361
+ or
1362
+ // Function-style class methods via prototype
1363
+ astNode instanceof Function and
1368
1364
kind = MemberKind:: method ( ) and
1369
- result = this .getAPrototypeReference ( ) .getAPropertySource ( )
1365
+ exists ( DataFlow:: SourceNode proto |
1366
+ proto = this .getAPrototypeReference ( ) and
1367
+ result = proto .getAPropertySource ( )
1368
+ )
1370
1369
or
1370
+ // Function-style class methods via constructor
1371
+ astNode instanceof Function and
1371
1372
kind = MemberKind:: method ( ) and
1372
- result = this .getConstructor ( ) .getReceiver ( ) .getAPropertySource ( )
1373
+ exists ( ThisNode receiver |
1374
+ receiver = this .getConstructor ( ) .getReceiver ( ) and
1375
+ result = receiver .getAPropertySource ( )
1376
+ )
1373
1377
or
1378
+ // Function-style class accessors
1379
+ astNode instanceof Function and
1374
1380
exists ( PropertyAccessor accessor |
1375
1381
accessor = this .getAnAccessor ( kind ) and
1376
1382
result = accessor .getInit ( ) .flow ( )
1377
1383
)
1378
1384
}
1379
1385
1380
1386
override FunctionNode getStaticMember ( string name , MemberKind kind ) {
1387
+ exists ( MethodDeclaration method |
1388
+ astNode instanceof ClassDefinition and
1389
+ method = astNode .( ClassDefinition ) .getMethod ( name ) and
1390
+ method .isStatic ( ) and
1391
+ kind = MemberKind:: of ( method ) and
1392
+ result = method .getBody ( ) .flow ( )
1393
+ )
1394
+ or
1381
1395
kind .isMethod ( ) and
1382
1396
result = this .getAPropertySource ( name )
1383
1397
}
1384
1398
1385
1399
override FunctionNode getAStaticMember ( MemberKind kind ) {
1400
+ exists ( MethodDeclaration method |
1401
+ astNode instanceof ClassDefinition and
1402
+ method = astNode .( ClassDefinition ) .getAMethod ( ) and
1403
+ method .isStatic ( ) and
1404
+ kind = MemberKind:: of ( method ) and
1405
+ result = method .getBody ( ) .flow ( )
1406
+ )
1407
+ or
1386
1408
kind .isMethod ( ) and
1387
1409
result = this .getAPropertySource ( )
1388
1410
}
1389
1411
1390
1412
/**
1391
1413
* Gets a reference to the prototype of this class.
1414
+ * Only applies to function-style classes.
1392
1415
*/
1393
1416
DataFlow:: SourceNode getAPrototypeReference ( ) {
1394
- exists ( DataFlow:: SourceNode base | base = getAFunctionValueWithPrototype ( function ) |
1395
- result = base .getAPropertyRead ( "prototype" )
1417
+ astNode instanceof Function and
1418
+ (
1419
+ exists ( DataFlow:: SourceNode base | base = getAFunctionValueWithPrototype ( function ) |
1420
+ result = base .getAPropertyRead ( "prototype" )
1421
+ or
1422
+ result = base .getAPropertySource ( "prototype" )
1423
+ )
1396
1424
or
1397
- result = base .getAPropertySource ( "prototype" )
1398
- )
1399
- or
1400
- exists ( string name |
1401
- this = AccessPath:: getAnAssignmentTo ( name ) and
1402
- result = getAPrototypeReferenceInFile ( name , this .getFile ( ) )
1403
- )
1404
- or
1405
- exists ( ExtendCall call |
1406
- call .getDestinationOperand ( ) = this .getAPrototypeReference ( ) and
1407
- result = call .getASourceOperand ( )
1425
+ exists ( string name |
1426
+ this = AccessPath:: getAnAssignmentTo ( name ) and
1427
+ result = getAPrototypeReferenceInFile ( name , this .getFile ( ) )
1428
+ )
1429
+ or
1430
+ exists ( ExtendCall call |
1431
+ call .getDestinationOperand ( ) = this .getAPrototypeReference ( ) and
1432
+ result = call .getASourceOperand ( )
1433
+ )
1408
1434
)
1409
1435
}
1410
1436
1411
1437
override DataFlow:: Node getASuperClassNode ( ) {
1412
- // C.prototype = Object.create(D.prototype)
1413
- exists ( DataFlow:: InvokeNode objectCreate , DataFlow:: PropRead superProto |
1414
- this .getAPropertySource ( "prototype" ) = objectCreate and
1415
- objectCreate = DataFlow:: globalVarRef ( "Object" ) .getAMemberCall ( "create" ) and
1416
- superProto .flowsTo ( objectCreate .getArgument ( 0 ) ) and
1417
- superProto .getPropertyName ( ) = "prototype" and
1418
- result = superProto .getBase ( )
1419
- )
1438
+ // ES6 class superclass
1439
+ astNode instanceof ClassDefinition and
1440
+ result = astNode .( ClassDefinition ) .getSuperClass ( ) .flow ( )
1420
1441
or
1421
- // C.prototype = new D()
1422
- exists ( DataFlow:: NewNode newCall |
1423
- this .getAPropertySource ( "prototype" ) = newCall and
1424
- result = newCall .getCalleeNode ( )
1442
+ // Function-style class superclass patterns
1443
+ astNode instanceof Function and
1444
+ (
1445
+ // C.prototype = Object.create(D.prototype)
1446
+ exists ( DataFlow:: InvokeNode objectCreate , DataFlow:: PropRead superProto |
1447
+ this .getAPropertySource ( "prototype" ) = objectCreate and
1448
+ objectCreate = DataFlow:: globalVarRef ( "Object" ) .getAMemberCall ( "create" ) and
1449
+ superProto .flowsTo ( objectCreate .getArgument ( 0 ) ) and
1450
+ superProto .getPropertyName ( ) = "prototype" and
1451
+ result = superProto .getBase ( )
1452
+ )
1453
+ or
1454
+ // C.prototype = new D()
1455
+ exists ( DataFlow:: NewNode newCall |
1456
+ this .getAPropertySource ( "prototype" ) = newCall and
1457
+ result = newCall .getCalleeNode ( )
1458
+ )
1459
+ or
1460
+ // util.inherits(C, D);
1461
+ exists ( DataFlow:: CallNode inheritsCall |
1462
+ inheritsCall = DataFlow:: moduleMember ( "util" , "inherits" ) .getACall ( )
1463
+ |
1464
+ this = inheritsCall .getArgument ( 0 ) .getALocalSource ( ) and
1465
+ result = inheritsCall .getArgument ( 1 )
1466
+ )
1425
1467
)
1426
- or
1427
- // util.inherits(C, D);
1428
- exists ( DataFlow :: CallNode inheritsCall |
1429
- inheritsCall = DataFlow :: moduleMember ( "util" , "inherits" ) . getACall ( )
1430
- |
1431
- this = inheritsCall . getArgument ( 0 ) . getALocalSource ( ) and
1432
- result = inheritsCall . getArgument ( 1 )
1468
+ }
1469
+
1470
+ override TypeAnnotation getFieldTypeAnnotation ( string fieldName ) {
1471
+ exists ( FieldDeclaration field |
1472
+ field . getDeclaringClass ( ) = astNode and
1473
+ fieldName = field . getName ( ) and
1474
+ result = field . getTypeAnnotation ( )
1433
1475
)
1434
1476
}
1477
+
1478
+ override DataFlow:: Node getADecorator ( ) {
1479
+ astNode instanceof ClassDefinition and
1480
+ result = astNode .( ClassDefinition ) .getADecorator ( ) .getExpression ( ) .flow ( )
1481
+ }
1435
1482
}
1436
1483
}
1437
1484
0 commit comments