mirror of
https://github.com/github/codeql.git
synced 2026-04-25 08:45:14 +02:00
Fix trailing whitespace in docs
This commit is contained in:
@@ -27,8 +27,8 @@ This example of an extensible predicate for a source is taken from the core Java
|
||||
.. code-block:: ql
|
||||
|
||||
extensible predicate sourceModel(
|
||||
string package, string type, boolean subtypes, string name,
|
||||
string signature, string ext, string output, string kind,
|
||||
string package, string type, boolean subtypes, string name,
|
||||
string signature, string ext, string output, string kind,
|
||||
string provenance
|
||||
);
|
||||
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
|
||||
Modules
|
||||
#######
|
||||
|
||||
Modules provide a way of organizing QL code by grouping together related types, predicates, and other modules.
|
||||
|
||||
You can import modules into other files, which avoids duplication, and helps
|
||||
Modules provide a way of organizing QL code by grouping together related types, predicates, and other modules.
|
||||
|
||||
You can import modules into other files, which avoids duplication, and helps
|
||||
structure your code into more manageable pieces.
|
||||
|
||||
.. _defining-module:
|
||||
@@ -16,7 +16,7 @@ Defining a module
|
||||
*****************
|
||||
|
||||
There are various ways to define modules—here is an example of the simplest way, declaring an
|
||||
:ref:`explicit module <explicit-modules>` named ``Example`` containing
|
||||
:ref:`explicit module <explicit-modules>` named ``Example`` containing
|
||||
a class ``OneTwoThree``:
|
||||
|
||||
.. code-block:: ql
|
||||
@@ -27,17 +27,17 @@ a class ``OneTwoThree``:
|
||||
this = 1 or this = 2 or this = 3
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
The name of a module can be any `identifier <https://codeql.github.com/docs/ql-language-reference/ql-language-specification/#identifiers>`_
|
||||
that starts with an uppercase or lowercase letter.
|
||||
that starts with an uppercase or lowercase letter.
|
||||
|
||||
``.ql`` or ``.qll`` files also implicitly define modules.
|
||||
For more information, see ":ref:`kinds-of-modules`."
|
||||
|
||||
You can also annotate a module. For more information, see of ":ref:`annotations-overview`."
|
||||
|
||||
Note that you can only annotate :ref:`explicit modules <explicit-modules>`.
|
||||
Note that you can only annotate :ref:`explicit modules <explicit-modules>`.
|
||||
File modules cannot be annotated.
|
||||
|
||||
.. _kinds-of-modules:
|
||||
@@ -48,7 +48,7 @@ Kinds of modules
|
||||
File modules
|
||||
============
|
||||
|
||||
Each query file (extension ``.ql``) and library file (extension ``.qll``) implicitly defines
|
||||
Each query file (extension ``.ql``) and library file (extension ``.qll``) implicitly defines
|
||||
a module. The module has the same name as the file, but any spaces in the file name are replaced
|
||||
by underscores (``_``). The contents of the file form the :ref:`body of the module <module-bodies>`.
|
||||
|
||||
@@ -57,7 +57,7 @@ by underscores (``_``). The contents of the file form the :ref:`body of the modu
|
||||
Library modules
|
||||
---------------
|
||||
|
||||
A library module is defined by a ``.qll`` file. It can contain any of the
|
||||
A library module is defined by a ``.qll`` file. It can contain any of the
|
||||
elements listed in :ref:`module-bodies` below, apart from select clauses.
|
||||
|
||||
For example, consider the following QL library:
|
||||
@@ -75,19 +75,19 @@ For example, consider the following QL library:
|
||||
This file defines a library module named ``OneTwoThreeLib``. The body of this module
|
||||
defines the class ``OneTwoThree``.
|
||||
|
||||
.. _query-modules:
|
||||
.. _query-modules:
|
||||
|
||||
Query modules
|
||||
-------------
|
||||
|
||||
A query module is defined by a ``.ql`` file. It can contain any of the elements listed
|
||||
in :ref:`module-bodies` below.
|
||||
A query module is defined by a ``.ql`` file. It can contain any of the elements listed
|
||||
in :ref:`module-bodies` below.
|
||||
|
||||
Query modules are slightly different from other modules:
|
||||
|
||||
- A query module can't be imported.
|
||||
- A query module must have at least one query in its
|
||||
:ref:`namespace <namespaces>`. This is usually a :ref:`select clause <select-clauses>`,
|
||||
- A query module must have at least one query in its
|
||||
:ref:`namespace <namespaces>`. This is usually a :ref:`select clause <select-clauses>`,
|
||||
but can also be a :ref:`query predicate <query-predicates>`.
|
||||
|
||||
For example:
|
||||
@@ -97,7 +97,7 @@ For example:
|
||||
.. code-block:: ql
|
||||
|
||||
import OneTwoThreeLib
|
||||
|
||||
|
||||
from OneTwoThree ott
|
||||
where ott = 1 or ott = 2
|
||||
select ott
|
||||
@@ -110,13 +110,13 @@ This file defines a query module named ``OneTwoQuery``. The body of this module
|
||||
Explicit modules
|
||||
================
|
||||
|
||||
You can also define a module within another module. This is an explicit module definition.
|
||||
You can also define a module within another module. This is an explicit module definition.
|
||||
|
||||
An explicit module is defined with the keyword ``module`` followed by
|
||||
the module name, and then the module body enclosed in braces. It can contain any
|
||||
of the elements listed in ":ref:`module-bodies`" below, apart from select clauses.
|
||||
An explicit module is defined with the keyword ``module`` followed by
|
||||
the module name, and then the module body enclosed in braces. It can contain any
|
||||
of the elements listed in ":ref:`module-bodies`" below, apart from select clauses.
|
||||
|
||||
For example, you could add the following QL snippet to the library file **OneTwoThreeLib.qll**
|
||||
For example, you could add the following QL snippet to the library file **OneTwoThreeLib.qll**
|
||||
defined :ref:`above <library-modules>`:
|
||||
|
||||
.. code-block:: ql
|
||||
@@ -129,7 +129,7 @@ defined :ref:`above <library-modules>`:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
This defines an explicit module named ``M``. The body of this module defines
|
||||
the class ``OneTwo``.
|
||||
|
||||
@@ -226,7 +226,7 @@ Module bodies
|
||||
*************
|
||||
|
||||
The body of a module is the code inside the module definition, for example
|
||||
the class ``OneTwo`` in the :ref:`explicit module <explicit-modules>` ``M``.
|
||||
the class ``OneTwo`` in the :ref:`explicit module <explicit-modules>` ``M``.
|
||||
|
||||
In general, the body of a module can contain the following constructs:
|
||||
|
||||
@@ -243,11 +243,11 @@ In general, the body of a module can contain the following constructs:
|
||||
Importing modules
|
||||
*****************
|
||||
|
||||
The main benefit of storing code in a module is that you can reuse it in other modules.
|
||||
To access the contents of an external module, you can import the module using an
|
||||
The main benefit of storing code in a module is that you can reuse it in other modules.
|
||||
To access the contents of an external module, you can import the module using an
|
||||
:ref:`import statement <import-statements>`.
|
||||
|
||||
When you import a module this brings all the names in its namespace, apart from :ref:`private` names,
|
||||
When you import a module this brings all the names in its namespace, apart from :ref:`private` names,
|
||||
into the :ref:`namespace <namespaces>` of the current module.
|
||||
|
||||
.. _import-statements:
|
||||
@@ -263,7 +263,7 @@ Import statements are used for importing modules. They are of the form:
|
||||
import <module_expression2>
|
||||
|
||||
Import statements are usually listed at the beginning of the module. Each
|
||||
import statement imports one module. You can import multiple modules by
|
||||
import statement imports one module. You can import multiple modules by
|
||||
including multiple import statements (one for each module you want to import).
|
||||
|
||||
An import statement can also be :ref:`annotated <annotations-overview>` with
|
||||
@@ -272,14 +272,14 @@ An import statement can also be :ref:`annotated <annotations-overview>` with
|
||||
only reachable through deprecated imports in a given context then usage of the
|
||||
name in that context will generate deprecation warnings.
|
||||
|
||||
You can import a module under a different name using the ``as`` keyword,
|
||||
You can import a module under a different name using the ``as`` keyword,
|
||||
for example ``import javascript as js``.
|
||||
|
||||
The ``<module_expression>`` itself can be a module name, a selection, or a qualified
|
||||
reference. For more information, see ":ref:`name-resolution`."
|
||||
|
||||
For information about how import statements are looked up, see "`Module resolution <https://codeql.github.com/docs/ql-language-reference/ql-language-specification/#module-resolution>`__"
|
||||
in the QL language specification.
|
||||
in the QL language specification.
|
||||
|
||||
Built-in modules
|
||||
****************
|
||||
@@ -353,7 +353,7 @@ Sets
|
||||
|
||||
The built-in ``InternSets`` module is parameterized by ``Key`` and ``Value`` types
|
||||
and a ``Value getAValue(Key key)`` relation. The module groups the ``Value``
|
||||
column by ``Key`` and creates a set for each group of values related by a key.
|
||||
column by ``Key`` and creates a set for each group of values related by a key.
|
||||
|
||||
The ``InternSets`` module exports a functional ``Set getSet(Key key)`` relation
|
||||
that relates keys with the set of value related to the given key by
|
||||
|
||||
@@ -10,12 +10,12 @@ Types
|
||||
QL is a statically typed language, so each variable must have a declared type.
|
||||
|
||||
A type is a set of values.
|
||||
For example, the type ``int`` is the set of integers.
|
||||
Note that a value can belong to more than one of these sets, which means that it can have more
|
||||
For example, the type ``int`` is the set of integers.
|
||||
Note that a value can belong to more than one of these sets, which means that it can have more
|
||||
than one type.
|
||||
|
||||
The kinds of types in QL are :ref:`primitive types <primitive-types>`, :ref:`classes <classes>`,
|
||||
:ref:`character types <character-types>`, :ref:`class domain types <domain-types>`,
|
||||
:ref:`character types <character-types>`, :ref:`class domain types <domain-types>`,
|
||||
:ref:`algebraic datatypes <algebraic-datatypes>`, :ref:`type unions <type-unions>`,
|
||||
and :ref:`database types <database-types>`.
|
||||
|
||||
@@ -31,23 +31,23 @@ independent of the database that you are querying.
|
||||
.. _boolean:
|
||||
|
||||
#. **boolean**: This type contains the values ``true`` and ``false``.
|
||||
|
||||
|
||||
.. _float:
|
||||
|
||||
#. **float**: This type contains 64-bit floating point numbers, such as ``6.28`` and ``-0.618``.
|
||||
|
||||
|
||||
.. _int:
|
||||
|
||||
#. **int**: This type contains 32-bit `two's complement <https://en.wikipedia.org/wiki/Two%27s_complement>`_ integers, such as ``-1`` and ``42``.
|
||||
|
||||
|
||||
.. _string:
|
||||
|
||||
#. **string**: This type contains finite strings of 16-bit characters.
|
||||
|
||||
|
||||
.. _date:
|
||||
|
||||
#. **date**: This type contains dates (and optionally times).
|
||||
|
||||
#. **date**: This type contains dates (and optionally times).
|
||||
|
||||
|
||||
QL has a range of built-in operations defined on primitive types. These are available by using dispatch on expressions of the appropriate type. For example, ``1.toString()`` is the string representation of the integer constant ``1``. For a full list of built-in operations available in QL, see the
|
||||
section on `built-ins <https://codeql.github.com/docs/ql-language-reference/ql-language-specification/#built-ins>`__ in the QL language specification.
|
||||
@@ -65,7 +65,7 @@ Classes provide an easy way to reuse and structure code. For example, you can:
|
||||
- Define :ref:`member predicates <member-predicates>` on those values.
|
||||
- Define subclasses that :ref:`override member predicates <overriding-member-predicates>`.
|
||||
|
||||
A class in QL doesn't "create" a new object, it just represents a logical property. A value is
|
||||
A class in QL doesn't "create" a new object, it just represents a logical property. A value is
|
||||
in a particular class if it satisfies that logical property.
|
||||
|
||||
.. _defining-a-class:
|
||||
@@ -75,8 +75,8 @@ Defining a class
|
||||
|
||||
To define a class, you write:
|
||||
|
||||
#. The keyword ``class``.
|
||||
#. The name of the class. This is an `identifier <https://codeql.github.com/docs/ql-language-reference/ql-language-specification/#identifiers>`_
|
||||
#. The keyword ``class``.
|
||||
#. The name of the class. This is an `identifier <https://codeql.github.com/docs/ql-language-reference/ql-language-specification/#identifiers>`_
|
||||
starting with an uppercase letter.
|
||||
#. The supertypes that the class is derived from via `extends` and/or `instanceof`
|
||||
#. The :ref:`body of the class <class-bodies>`, enclosed in braces.
|
||||
@@ -89,11 +89,11 @@ For example:
|
||||
OneTwoThree() { // characteristic predicate
|
||||
this = 1 or this = 2 or this = 3
|
||||
}
|
||||
|
||||
|
||||
string getAString() { // member predicate
|
||||
result = "One, two or three: " + this.toString()
|
||||
}
|
||||
|
||||
|
||||
predicate isEven() { // member predicate
|
||||
this = 2
|
||||
}
|
||||
@@ -101,7 +101,7 @@ For example:
|
||||
|
||||
This defines a class ``OneTwoThree``, which contains the values ``1``, ``2``, and ``3``. The
|
||||
:ref:`characteristic predicate <characteristic-predicates>` captures the logical property of
|
||||
"being one of the integers 1, 2, or 3."
|
||||
"being one of the integers 1, 2, or 3."
|
||||
|
||||
.. index:: extends
|
||||
|
||||
@@ -132,12 +132,12 @@ Class bodies
|
||||
The body of a class can contain:
|
||||
- A :ref:`characteristic predicate <characteristic-predicates>` declaration.
|
||||
- Any number of :ref:`member predicate <member-predicates>` declarations.
|
||||
- Any number of :ref:`field <fields>` declarations.
|
||||
- Any number of :ref:`field <fields>` declarations.
|
||||
|
||||
When you define a class, that class also inherits all non-:ref:`private` member predicates and
|
||||
fields from its supertypes.
|
||||
|
||||
Depending on whether they are final, you can :ref:`override <overriding-member-predicates>` or
|
||||
Depending on whether they are final, you can :ref:`override <overriding-member-predicates>` or
|
||||
:ref:`shadow <final-extensions>` those predicates and fields to give them a more specific definition.
|
||||
|
||||
.. _characteristic-predicates:
|
||||
@@ -181,22 +181,22 @@ This call returns ``"ONE, TWO OR THREE: 1"``.
|
||||
|
||||
.. pull-quote:: Note
|
||||
|
||||
Characteristic predicates and member predicates often use the variable ``this``.
|
||||
This variable always refers to a member of the class—in this case a value belonging to the
|
||||
Characteristic predicates and member predicates often use the variable ``this``.
|
||||
This variable always refers to a member of the class—in this case a value belonging to the
|
||||
class ``OneTwoThree``.
|
||||
In the :ref:`characteristic predicate <characteristic-predicates>`, the variable ``this``
|
||||
In the :ref:`characteristic predicate <characteristic-predicates>`, the variable ``this``
|
||||
constrains the values that are in the class.
|
||||
In a :ref:`member predicate <member-predicates>`, ``this`` acts in the same way as any
|
||||
In a :ref:`member predicate <member-predicates>`, ``this`` acts in the same way as any
|
||||
other argument to the predicate.
|
||||
|
||||
.. index:: field
|
||||
.. _fields:
|
||||
.. _fields:
|
||||
|
||||
Fields
|
||||
------
|
||||
|
||||
These are variables declared in the body of a class. A class can have any number of field
|
||||
declarations (that is, variable declarations) within its body. You can use these variables in
|
||||
declarations (that is, variable declarations) within its body. You can use these variables in
|
||||
predicate declarations inside the class. Much like the :ref:`variable <this>` ``this``, fields
|
||||
must be constrained in the :ref:`characteristic predicate <characteristic-predicates>`.
|
||||
|
||||
@@ -207,21 +207,21 @@ For example:
|
||||
class SmallInt extends int {
|
||||
SmallInt() { this = [1 .. 10] }
|
||||
}
|
||||
|
||||
|
||||
class DivisibleInt extends SmallInt {
|
||||
SmallInt divisor; // declaration of the field `divisor`
|
||||
DivisibleInt() { this % divisor = 0 }
|
||||
|
||||
|
||||
SmallInt getADivisor() { result = divisor }
|
||||
}
|
||||
|
||||
|
||||
from DivisibleInt i
|
||||
select i, i.getADivisor()
|
||||
|
||||
In this example, the declaration ``SmallInt divisor`` introduces a field ``divisor``, constrains
|
||||
it in the characteristic predicate, and then uses it in the declaration of the member predicate
|
||||
``getADivisor``. This is similar to introducing variables in a :ref:`select clause <select-clauses>`
|
||||
by declaring them in the ``from`` part.
|
||||
by declaring them in the ``from`` part.
|
||||
|
||||
You can also annotate predicates and fields. See the list of :ref:`annotations <annotations-overview>`
|
||||
that are available.
|
||||
@@ -231,7 +231,7 @@ that are available.
|
||||
Concrete classes
|
||||
================
|
||||
|
||||
The classes in the above examples are all **concrete** classes. They are defined by
|
||||
The classes in the above examples are all **concrete** classes. They are defined by
|
||||
restricting the values in a larger type. The values in a concrete class are precisely those
|
||||
values in the intersection of the supertypes that also satisfy the
|
||||
:ref:`characteristic predicate <characteristic-predicates>` of the class.
|
||||
@@ -241,32 +241,32 @@ values in the intersection of the supertypes that also satisfy the
|
||||
Abstract classes
|
||||
================
|
||||
|
||||
A class :ref:`annotated <abstract>` with ``abstract``, known as an **abstract** class, is also a restriction of
|
||||
the values in a larger type. However, an abstract class is defined as the union of its
|
||||
subclasses. In particular, for a value to be in an abstract class, it must satisfy the
|
||||
A class :ref:`annotated <abstract>` with ``abstract``, known as an **abstract** class, is also a restriction of
|
||||
the values in a larger type. However, an abstract class is defined as the union of its
|
||||
subclasses. In particular, for a value to be in an abstract class, it must satisfy the
|
||||
characteristic predicate of the class itself **and** the characteristic predicate of a subclass.
|
||||
Note that final extensions are not considered subclasses in this context.
|
||||
|
||||
An abstract class is useful if you want to group multiple existing classes together
|
||||
under a common name. You can then define member predicates on all those classes. You can also
|
||||
extend predefined abstract classes: for example, if you import a library that contains an
|
||||
An abstract class is useful if you want to group multiple existing classes together
|
||||
under a common name. You can then define member predicates on all those classes. You can also
|
||||
extend predefined abstract classes: for example, if you import a library that contains an
|
||||
abstract class, you can add more subclasses to it.
|
||||
|
||||
**Example**
|
||||
|
||||
If you are writing a security query, you may be interested in identifying
|
||||
all expressions that can be interpreted as SQL queries.
|
||||
If you are writing a security query, you may be interested in identifying
|
||||
all expressions that can be interpreted as SQL queries.
|
||||
You can use the following abstract class to describe these expressions:
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
abstract class SqlExpr extends Expr {
|
||||
...
|
||||
...
|
||||
}
|
||||
|
||||
Now define various subclasses—one for each kind of database management system. For example, you
|
||||
can define a subclass ``class PostgresSqlExpr extends SqlExpr``, which contains expressions
|
||||
passed to some Postgres API that performs a database query.
|
||||
can define a subclass ``class PostgresSqlExpr extends SqlExpr``, which contains expressions
|
||||
passed to some Postgres API that performs a database query.
|
||||
You can define similar subclasses for MySQL and other database management systems.
|
||||
|
||||
The abstract class ``SqlExpr`` refers to all of those different expressions. If you want to add
|
||||
@@ -278,7 +278,7 @@ there is no need to update the queries that rely on it.
|
||||
|
||||
You must take care when you add a new subclass to an existing abstract class. Adding a subclass
|
||||
is not an isolated change, it also extends the abstract class since that is a union of its
|
||||
subclasses.
|
||||
subclasses.
|
||||
|
||||
.. _overriding-member-predicates:
|
||||
|
||||
@@ -288,7 +288,7 @@ Overriding member predicates
|
||||
If a class inherits a member predicate from a non-final supertype, you can **override** the
|
||||
inherited definition. You do this by defining a member predicate with the same name and arity
|
||||
as the inherited predicate, and by adding the ``override`` :ref:`annotation <override>`.
|
||||
This is useful if you want to refine the predicate to give a more specific result for the
|
||||
This is useful if you want to refine the predicate to give a more specific result for the
|
||||
values in the subclass.
|
||||
|
||||
For example, extending the class from the :ref:`first example <defining-a-class>`:
|
||||
@@ -299,7 +299,7 @@ For example, extending the class from the :ref:`first example <defining-a-class>
|
||||
OneTwo() {
|
||||
this = 1 or this = 2
|
||||
}
|
||||
|
||||
|
||||
override string getAString() {
|
||||
result = "One or two: " + this.toString()
|
||||
}
|
||||
@@ -328,7 +328,7 @@ look like this:
|
||||
| 3 | One, two or three: 3 |
|
||||
+---+-------------------------+
|
||||
|
||||
In QL, unlike other object-oriented languages, different subtypes of the same types don't need to be
|
||||
In QL, unlike other object-oriented languages, different subtypes of the same types don't need to be
|
||||
disjoint. For example, you could define another subclass of ``OneTwoThree``, which overlaps
|
||||
with ``OneTwo``:
|
||||
|
||||
@@ -338,14 +338,14 @@ with ``OneTwo``:
|
||||
TwoThree() {
|
||||
this = 2 or this = 3
|
||||
}
|
||||
|
||||
|
||||
override string getAString() {
|
||||
result = "Two or three: " + this.toString()
|
||||
}
|
||||
}
|
||||
|
||||
Now the value 2 is included in both class types ``OneTwo`` and ``TwoThree``. Both of these classes
|
||||
override the original definition of ``getAString()``. There are two new "most specific" definitions,
|
||||
Now the value 2 is included in both class types ``OneTwo`` and ``TwoThree``. Both of these classes
|
||||
override the original definition of ``getAString()``. There are two new "most specific" definitions,
|
||||
so running the above query gives the following results:
|
||||
|
||||
+---+-------------------------+
|
||||
@@ -373,7 +373,7 @@ For example, using the definitions from the above section:
|
||||
|
||||
class Two extends OneTwo, TwoThree {}
|
||||
|
||||
Any value in the class ``Two`` must satisfy the logical property represented by ``OneTwo``,
|
||||
Any value in the class ``Two`` must satisfy the logical property represented by ``OneTwo``,
|
||||
**and** the logical property represented by ``TwoThree``. Here the class ``Two`` contains one
|
||||
value, namely 2.
|
||||
|
||||
@@ -401,12 +401,12 @@ For example, extending the class from the :ref:`first example <defining-a-class>
|
||||
.. code-block:: ql
|
||||
|
||||
final class FinalOneTwoThree = OneTwoThree;
|
||||
|
||||
|
||||
class OneTwoFinalExtension extends FinalOneTwoThree {
|
||||
OneTwoFinalExtension() {
|
||||
this = 1 or this = 2
|
||||
}
|
||||
|
||||
|
||||
string getAString() {
|
||||
result = "One or two: " + this.toString()
|
||||
}
|
||||
@@ -507,19 +507,19 @@ Had ``Bar`` been defined as ``extends Foo``, then ``select any(Foo f).foo()`` wo
|
||||
Character types and class domain types
|
||||
**************************************
|
||||
|
||||
You can't refer to these types directly, but each class in QL implicitly defines a character
|
||||
type and a class domain type. (These are rather more subtle concepts and don't appear very
|
||||
You can't refer to these types directly, but each class in QL implicitly defines a character
|
||||
type and a class domain type. (These are rather more subtle concepts and don't appear very
|
||||
often in practical query writing.)
|
||||
|
||||
The **character type** of a QL class is the set of values satisfying the :ref:`characteristic
|
||||
predicate <characteristic-predicates>` of the class.
|
||||
It is a subset of the domain type. For concrete classes, a value belongs to
|
||||
the class if, and only if, it is in the character type. For :ref:`abstract classes
|
||||
The **character type** of a QL class is the set of values satisfying the :ref:`characteristic
|
||||
predicate <characteristic-predicates>` of the class.
|
||||
It is a subset of the domain type. For concrete classes, a value belongs to
|
||||
the class if, and only if, it is in the character type. For :ref:`abstract classes
|
||||
<abstract-classes>`, a value must also belong to at least one of the subclasses, in addition to
|
||||
being in the character type.
|
||||
being in the character type.
|
||||
|
||||
The **domain type** of a QL class is the intersection of the character types of all its supertypes, that is, a value
|
||||
belongs to the domain type if it belongs to every supertype. It occurs as the type of ``this``
|
||||
belongs to the domain type if it belongs to every supertype. It occurs as the type of ``this``
|
||||
in the characteristic predicate of a class.
|
||||
|
||||
.. index:: newtype
|
||||
@@ -570,13 +570,13 @@ The branch definitions have the following form:
|
||||
|
||||
<BranchName>(<arguments>) { <body> }
|
||||
|
||||
- The type name and the branch names must be `identifiers <https://codeql.github.com/docs/ql-language-reference/ql-language-specification/#identifiers>`_
|
||||
- The type name and the branch names must be `identifiers <https://codeql.github.com/docs/ql-language-reference/ql-language-specification/#identifiers>`_
|
||||
starting with an uppercase letter. Conventionally, they start with ``T``.
|
||||
- The different branches of an algebraic datatype are separated by ``or``.
|
||||
- The arguments to a branch, if any, are :ref:`variable declarations <variable-declarations>`
|
||||
separated by commas.
|
||||
- The body of a branch is a :ref:`predicate <predicates>` body. You can omit the branch body, in which case
|
||||
it defaults to ``any()``.
|
||||
it defaults to ``any()``.
|
||||
Note that branch bodies are evaluated fully, so they must be finite. They should be kept small
|
||||
for good performance.
|
||||
|
||||
@@ -586,28 +586,28 @@ For example, the following algebraic datatype has three branches:
|
||||
|
||||
newtype T =
|
||||
Type1(A a, B b) { body(a, b) }
|
||||
or
|
||||
or
|
||||
Type2(C c)
|
||||
or
|
||||
or
|
||||
Type3()
|
||||
|
||||
Standard pattern for using algebraic datatypes
|
||||
==============================================
|
||||
|
||||
Algebraic datatypes are different from :ref:`classes <classes>`. In particular, algebraic datatypes don't have a
|
||||
Algebraic datatypes are different from :ref:`classes <classes>`. In particular, algebraic datatypes don't have a
|
||||
``toString()`` member predicate, so you can't use them in a :ref:`select clause <select-clauses>`.
|
||||
|
||||
Classes are often used to extend algebraic datatypes (and to provide a ``toString()`` predicate).
|
||||
Classes are often used to extend algebraic datatypes (and to provide a ``toString()`` predicate).
|
||||
In the standard QL language libraries, this is usually done as follows:
|
||||
|
||||
- Define a class ``A`` that extends the algebraic datatype and optionally declares :ref:`abstract`
|
||||
predicates.
|
||||
- For each branch type, define a class ``B`` that extends both ``A`` and the branch type,
|
||||
- For each branch type, define a class ``B`` that extends both ``A`` and the branch type,
|
||||
and provide a definition for any abstract predicates from ``A``.
|
||||
- Annotate the algebraic datatype with :ref:`private`, and leave the classes public.
|
||||
|
||||
For example, the following code snippet from the CodeQL data-flow library for C# defines classes
|
||||
for dealing with tainted or untainted values. In this case, it doesn't make sense for
|
||||
for dealing with tainted or untainted values. In this case, it doesn't make sense for
|
||||
``TaintType`` to extend a database type. It is part of the taint analysis, not the underlying
|
||||
program, so it's helpful to extend a new type (namely ``TTaintType``):
|
||||
|
||||
@@ -617,24 +617,24 @@ program, so it's helpful to extend a new type (namely ``TTaintType``):
|
||||
TExactValue()
|
||||
or
|
||||
TTaintedValue()
|
||||
|
||||
|
||||
/** Describes how data is tainted. */
|
||||
class TaintType extends TTaintType {
|
||||
string toString() {
|
||||
this = TExactValue() and result = "exact"
|
||||
or
|
||||
or
|
||||
this = TTaintedValue() and result = "tainted"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** A taint type where the data is untainted. */
|
||||
class Untainted extends TaintType, TExactValue {
|
||||
}
|
||||
|
||||
|
||||
/** A taint type where the data is tainted. */
|
||||
class Tainted extends TaintType, TTaintedValue {
|
||||
}
|
||||
|
||||
|
||||
.. _type-unions:
|
||||
|
||||
Type unions
|
||||
@@ -672,7 +672,7 @@ If we had implemented ``DefiniteInitialization`` as a class extension instead, i
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
// THIS WON'T WORK: The implicit type check for InitialValueSource involves an illegal recursion
|
||||
// THIS WON'T WORK: The implicit type check for InitialValueSource involves an illegal recursion
|
||||
// DefiniteInitialization -> InitialValueSource -> UnknownInitialGarbage -> ¬DefiniteInitialization!
|
||||
class DefiniteInitialization extends InitialValueSource {
|
||||
DefiniteInitialization() {
|
||||
@@ -692,7 +692,7 @@ Database types are defined in the database schema. This means that they depend o
|
||||
that you are querying, and vary according to the data you are analyzing.
|
||||
|
||||
For example, if you are querying a CodeQL database for a Java project, the database types may
|
||||
include ``@ifstmt``, representing an if statement in the Java code, and ``@variable``,
|
||||
include ``@ifstmt``, representing an if statement in the Java code, and ``@variable``,
|
||||
representing a variable.
|
||||
|
||||
.. _type-compatibility:
|
||||
|
||||
Reference in New Issue
Block a user