add explicit this to all member calls

This commit is contained in:
Erik Krogh Kristensen
2021-11-01 09:51:15 +01:00
parent 1c78c792ff
commit db40ccae81
85 changed files with 2063 additions and 1937 deletions

View File

@@ -39,14 +39,14 @@ import javascript
class Function extends @function, Parameterized, TypeParameterized, StmtContainer, Documentable,
AST::ValueNode {
/** Gets the `i`th parameter of this function. */
Parameter getParameter(int i) { result = getChildExpr(i) }
Parameter getParameter(int i) { result = this.getChildExpr(i) }
/** Gets a parameter of this function. */
override Parameter getAParameter() { exists(int idx | result = getParameter(idx)) }
override Parameter getAParameter() { exists(int idx | result = this.getParameter(idx)) }
/** Gets the parameter named `name` of this function, if any. */
SimpleParameter getParameterByName(string name) {
result = getAParameter() and
result = this.getAParameter() and
result.getName() = name
}
@@ -72,9 +72,9 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
* `this` parameter types are specific to TypeScript.
*/
TypeAnnotation getThisTypeAnnotation() {
result = getChildTypeExpr(-4)
result = this.getChildTypeExpr(-4)
or
result = getDocumentation().getATagByTitle("this").getType()
result = this.getDocumentation().getATagByTitle("this").getType()
}
/**
@@ -82,10 +82,10 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
*
* Gets the identifier specifying the name of this function, if any.
*/
deprecated VarDecl getId() { result = getIdentifier() }
deprecated VarDecl getId() { result = this.getIdentifier() }
/** Gets the identifier specifying the name of this function, if any. */
VarDecl getIdentifier() { result = getChildExpr(-1) }
VarDecl getIdentifier() { result = this.getChildExpr(-1) }
/**
* Gets the name of this function if it has one, or a name inferred from its context.
@@ -96,9 +96,9 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
* can be inferred, there is no result.
*/
string getName() {
result = getIdentifier().getName()
result = this.getIdentifier().getName()
or
not exists(getIdentifier()) and
not exists(this.getIdentifier()) and
(
exists(VarDef vd | this = vd.getSource() | result = vd.getTarget().(VarRef).getName())
or
@@ -118,17 +118,17 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
}
/** Gets the variable holding this function. */
Variable getVariable() { result = getIdentifier().getVariable() }
Variable getVariable() { result = this.getIdentifier().getVariable() }
/** Gets the `arguments` variable of this function, if any. */
ArgumentsVariable getArgumentsVariable() { result.getFunction() = this }
/** Holds if the body of this function refers to the function's `arguments` variable. */
predicate usesArgumentsObject() {
exists(getArgumentsVariable().getAnAccess())
exists(this.getArgumentsVariable().getAnAccess())
or
exists(PropAccess read |
read.getBase() = getVariable().getAnAccess() and
read.getBase() = this.getVariable().getAnAccess() and
read.getPropertyName() = "arguments"
)
}
@@ -136,29 +136,31 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
/**
* Holds if this function declares a parameter or local variable named `arguments`.
*/
predicate declaresArguments() { exists(getScope().getVariable("arguments").getADeclaration()) }
predicate declaresArguments() {
exists(this.getScope().getVariable("arguments").getADeclaration())
}
/** Gets the statement enclosing this function, if any. */
Stmt getEnclosingStmt() { none() }
/** Gets the body of this function. */
override ExprOrStmt getBody() { result = getChild(-2) }
override ExprOrStmt getBody() { result = this.getChild(-2) }
/** Gets the `i`th statement in the body of this function. */
Stmt getBodyStmt(int i) { result = getBody().(BlockStmt).getStmt(i) }
Stmt getBodyStmt(int i) { result = this.getBody().(BlockStmt).getStmt(i) }
/** Gets a statement in the body of this function. */
Stmt getABodyStmt() { result = getBodyStmt(_) }
Stmt getABodyStmt() { result = this.getBodyStmt(_) }
/** Gets the number of statements in the body of this function. */
int getNumBodyStmt() { result = count(getABodyStmt()) }
int getNumBodyStmt() { result = count(this.getABodyStmt()) }
/** Gets the return type annotation on this function, if any. */
TypeAnnotation getReturnTypeAnnotation() {
typeexprs(result, _, this, -3, _)
or
exists(string title | title = "return" or title = "returns" |
result = getDocumentation().getATagByTitle(title).getType()
result = this.getDocumentation().getATagByTitle(title).getType()
)
}
@@ -179,7 +181,7 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
*/
private Token lastTokenOfParameterList() {
// if there are any parameters, it's the last token of the last parameter
exists(Parameter lastParam | lastParam = getParameter(getNumParameter() - 1) |
exists(Parameter lastParam | lastParam = this.getParameter(this.getNumParameter() - 1) |
result = lastParam.getDefault().getLastToken()
or
not exists(lastParam.getDefault()) and result = lastParam.getLastToken()
@@ -187,32 +189,34 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
or
// otherwise we have an empty parameter list `()`, and
// we want to return the opening parenthesis
not exists(getAParameter()) and
not exists(this.getAParameter()) and
(
// if the function has a name, the opening parenthesis comes right after it
result = getIdentifier().getLastToken().getNextToken()
result = this.getIdentifier().getLastToken().getNextToken()
or
// otherwise this must be an arrow function with no parameters, so the opening
// parenthesis is the very first token of the function
not exists(getIdentifier()) and result = getFirstToken()
not exists(this.getIdentifier()) and result = this.getFirstToken()
)
}
/** Holds if the parameter list of this function has a trailing comma. */
predicate hasTrailingComma() { lastTokenOfParameterList().getNextToken().getValue() = "," }
predicate hasTrailingComma() { this.lastTokenOfParameterList().getNextToken().getValue() = "," }
/** Holds if this function is an asynchronous function. */
predicate isAsync() { is_async(this) }
/** Holds if this function is asynchronous or a generator. */
predicate isAsyncOrGenerator() { isAsync() or isGenerator() }
predicate isAsyncOrGenerator() { this.isAsync() or this.isGenerator() }
/** Gets the enclosing function or toplevel of this function. */
override StmtContainer getEnclosingContainer() { result = getEnclosingStmt().getContainer() }
override StmtContainer getEnclosingContainer() { result = this.getEnclosingStmt().getContainer() }
/** Gets the number of lines in this function. */
int getNumberOfLines() {
exists(int sl, int el | getLocation().hasLocationInfo(_, sl, _, el, _) | result = el - sl + 1)
exists(int sl, int el | this.getLocation().hasLocationInfo(_, sl, _, el, _) |
result = el - sl + 1
)
}
/** Gets the number of lines containing code in this function. */
@@ -247,8 +251,8 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
/** Gets an expression that could be returned by this function, if any. */
Expr getAReturnedExpr() {
result = getBody() or
result = getAReturnStmt().getExpr()
result = this.getBody() or
result = this.getAReturnStmt().getExpr()
}
/**
@@ -262,10 +266,10 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
* which is the nearest enclosing non-arrow function or top-level.
*/
StmtContainer getThisBindingContainer() {
result = getThisBinder()
result = this.getThisBinder()
or
not exists(getThisBinder()) and
result = getTopLevel()
not exists(this.getThisBinder()) and
result = this.getTopLevel()
}
/**
@@ -276,12 +280,12 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
* parameter, no parameter default values, and no destructuring parameters.
*/
predicate hasMappedArgumentsVariable() {
exists(getArgumentsVariable()) and
not isStrict() and
forall(Parameter p | p = getAParameter() |
exists(this.getArgumentsVariable()) and
not this.isStrict() and
forall(Parameter p | p = this.getAParameter() |
p instanceof SimpleParameter and not exists(p.getDefault())
) and
not hasRestParameter()
not this.hasRestParameter()
}
/**
@@ -293,23 +297,23 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
* can be inferred, the result is "anonymous function".
*/
override string describe() {
if exists(inferNameFromVarDef())
then result = inferNameFromVarDef()
if exists(this.inferNameFromVarDef())
then result = this.inferNameFromVarDef()
else
if exists(inferNameFromProp())
then result = inferNameFromProp()
if exists(this.inferNameFromProp())
then result = this.inferNameFromProp()
else
if exists(inferNameFromMemberDef())
then result = inferNameFromMemberDef()
if exists(this.inferNameFromMemberDef())
then result = this.inferNameFromMemberDef()
else
if exists(inferNameFromCallSig())
then result = inferNameFromCallSig()
if exists(this.inferNameFromCallSig())
then result = this.inferNameFromCallSig()
else
if exists(inferNameFromIndexSig())
then result = inferNameFromIndexSig()
if exists(this.inferNameFromIndexSig())
then result = this.inferNameFromIndexSig()
else
if exists(inferNameFromFunctionType())
then result = inferNameFromFunctionType()
if exists(this.inferNameFromFunctionType())
then result = this.inferNameFromFunctionType()
else result = "anonymous function"
}
@@ -319,8 +323,8 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
*/
private string inferNameFromVarDef() {
// in ambiguous cases like `var f = function g() {}`, prefer `g` to `f`
if exists(getIdentifier())
then result = "function " + getIdentifier().getName()
if exists(this.getIdentifier())
then result = "function " + this.getIdentifier().getName()
else
exists(VarDef vd | this = vd.getSource() |
result = "function " + vd.getTarget().(VarRef).getName()
@@ -400,7 +404,7 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
*
* A JavaScript function always has a body.
*/
predicate hasBody() { exists(getBody()) }
predicate hasBody() { exists(this.getBody()) }
/**
* Holds if this function is part of an abstract class member.
@@ -419,10 +423,10 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
this instanceof ArrowFunctionExpr and
kind = "an arrow function"
or
isGenerator() and
this.isGenerator() and
kind = "a generator function"
or
isAsync() and
this.isAsync() and
kind = "an async function"
}