-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Rust: Add Basic query for Rust code doc #20561
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
+135
−0
Merged
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
f4758fe
Rust: Add a basic-query-for-rust-code.rst (copied from Swift).
geoffw0 1211dc8
Rust: Replace 'swift' with 'rust'.
geoffw0 db3d177
Rust: Port the code examples to Rust / CodeQL for Rust.
geoffw0 dba4b5e
Rust: Add images.
geoffw0 771d934
Merge branch 'main' into basicquery
geoffw0 92122fe
Rust: statement -> expression.
geoffw0 513dcf1
Merge branch 'main' into basicquery
subatoi 2c7291d
Rust: Fix toctree bug.
geoffw0 936702a
Rust: Update graphics.
geoffw0 b02c19b
Rust: Slightly cleaner screenshots.
geoffw0 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
131 changes: 131 additions & 0 deletions
131
docs/codeql/codeql-language-guides/basic-query-for-rust-code.rst
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
.. _basic-query-for-rust-code: | ||
|
||
Basic query for Rust code | ||
========================== | ||
|
||
Learn to write and run a simple CodeQL query using Visual Studio Code with the CodeQL extension. | ||
|
||
.. include:: ../reusables/vs-code-basic-instructions/setup-to-run-queries.rst | ||
|
||
About the query | ||
--------------- | ||
|
||
The query we're going to run performs a basic search of the code for ``if`` expressions that are redundant, in the sense that they have an empty ``then`` branch. For example, code such as: | ||
|
||
.. code-block:: rust | ||
|
||
if error { | ||
// we should handle the error | ||
} | ||
|
||
.. include:: ../reusables/vs-code-basic-instructions/find-database.rst | ||
|
||
Running a quick query | ||
--------------------- | ||
|
||
.. include:: ../reusables/vs-code-basic-instructions/run-quick-query-1.rst | ||
|
||
#. In the quick query tab, delete the content and paste in the following query. | ||
|
||
.. code-block:: ql | ||
|
||
import rust | ||
|
||
from IfExpr ifExpr | ||
where ifExpr.getThen().(BlockExpr).getStmtList().getNumberOfStmtOrExpr() = 0 | ||
select ifExpr, "This 'if' expression is redundant." | ||
|
||
.. include:: ../reusables/vs-code-basic-instructions/run-quick-query-2.rst | ||
|
||
.. image:: ../images/codeql-for-visual-studio-code/basic-rust-query-results-1.png | ||
:align: center | ||
|
||
If any matching code is found, click a link in the ``ifExpr`` column to open the file and highlight the matching ``if`` expression. | ||
|
||
.. image:: ../images/codeql-for-visual-studio-code/basic-rust-query-results-2.png | ||
:align: center | ||
|
||
.. include:: ../reusables/vs-code-basic-instructions/note-store-quick-query.rst | ||
|
||
About the query structure | ||
~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
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. | ||
|
||
+----------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------+ | ||
| Query part | Purpose | Details | | ||
+==================================================================================+===================================================================================================================+======================================================================================================+ | ||
| ``import rust`` | Imports the standard CodeQL AST libraries for Rust. | Every query begins with one or more ``import`` statements. | | ||
+----------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------+ | ||
| ``from IfExpr ifExpr`` | Defines the variables for the query. | We use: an ``IfExpr`` variable for ``if`` expressions. | | ||
| | Declarations are of the form: | | | ||
| | ``<type> <variable name>`` | | | ||
+----------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------+ | ||
| ``where ifExpr.getThen().(BlockExpr).getStmtList().getNumberOfStmtOrExpr() = 0`` | Defines a condition on the variables. | ``ifExpr.getThen()``: gets the ``then`` branch of the ``if`` expression. | | ||
| | | ``.(BlockExpr)``: requires that the ``then`` branch is a block expression (``{ }``). | | ||
| | | ``.getStmtList()``: gets the list of things in the block. | | ||
| | | ``.getNumberOfStmtOrExpr() = 0``: requires that there are no statements or expressions in the block. | | ||
+----------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------+ | ||
| ``select ifExpr, "This 'if' expression is redundant."`` | Defines what to report for each match. | Reports the resulting ``if`` expression with a string that explains the problem. | | ||
| | | | | ||
| | ``select`` statements for queries that are used to find instances of poor coding practice are always in the form: | | | ||
| | ``select <program element>, "<alert message>"`` | | | ||
+----------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------+ | ||
|
||
Extend the query | ||
---------------- | ||
|
||
Query writing is an inherently iterative process. You write a simple query and then, when you run it, you discover examples that you had not previously considered, or opportunities for improvement. | ||
|
||
Remove false positive results | ||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
Browsing the results of our basic query shows that it could be improved. Among the results you are likely to find examples of ``if`` expressions with an ``else`` branch, where an empty ``then`` branch does serve a purpose. For example: | ||
|
||
.. code-block:: rust | ||
|
||
if (option == "-verbose") { | ||
// nothing to do - handled earlier | ||
} else { | ||
handleError("unrecognized option") | ||
} | ||
|
||
In this case, identifying the ``if`` expression with the empty ``then`` branch as redundant is a false positive. One solution to this is to modify the query to select ``if`` expressions where both the ``then`` and ``else`` branches are missing. | ||
|
||
To exclude ``if`` expressions that have an ``else`` branch: | ||
|
||
#. Add the following to the where clause: | ||
|
||
.. code-block:: ql | ||
|
||
and not exists(ifExpr.getElse()) | ||
|
||
The ``where`` clause is now: | ||
|
||
.. code-block:: ql | ||
|
||
where | ||
ifExpr.getThen().(BlockExpr).getStmtList().getNumberOfStmtOrExpr() = 0 and | ||
not exists(ifExpr.getElse()) | ||
|
||
#. Re-run the query. | ||
|
||
There are now fewer results because ``if`` expressions with an ``else`` branch are no longer included. | ||
|
||
Further reading | ||
--------------- | ||
|
||
.. include:: ../reusables/rust-further-reading.rst | ||
.. include:: ../reusables/codeql-ref-tools-further-reading.rst | ||
|
||
.. Article-specific substitutions for the reusables used in docs/codeql/reusables/vs-code-basic-instructions | ||
|
||
.. |language-text| replace:: Rust | ||
|
||
.. |language-code| replace:: ``rust`` | ||
|
||
.. |example-url| replace:: https://github.com/rust-lang/rustlings | ||
|
||
.. |image-quick-query| image:: ../images/codeql-for-visual-studio-code/quick-query-tab-rust.png | ||
|
||
.. |result-col-1| replace:: The first column corresponds to the expression ``ifExpr`` and is linked to the location in the source code of the project where ``ifExpr`` occurs. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file added
BIN
+32.5 KB
docs/codeql/images/codeql-for-visual-studio-code/basic-rust-query-results-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+32.3 KB
docs/codeql/images/codeql-for-visual-studio-code/basic-rust-query-results-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+9.1 KB
docs/codeql/images/codeql-for-visual-studio-code/quick-query-tab-rust.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error message refers to 'if' expression, but line 36 uses 'if' statement. The terminology should be consistent - use 'if' expression in both places since Rust treats
if
as an expression.Copilot uses AI. Check for mistakes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, though it's line 36 that should be updated - they're if "expressions" in Rust.
Updated the doc.
I'll need to re-create the screenshots as well, but lets wait and see if any other changes are suggested first...