JS: Add ClassDefinition.getInferredName

This commit is contained in:
Asger F
2019-07-11 16:19:11 +01:00
parent eead67ac6d
commit c44a3b4735
5 changed files with 46 additions and 0 deletions

View File

@@ -17,6 +17,16 @@ class ClassOrInterface extends @classorinterface, TypeParameterized {
/** Gets the name of the defined class or interface, if any. */
string getName() { result = getIdentifier().getName() }
/**
* Gets the name of the defined class or interface, possibly inferred
* from the context if this is an anonymous class expression.
*
* Has no result if no name could be determined.
*/
string getInferredName() {
result = getName() // Overridden in ClassExpr
}
/** Gets the nearest enclosing function or toplevel in which this class or interface occurs. */
StmtContainer getContainer() { result = this.(ExprOrStmt).getContainer() }
@@ -210,6 +220,25 @@ class ClassDeclStmt extends @classdeclstmt, ClassDefinition, Stmt {
* A class expression.
*/
class ClassExpr extends @classexpr, ClassDefinition, Expr {
override 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()
)
}
override predicate isImpure() { none() }
/** Gets the nearest enclosing function or toplevel in which this class expression occurs. */

View File

@@ -1,5 +1,14 @@
getInferredName
| tst.js:16:1:19:1 | class C ... ss C"\\n} | C |
| tst.js:21:2:23:1 | class D ... lass"\\n} | D |
| tst.js:22:12:22:18 | class{} | |
| tst.js:25:11:25:18 | class {} | E |
| tst.js:26:11:29:1 | class G ... ss G"\\n} | G |
| tst.js:34:9:34:16 | class {} | Foo |
#select
| tst.js:16:1:19:1 | class C ... ss C"\\n} | class C |
| tst.js:21:2:23:1 | class D ... lass"\\n} | class D |
| tst.js:22:12:22:18 | class{} | anonymous class |
| tst.js:25:11:25:18 | class {} | class E |
| tst.js:26:11:29:1 | class G ... ss G"\\n} | class G |
| tst.js:34:9:34:16 | class {} | class Foo |

View File

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

View File

@@ -18,6 +18,7 @@ getInferredName
| tst.js:27:8:27:12 | () {} | y |
| tst.js:28:8:28:13 | (v) {} | y |
| tst.js:31:9:31:21 | function() {} | foo |
| tst.js:34:15:34:14 | () {} | constructor |
#select
| tst.js:1:1:1:15 | function f() {} | function f |
| tst.js:2:2:2:16 | function g() {} | function g |
@@ -40,3 +41,4 @@ getInferredName
| 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 |
| tst.js:34:15:34:14 | () {} | default constructor of class Foo |

View File

@@ -30,3 +30,5 @@ const E = class {}, // "class E", "default constructor of class E"
o.foo = function() {}; // "method foo"
o["Hey"] = function() {}; // "anonymous function"
o.Foo = class {}; // "class Foo"