JS: Add ClassNode.getStaticMember

This commit is contained in:
Asger Feldthaus
2022-03-30 10:09:57 +02:00
parent cb898ae03f
commit 37b3a6e5c0
4 changed files with 66 additions and 8 deletions

View File

@@ -898,17 +898,31 @@ class ClassNode extends DataFlow::SourceNode instanceof ClassNode::Range {
*/
FunctionNode getAnInstanceMember() { result = super.getAnInstanceMember(_) }
/**
* Gets the static method, getter, or setter declared in this class with the given name and kind.
*/
FunctionNode getStaticMember(string name, MemberKind kind) {
result = super.getStaticMember(name, kind)
}
/**
* Gets the static method declared in this class with the given name.
*/
FunctionNode getStaticMethod(string name) { result = super.getStaticMethod(name) }
FunctionNode getStaticMethod(string name) {
result = this.getStaticMember(name, MemberKind::method())
}
/**
* Gets a static method, getter, or setter declared in this class with the given kind.
*/
FunctionNode getAStaticMember(MemberKind kind) { result = super.getAStaticMember(kind) }
/**
* Gets a static method declared in this class.
*
* The constructor is not considered a static method.
*/
FunctionNode getAStaticMethod() { result = super.getAStaticMethod() }
FunctionNode getAStaticMethod() { result = this.getAStaticMember(MemberKind::method()) }
/**
* Gets a dataflow node that refers to the superclass of this class.
@@ -1119,18 +1133,34 @@ module ClassNode {
abstract FunctionNode getAnInstanceMember(MemberKind kind);
/**
* Gets the static member of this class with the given name and kind.
*/
cached
abstract FunctionNode getStaticMember(string name, MemberKind kind);
/**
* DEPRECATED. Override `getStaticMember` instead.
*
* Gets the static method of this class with the given name.
*/
cached
abstract FunctionNode getStaticMethod(string name);
deprecated FunctionNode getStaticMethod(string name) { none() }
/**
* Gets a static member of this class of the given kind.
*/
cached
abstract FunctionNode getAStaticMember(MemberKind kind);
/**
* DEPRECATED. Override `getAStaticMember` instead.
*
* Gets a static method of this class.
*
* The constructor is not considered a static method.
*/
cached
abstract FunctionNode getAStaticMethod();
deprecated FunctionNode getAStaticMethod() { none() }
/**
* Gets a dataflow node representing a class to be used as the super-class
@@ -1186,23 +1216,27 @@ module ClassNode {
result = this.getConstructor().getReceiver().getAPropertySource()
}
override FunctionNode getStaticMethod(string name) {
override FunctionNode getStaticMember(string name, MemberKind kind) {
exists(MethodDeclaration method |
method = astNode.getMethod(name) and
method.isStatic() and
kind = MemberKind::of(method) and
result = method.getBody().flow()
)
or
kind.isMethod() and
result = this.getAPropertySource(name)
}
override FunctionNode getAStaticMethod() {
override FunctionNode getAStaticMember(MemberKind kind) {
exists(MethodDeclaration method |
method = astNode.getAMethod() and
method.isStatic() and
kind = MemberKind::of(method) and
result = method.getBody().flow()
)
or
kind.isMethod() and
result = this.getAPropertySource()
}
@@ -1300,9 +1334,15 @@ module ClassNode {
)
}
override FunctionNode getStaticMethod(string name) { result = this.getAPropertySource(name) }
override FunctionNode getStaticMember(string name, MemberKind kind) {
kind.isMethod() and
result = this.getAPropertySource(name)
}
override FunctionNode getAStaticMethod() { result = this.getAPropertySource() }
override FunctionNode getAStaticMember(MemberKind kind) {
kind.isMethod() and
result = this.getAPropertySource()
}
/**
* Gets a reference to the prototype of this class.

View File

@@ -24,6 +24,7 @@ getAReceiverNode
| tst.js:23:1:23:15 | function D() {} | tst.js:25:13:25:12 | this |
| tst.js:23:1:23:15 | function D() {} | tst.js:26:13:26:12 | this |
| tst.js:23:1:23:15 | function D() {} | tst.js:27:4:27:3 | this |
| tst.js:30:1:34:1 | class S ... x) {}\\n} | tst.js:30:21:30:20 | this |
getFieldTypeAnnotation
| fields.ts:1:1:3:1 | class B ... mber;\\n} | baseField | fields.ts:2:16:2:21 | number |
| fields.ts:5:1:13:1 | class F ... > {};\\n} | x | fields.ts:6:27:6:32 | number |
@@ -53,6 +54,11 @@ instanceMethod
| tst.js:15:1:15:15 | function B() {} | foo | tst.js:17:19:17:31 | function() {} | B |
| tst.js:19:1:19:15 | function C() {} | bar | tst.js:21:19:21:31 | function() {} | C |
| tst.js:23:1:23:15 | function D() {} | m | tst.js:27:4:27:8 | () {} | D |
staticMember
| tst.js:3:1:10:1 | class A ... () {}\\n} | staticMethod | method | tst.js:5:22:5:26 | () {} | A |
| tst.js:30:1:34:1 | class S ... x) {}\\n} | getter | getter | tst.js:32:20:32:24 | () {} | StaticMembers |
| tst.js:30:1:34:1 | class S ... x) {}\\n} | method | method | tst.js:31:16:31:20 | () {} | StaticMembers |
| tst.js:30:1:34:1 | class S ... x) {}\\n} | setter | setter | tst.js:33:20:33:25 | (x) {} | StaticMembers |
superClass
| fields.ts:5:1:13:1 | class F ... > {};\\n} | fields.ts:1:1:3:1 | class B ... mber;\\n} | Foo | Base |
| tst.js:13:1:13:21 | class A ... ds A {} | tst.js:3:1:10:1 | class A ... () {}\\n} | A2 | A |

View File

@@ -24,6 +24,12 @@ query predicate instanceMethod(
cls.getInstanceMethod(name) = inst and clsName = cls.getName()
}
query predicate staticMember(
DataFlow::ClassNode cls, string name, string kind, DataFlow::FunctionNode inst, string clsName
) {
cls.getStaticMember(name, kind) = inst and clsName = cls.getName()
}
query predicate superClass(
DataFlow::ClassNode cls, DataFlow::ClassNode sup, string clsName, string supName
) {

View File

@@ -26,3 +26,9 @@ D.prototype = {
set setter(x) {},
m() {}
}
class StaticMembers {
static method() {}
static get getter() {}
static set setter(x) {}
}