Closed github-learning-lab[bot] closed 3 years ago
$
We want to identify the expression that is used as the first argument for each call, such as in $(<first-argument>)
.
calls-to-dollar-arg.ql
and start by copying your previous query.dollarArg
) that belongs to this class.dollarCall
variable of type CallExpr
to guess the predicate that gets the argument at a 0-based index. Start typing get
and browse the predicates, and their contextual documentation.and
in the where
clause.Ooops! The query you submitted in 2bb33dc122ffbcbfba8fe5c60673a7f74022a573 didn't find the right results. Have a look at the comment.
To submit a new iteration of your query, you just have to push a new commit to the same branch (the default branch or the PR branch).
Congratulations, looks like the query you introduced in 969947d1c7a0099c284eb0aedbbceb272b1c9f75 finds the correct results!
Take a look at the instructions for the next step to continue.
Step 4: Anatomy of a query
Now let's analyze what you have written. A CodeQL query has the following basic structure:
The
from
/where
/select
part is the query clause: it describes what we are trying to find in the source code.Let's look closer at the query we wrote in the previous step.
Show the query
```ql import javascript from CallExpr dollarCall where dollarCall.getCalleeName() = "$" select dollarCall ```Imports
At the top of the query is
import javascript
. This is an import statement . It brings into scope the standard CodeQL library that models JavaScript/TypeScript code, allowing us to use its features in our query. We'll use this library in every query, and in later steps we'll also use some more specialized libraries.Classes
In the
from
section, there is a declarationCallExpr dollarCall
. Here we declare a variable nameddollarCall
which has the typeCallExpr
.CallExpr
is a class declared in the standard library (you can jump to the definition usingF12
). A class represents a collection of values, in this case the collection of all function calls.Predicates
Now look at the expression
dollarCall.getCalleeName()
in thewhere
section. Here we call the predicategetCalleeName
on the variabledollarCall
of typeCallExpr
. Predicates are the building blocks of a query: they express logical properties that we want to hold. Some predicates return results (likegetCalleeName
) , and some predicates do not (they just assert that a property must be true).So far your query finds all functions with the name
$
. It does this by asserting that the result ofdollarCall.getCalleeName()
is equal to the string"$"
. But what we want actually is to find the first argument of each of these calls.One way to do this is to declare two variables: one to represent function calls, and one to represent call arguments. Then you will have to create a relationship between these variables in the
where
section, so that they are restricted to the first arguments of calls to functions named$
.