JS: Add Function.getInferredName()

This commit is contained in:
Asger F
2019-07-11 16:15:53 +01:00
parent 66464b5c48
commit eead67ac6d
4 changed files with 65 additions and 1 deletions

View File

@@ -47,9 +47,43 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
/** Gets the identifier specifying the name of this function, if any. */
VarDecl getId() { result = getChildExpr(-1) }
/** Gets the name of this function, if any. */
/**
* Gets the name of this function, if it is a function declaration
* or named function expression.
*/
string getName() { result = getId().getName() }
/**
* Gets the name of this function if it has one, or a name inferred from its context.
*
* For named functions such as `function f() { ... }`, this is just the declared
* name. For functions assigned to variables or properties (including class
* members), this is the name of the variable or property. If no meaningful name
* can be inferred, there is no result.
*/
string getInferredName() {
result = getName()
or
exists(VarDef vd | this = vd.getSource() |
result = vd.getTarget().(VarRef).getName()
)
or
exists(Property p |
this = p.getInit() and
result = p.getName()
)
or
exists(AssignExpr assign, DotExpr prop |
this = assign.getRhs().getUnderlyingValue() and
prop = assign.getLhs() and
result = prop.getPropertyName()
)
or
exists(ClassOrInterface c |
this = c.getMember(result).getInit()
)
}
/** Gets the variable holding this function. */
Variable getVariable() { result = getId().getVariable() }

View File

@@ -1,3 +1,24 @@
getInferredName
| tst.js:1:1:1:15 | function f() {} | f |
| tst.js:2:2:2:16 | function g() {} | g |
| tst.js:4:9:4:22 | function () {} | h |
| tst.js:5:9:5:14 | x => x | k |
| tst.js:6:9:6:23 | function n() {} | n |
| tst.js:9:6:9:18 | function() {} | p |
| tst.js:10:6:10:20 | function f() {} | f |
| tst.js:11:8:11:12 | () {} | x |
| tst.js:12:8:12:13 | (v) {} | x |
| tst.js:13:4:13:8 | () {} | m |
| tst.js:17:14:17:18 | () {} | constructor |
| tst.js:18:4:18:8 | () {} | n |
| tst.js:22:17:22:16 | () {} | constructor |
| tst.js:22:21:22:20 | (...arg ... rgs); } | constructor |
| tst.js:25:17:25:16 | () {} | constructor |
| tst.js:26:19:26:18 | () {} | constructor |
| tst.js:27:8:27:12 | () {} | y |
| tst.js:28:8:28:13 | (v) {} | y |
| tst.js:31:9:31:21 | function() {} | foo |
#select
| tst.js:1:1:1:15 | function f() {} | function f |
| tst.js:2:2:2:16 | function g() {} | function g |
| tst.js:3:2:3:14 | function() {} | anonymous function |
@@ -17,3 +38,5 @@
| tst.js:26:19:26:18 | () {} | default constructor of class G |
| tst.js:27:8:27:12 | () {} | getter method for property y of class G |
| tst.js:28:8:28:13 | (v) {} | setter method for property y of class G |
| tst.js:31:9:31:21 | function() {} | method foo |
| tst.js:32:12:32:24 | function() {} | anonymous function |

View File

@@ -1,4 +1,8 @@
import javascript
query string getInferredName(Function f) {
result = f.getInferredName()
}
from Function f
select f, f.describe()

View File

@@ -27,3 +27,6 @@ const E = class {}, // "class E", "default constructor of class E"
get y() {} // "getter method for property y of class G"
set y(v) {} // "setter method for property y of class G"
};
o.foo = function() {}; // "method foo"
o["Hey"] = function() {}; // "anonymous function"