You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/codeql/codeql-language-guides/basic-query-for-java-code.rst
+62-48Lines changed: 62 additions & 48 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,18 +1,33 @@
1
1
.. _basic-query-for-java-code:
2
2
3
-
Basic query for Java code
4
-
=========================
3
+
Basic query for Java and Kotlin code
4
+
====================================
5
5
6
6
Learn to write and run a simple CodeQL query using LGTM.
7
7
8
8
About the query
9
9
---------------
10
10
11
-
The query we're going to run performs a basic search of the code for ``if`` statements that are redundant, in the sense that they have an empty then branch. For example, code such as:
11
+
The query we're going to run searches for inefficient tests for empty strings. For example, Java code such as:
12
12
13
13
.. code-block:: java
14
14
15
-
if (error) { }
15
+
publicclassTestJava {
16
+
voidmyJavaFun(Strings) {
17
+
boolean b = s.equals("");
18
+
}
19
+
}
20
+
21
+
or Kotlin code such as:
22
+
23
+
.. code-block:: kotlin
24
+
25
+
void myKotlinFun(s: String) {
26
+
var b = s.equals("")
27
+
}
28
+
29
+
In either case, replacing ``s.equals("")`` with ``s.isEmpty()``
30
+
would be more efficient.
16
31
17
32
Running the query
18
33
-----------------
@@ -37,10 +52,13 @@ Running the query
37
52
38
53
import java
39
54
40
-
from IfStmt ifstmt, BlockStmt block
41
-
where ifstmt.getThen() = block and
42
-
block.getNumStmt() = 0
43
-
select ifstmt, "This 'if' statement is redundant."
55
+
from MethodAccess ma
56
+
where
57
+
ma.getMethod().hasName("equals") and
58
+
ma.getArgument(0).(StringLiteral).getValue() = ""
59
+
select ma, "This comparison to empty string is inefficient, use isEmpty() instead."
60
+
61
+
Note that CodeQL treats Java and Kotlin as part of the same language, so even though this query starts with ``import java``, it will work for both Java and Kotlin code.
44
62
45
63
LGTM checks whether your query compiles and, if all is well, the **Run** button changes to green to indicate that you can go ahead and run the query.
46
64
@@ -57,44 +75,43 @@ Running the query
57
75
58
76
Your query is always run against the most recently analyzed commit to the selected project.
59
77
60
-
The query will take a few moments to return results. When the query completes, the results are displayed below the project name. The query results are listed in two columns, corresponding to the two expressions in the ``select`` clause of the query. The first column corresponds to the expression ``ifstmt`` and is linked to the location in the source code of the project where ``ifstmt`` occurs. The second column is the alert message.
78
+
The query will take a few moments to return results. When the query completes, the results are displayed below the project name. The query results are listed in two columns, corresponding to the two expressions in the ``select`` clause of the query. The first column corresponds to the expression ``ma`` and is linked to the location in the source code of the project where ``ma`` occurs. The second column is the alert message.
An ellipsis (…) at the bottom of the table indicates that the entire list is not displayed—click it to show more results.
69
87
70
-
#. If any matching code is found, click a link in the ``ifstmt`` column to view the ``if`` statement in the code viewer.
88
+
#. If any matching code is found, click a link in the ``ma`` column to view the ``.equals`` expression in the code viewer.
71
89
72
-
The matching ``if`` statement is highlighted with a yellow background in the code viewer. If any code in the file also matches a query from the standard query library for that language, you will see a red alert message at the appropriate point within the code.
90
+
The matching ``.equals`` expression is highlighted with a yellow background in the code viewer. If any code in the file also matches a query from the standard query library for that language, you will see a red alert message at the appropriate point within the code.
73
91
74
92
About the query structure
75
93
~~~~~~~~~~~~~~~~~~~~~~~~~
76
94
77
95
After the initial ``import`` statement, this simple query comprises three parts that serve similar purposes to the FROM, WHERE, and SELECT parts of an SQL query.
| ``where ifstmt.getThen() = block and block.getNumStmt() = 0`` | Defines a condition on the variables. | ``ifstmt.getThen() = block`` relates the two variables. The block must be the ``then`` branch of the ``if`` statement. |
90
-
||||
91
-
||| ``block.getNumStmt() = 0`` states that the block must be empty (that is, it contains no statements). |
| ``select ifstmt, "This 'if' statement is redundant."`` | Defines what to report for each match. | Reports the resulting ``if`` statement with a string that explains the problem. |
94
-
||||
95
-
|| ``select`` statements for queries that are used to find instances of poor coding practice are always in the form: ||
| ``where ma.getMethod().hasName("equals") and ma.getArgument(0).(StringLiteral).getValue() = ""`` | Defines a condition on the variables. | ``ma.getMethod().hasName("equals")`` restricts ``ma`` to only calls to methods call ``equals``. |
107
+
||||
108
+
||| ``ma.getArgument(0).(StringLiteral).getValue() = ""`` says the argument must be literal ``""``. |
| ``select ma, "This comparison to empty string is inefficient, use isEmpty() instead."`` | Defines what to report for each match. | Reports the resulting ``.equals`` expression with a string that explains the problem. |
111
+
||||
112
+
|| ``select`` statements for queries that are used to find instances of poor coding practice are always in the form: ||
@@ -104,41 +121,38 @@ Query writing is an inherently iterative process. You write a simple query and t
104
121
Remove false positive results
105
122
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
106
123
107
-
Browsing the results of our basic query shows that it could be improved. Among the results you are likely to find examples of ``if`` statements with an ``else`` branch, where an empty ``then`` branch does serve a purpose. For example:
124
+
Browsing the results of our basic query shows that it could be improved. For example, you may find results for code like:
108
125
109
126
.. code-block:: java
110
127
111
-
if (...) {
112
-
...
113
-
} elseif ("-verbose".equals(option)) {
114
-
// nothing to do - handled earlier
115
-
} else {
116
-
error("unrecognized option");
117
-
}
118
-
119
-
In this case, identifying the ``if`` statement with the empty ``then`` branch as redundant is a false positive. One solution to this is to modify the query to ignore empty ``then`` branches if the ``if`` statement has an ``else`` branch.
128
+
publicclassTestJava {
129
+
voidmyJavaFun(Objecto) {
130
+
boolean b = o.equals("");
131
+
}
132
+
}
120
133
121
-
To exclude ``if`` statements that have an ``else`` branch:
134
+
In this case, it is not possible to simply use ``o.isEmpty()`` instead, as ``o`` has type ``Object`` rather than ``String``. One solution to this is to modify the query to only return results where the expression being tested has type ``String``:
122
135
123
136
#. Extend the where clause to include the following extra condition:
124
137
125
138
.. code-block:: ql
126
139
127
-
and not exists(ifstmt.getElse())
140
+
ma.getQualifier().getType() instanceof TypeString
128
141
129
142
The ``where`` clause is now:
130
143
131
144
.. code-block:: ql
132
145
133
-
where ifstmt.getThen() = block and
134
-
block.getNumStmt() = 0 and
135
-
not exists(ifstmt.getElse())
146
+
where
147
+
ma.getQualifier().getType() instanceof TypeString and
148
+
ma.getMethod().hasName("equals") and
149
+
ma.getArgument(0).(StringLiteral).getValue() = ""
136
150
137
151
#. Click **Run**.
138
152
139
-
There are now fewer results because ``if`` statements with an ``else`` branch are no longer included.
153
+
There are now fewer results because ``.equals`` expressions with different types are no longer included.
140
154
141
-
➤ `See this in the query console <https://lgtm.com/query/2005778170075484819/>`__
155
+
➤ `See this in the query console <https://lgtm.com/query/3716567543394265485/>`__
0 commit comments