PS: AST support for 'this'.

This commit is contained in:
Mathias Vorreiter Pedersen
2024-10-08 14:44:05 +01:00
parent a429485b56
commit 61d5f4412c
4 changed files with 45 additions and 5 deletions

View File

@@ -33,16 +33,28 @@ abstract private class AbstractFunction extends Ast {
/** Gets the number of function parameters. */
final int getNumberOfFunctionParameters() { result = count(this.getAFunctionParameter()) }
/** Gets the number of parameters (both function and block). */
/**
* Gets the number of parameters (both function and block).
* Note: This excludes the `this` parameter.
*/
final int getNumberOfParameters() { result = count(this.getAParameter()) }
/** Gets the i'th parameter of this function, if any. */
/**
* Gets the i'th parameter of this function, if any.
*
* This does not include the `this` parameter.
*/
final Parameter getParameter(int i) {
result = this.getFunctionParameter(i)
or
result = this.getBody().getParamBlock().getParameter(i)
}
final Parameter getThisParameter() {
result.isThis() and
result.getFunction() = this
}
/** Gets any parameter of this function. */
final Parameter getAParameter() { result = this.getParameter(_) }

View File

@@ -42,7 +42,8 @@ private newtype TParameterImpl =
TInternalParameter(Internal::Parameter p) or
TUnderscore(Scope scope) {
exists(VarAccess va | va.getUserPath() = "_" and scope = va.getEnclosingScope())
}
} or
TThisParameter(Scope scope) { exists(scope.getEnclosingFunction().getDeclaringType()) }
private class ParameterImpl extends TParameterImpl {
abstract Location getLocation();
@@ -109,9 +110,22 @@ private class Underscore extends ParameterImpl, TUnderscore {
final override Scope getEnclosingScope() { result = scope }
}
private class ThisParameter extends ParameterImpl, TThisParameter {
Scope scope;
ThisParameter() { this = TThisParameter(scope) }
override Location getLocation() { result = scope.getLocation() }
override string getName() { result = "this" }
final override Scope getEnclosingScope() { result = scope }
}
private newtype TVariable =
TLocalVariable(string name, Scope scope) {
not isParameterImpl(name, scope) and
not name = "this" and // This is modeled as a parameter
exists(VarAccess va | va.getUserPath() = name and scope = va.getEnclosingScope())
} or
TParameter(ParameterImpl p)
@@ -186,8 +200,11 @@ class Parameter extends AbstractLocalScopeVariable, TParameter {
predicate hasDefaultValue() { exists(this.getDefaultValue()) }
/** Holds if this is the `this` parameter. */
predicate isThis() { p instanceof ThisParameter }
/**
* Gets the index of this parameter.
* Gets the index of this parameter, if any.
*
* The parameter may be in a parameter block or a function parameter.
*/

View File

@@ -217,7 +217,11 @@ module ExprNodes {
/** Gets the name of this argument, if any. */
string getName() { result = e.getName() }
StmtNodes::CmdCfgNode getCmd() { result.getAnArgument() = this }
/** Holds if `this` is a qualifier to a call. */
predicate isQualifier() { e.isQualifier() }
/** Gets the call for which this is an argument. */
CallCfgNode getCall() { result.getAnArgument() = this or result.getQualifier() = this }
}
private class InvokeMemberChildMapping extends ExprChildMapping, InvokeMemberExpr {

View File

@@ -36,4 +36,11 @@ class Scope extends Ast, @script_block {
* This may be both function paramters and parameter block parameters.
*/
Parameter getAParameter() { result = this.getParameter(_) }
Parameter getThisParameter() {
exists(Function func |
func.getBody() = this and
result = func.getThisParameter()
)
}
}