@@ -1214,81 +1214,6 @@ module ClassNode {
12141214 DataFlow:: Node getADecorator ( ) { none ( ) }
12151215 }
12161216
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-
12921217 private DataFlow:: PropRef getAPrototypeReferenceInFile ( string name , File f ) {
12931218 result .getBase ( ) = AccessPath:: getAReferenceOrAssignmentTo ( name ) and
12941219 result .getPropertyName ( ) = "prototype" and
@@ -1313,12 +1238,18 @@ module ClassNode {
13131238
13141239 /**
13151240 * 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.
13161242 */
13171243 class FunctionStyleClass extends Range , DataFlow:: ValueNode {
1318- override Function astNode ;
1244+ override AST :: ValueNode astNode ;
13191245 AbstractFunction function ;
13201246
13211247 FunctionStyleClass ( ) {
1248+ // ES6 class case
1249+ astNode instanceof ClassDefinition
1250+ or
1251+ // Function-style class case
1252+ astNode instanceof Function and
13221253 function .getFunction ( ) = astNode and
13231254 (
13241255 exists ( getAFunctionValueWithPrototype ( function ) )
@@ -1333,13 +1264,30 @@ module ClassNode {
13331264 )
13341265 }
13351266
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+ }
13371272
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+ }
13391278
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+ }
13411287
13421288 private PropertyAccessor getAnAccessor ( MemberKind kind ) {
1289+ // Only applies to function-style classes
1290+ astNode instanceof Function and
13431291 result .getObjectExpr ( ) = this .getAPrototypeReference ( ) .asExpr ( ) and
13441292 (
13451293 kind = MemberKind:: getter ( ) and
@@ -1351,12 +1299,41 @@ module ClassNode {
13511299 }
13521300
13531301 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
13541313 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+ )
13561326 or
1327+ // Function-style class methods via constructor
1328+ astNode instanceof Function and
13571329 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+ )
13591334 or
1335+ // Function-style class accessors
1336+ astNode instanceof Function and
13601337 exists ( PropertyAccessor accessor |
13611338 accessor = this .getAnAccessor ( kind ) and
13621339 accessor .getName ( ) = name and
@@ -1365,73 +1342,143 @@ module ClassNode {
13651342 }
13661343
13671344 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
13681364 kind = MemberKind:: method ( ) and
1369- result = this .getAPrototypeReference ( ) .getAPropertySource ( )
1365+ exists ( DataFlow:: SourceNode proto |
1366+ proto = this .getAPrototypeReference ( ) and
1367+ result = proto .getAPropertySource ( )
1368+ )
13701369 or
1370+ // Function-style class methods via constructor
1371+ astNode instanceof Function and
13711372 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+ )
13731377 or
1378+ // Function-style class accessors
1379+ astNode instanceof Function and
13741380 exists ( PropertyAccessor accessor |
13751381 accessor = this .getAnAccessor ( kind ) and
13761382 result = accessor .getInit ( ) .flow ( )
13771383 )
13781384 }
13791385
13801386 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
13811395 kind .isMethod ( ) and
13821396 result = this .getAPropertySource ( name )
13831397 }
13841398
13851399 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
13861408 kind .isMethod ( ) and
13871409 result = this .getAPropertySource ( )
13881410 }
13891411
13901412 /**
13911413 * Gets a reference to the prototype of this class.
1414+ * Only applies to function-style classes.
13921415 */
13931416 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+ )
13961424 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+ )
14081434 )
14091435 }
14101436
14111437 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 ( )
14201441 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+ )
14251467 )
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 ( )
14331475 )
14341476 }
1477+
1478+ override DataFlow:: Node getADecorator ( ) {
1479+ astNode instanceof ClassDefinition and
1480+ result = astNode .( ClassDefinition ) .getADecorator ( ) .getExpression ( ) .flow ( )
1481+ }
14351482 }
14361483}
14371484
0 commit comments