Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 25 additions & 23 deletions docs/language/learn-ql/java/annotations.rst
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
Tutorial: Annotations
=====================

Overview
--------
Annotations in Java
===================

CodeQL databases of Java projects contain information about all annotations attached to program elements.

Annotations are represented by the following CodeQL classes:
About working with annotations
------------------------------

Annotations are represented by these CodeQL classes:

- The class ``Annotatable`` represents all entities that may have an annotation attached to them (that is, packages, reference types, fields, methods, and local variables).
- The class ``AnnotationType`` represents a Java annotation type, such as ``java.lang.Override``; annotation types are interfaces.
- The class ``AnnotationElement`` represents an annotation element, that is, a member of an annotation type.
- The class ``Annotation`` represents an annotation such as ``@Override``; annotation values can be accessed through member predicate ``getValue``.

As an example, recall that the Java standard library defines an annotation ``SuppressWarnings`` that instructs the compiler not to emit certain kinds of warnings. It is defined as follows:
For example, the Java standard library defines an annotation ``SuppressWarnings`` that instructs the compiler not to emit certain kinds of warnings:

.. code-block:: java

Expand All @@ -25,7 +25,7 @@ As an example, recall that the Java standard library defines an annotation ``Sup

``SuppressWarnings`` is represented as an ``AnnotationType``, with ``value`` as its only ``AnnotationElement``.

A typical usage of ``SuppressWarnings`` would be the following annotation to prevent a warning about using raw types:
A typical usage of ``SuppressWarnings`` would be this annotation for preventing a warning about using raw types:

.. code-block:: java

Expand All @@ -37,7 +37,7 @@ A typical usage of ``SuppressWarnings`` would be the following annotation to pre

The expression ``@SuppressWarnings("rawtypes")`` is represented as an ``Annotation``. The string literal ``"rawtypes"`` is used to initialize the annotation element ``value``, and its value can be extracted from the annotation by means of the ``getValue`` predicate.

We could then write the following query to find all ``@SuppressWarnings`` annotations attached to constructors, and return both the annotation itself and the value of its ``value`` element:
We could then write this query to find all ``@SuppressWarnings`` annotations attached to constructors, and return both the annotation itself and the value of its ``value`` element:

.. code-block:: ql

Expand Down Expand Up @@ -69,9 +69,9 @@ As another example, this query finds all annotation types that only have a singl
Example: Finding missing ``@Override`` annotations
--------------------------------------------------

In newer versions of Java, it is recommended (though not required) to annotate methods that override another method with an ``@Override`` annotation. These annotations, which are checked by the compiler, serve as documentation, and also help you avoid accidental overloading where overriding was intended.
In newer versions of Java, it's recommended (though not required) that you annotate methods that override another method with an ``@Override`` annotation. These annotations, which are checked by the compiler, serve as documentation, and also help you avoid accidental overloading where overriding was intended.

For example, consider the following example program:
For example, consider this example program:

.. code-block:: java

Expand All @@ -89,9 +89,9 @@ For example, consider the following example program:

Here, both ``Sub1.m`` and ``Sub2.m`` override ``Super.m``, but only ``Sub1.m`` is annotated with ``@Override``.

We will now develop a query for finding methods like ``Sub2.m`` that should be annotated with ``@Override``, but are not.
We'll now develop a query for finding methods like ``Sub2.m`` that should be annotated with ``@Override``, but are not.

As a first step, let us write a query that finds all ``@Override`` annotations. Annotations are expressions, so their type can be accessed using ``getType``. Annotation types, on the other hand, are interfaces, so their qualified name can be queried using ``hasQualifiedName``. Therefore we can implement the query as follows:
As a first step, let's write a query that finds all ``@Override`` annotations. Annotations are expressions, so their type can be accessed using ``getType``. Annotation types, on the other hand, are interfaces, so their qualified name can be queried using ``hasQualifiedName``. Therefore we can implement the query like this:

.. code-block:: ql

Expand All @@ -111,7 +111,7 @@ As always, it is a good idea to try this query on a CodeQL database for a Java p
}
}

This makes it very easy to write our query for finding methods that override another method, but do not have an ``@Override`` annotation: we use predicate ``overrides`` to find out whether one method overrides another, and predicate ``getAnAnnotation`` (available on any ``Annotatable``) to retrieve some annotation.
This makes it very easy to write our query for finding methods that override another method, but don't have an ``@Override`` annotation: we use predicate ``overrides`` to find out whether one method overrides another, and predicate ``getAnAnnotation`` (available on any ``Annotatable``) to retrieve some annotation.

.. code-block:: ql

Expand All @@ -122,14 +122,14 @@ This makes it very easy to write our query for finding methods that override ano
not overriding.getAnAnnotation() instanceof OverrideAnnotation
select overriding, "Method overrides another method, but does not have an @Override annotation."

➤ `See this in the query console <https://lgtm.com/query/1505752756202/>`__. In practice, this query may yield many results from compiled library code, which are not very interesting. Therefore, it is a good idea to add another conjunct ``overriding.fromSource()`` to restrict the result to only report methods for which source code is available.
➤ `See this in the query console <https://lgtm.com/query/1505752756202/>`__. In practice, this query may yield many results from compiled library code, which aren't very interesting. It's therefore a good idea to add another conjunct ``overriding.fromSource()`` to restrict the result to only report methods for which source code is available.

Example: Finding calls to deprecated methods
--------------------------------------------

As another example, we can write a query that finds calls to methods marked with a ``@Deprecated`` annotation.

For example, consider the following example program:
For example, consider this example program:

.. code-block:: java

Expand All @@ -147,7 +147,7 @@ For example, consider the following example program:

Here, both ``A.m`` and ``A.n`` are marked as deprecated. Methods ``n`` and ``r`` both call ``m``, but note that ``n`` itself is deprecated, so we probably should not warn about this call.

Like in the previous example, we start by defining a class for representing ``@Deprecated`` annotations:
As in the previous example, we'll start by defining a class for representing ``@Deprecated`` annotations:

.. code-block:: ql

Expand All @@ -167,7 +167,7 @@ Now we can define a class for representing deprecated methods:
}
}

Finally, we use these classes to find calls to deprecated methods, excluding calls that themselves appear in deprecated methods (see :doc:`Tutorial: Navigating the call graph <call-graph>` for more information on class ``Call``):
Finally, we use these classes to find calls to deprecated methods, excluding calls that themselves appear in deprecated methods:

.. code-block:: ql

Expand All @@ -178,7 +178,9 @@ Finally, we use these classes to find calls to deprecated methods, excluding cal
and not call.getCaller() instanceof DeprecatedMethod
select call, "This call invokes a deprecated method."

On our example, this query flags the call to ``A.m`` in ``A.r``, but not the one in ``A.n``.
In our example, this query flags the call to ``A.m`` in ``A.r``, but not the one in ``A.n``.

For more information about the class ``Call``, see :doc:`Navigating the call graph <call-graph>`.

Improvements
~~~~~~~~~~~~
Expand Down Expand Up @@ -235,9 +237,9 @@ Now we can extend our query to filter out calls in methods carrying a ``Suppress

➤ `See this in the query console <https://lgtm.com/query/665760001>`__. It's fairly common for projects to contain calls to methods that appear to be deprecated.

What next?
----------
Further reading
---------------

- Take a look at some of the other tutorials: :doc:`Tutorial: Javadoc <javadoc>` and :doc:`Tutorial: Working with source locations <source-locations>`.
- Find out how specific classes in the AST are represented in the standard library for Java: :doc:`AST class reference <ast-class-reference>`.
- Take a look at some of the other articles in this section: :doc:`Javadoc <javadoc>` and :doc:`Working with source locations <source-locations>`.
- Find out how specific classes in the AST are represented in the standard library for Java: :doc:`Classes for working with Java code <ast-class-reference>`.
- Find out more about QL in the `QL language handbook <https://help.semmle.com/QL/ql-handbook/index.html>`__ and `QL language specification <https://help.semmle.com/QL/ql-spec/language.html>`__.
6 changes: 4 additions & 2 deletions docs/language/learn-ql/java/ast-class-reference.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
AST class reference
===================
Classes for working with Java code
==================================

CodeQL has a large selection of classes for working with Java statements and expressions.

.. _Expr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$Expr.html
.. _Stmt: https://help.semmle.com/qldoc/java/semmle/code/java/Statement.qll/type.Statement$Stmt.html
Expand Down
26 changes: 14 additions & 12 deletions docs/language/learn-ql/java/call-graph.rst
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
Tutorial: Navigating the call graph
===================================
Navigating the call graph
=========================

Call graph API
--------------
CodeQL has classes for identifying code that calls other code, and code that can be called from elsewhere. This allows you to find, for example, methods that are never used.

Call graph classes
------------------

The CodeQL library for Java provides two abstract classes for representing a program's call graph: ``Callable`` and ``Call``. The former is simply the common superclass of ``Method`` and ``Constructor``, the latter is a common superclass of ``MethodAccess``, ``ClassInstanceExpression``, ``ThisConstructorInvocationStmt`` and ``SuperConstructorInvocationStmt``. Simply put, a ``Callable`` is something that can be invoked, and a ``Call`` is something that invokes a ``Callable``.

Expand Down Expand Up @@ -56,7 +58,7 @@ Class ``Call`` provides two call graph navigation predicates:

For instance, in our example ``getCallee`` of the second call in ``Client.main`` would return ``Super.getX``. At runtime, though, this call would actually invoke ``Sub.getX``.

Class ``Callable`` defines a large number of member predicates; for our purposes, the two most important ones are as follows:
Class ``Callable`` defines a large number of member predicates; for our purposes, the two most important ones are:

- ``calls(Callable target)`` succeeds if this callable contains a call whose callee is ``target``.
- ``polyCalls(Callable target)`` succeeds if this callable may call ``target`` at runtime; this is the case if it contains a call whose callee is either ``target`` or a method that ``target`` overrides.
Expand All @@ -66,7 +68,7 @@ In our example, ``Client.main`` calls the constructor ``Sub(int)`` and the metho
Example: Finding unused methods
-------------------------------

Given this API, we can easily write a query that finds methods that are not called by any other method:
We can use the ``Callable`` class to write a query that finds methods that are not called by any other method:

.. code-block:: ql

Expand All @@ -84,7 +86,7 @@ Given this API, we can easily write a query that finds methods that are not call

We have to use ``polyCalls`` instead of ``calls`` here: we want to be reasonably sure that ``callee`` is not called, either directly or via overriding.

Running this query on a typical Java project results in lots of hits in the Java standard library. This makes sense, since no single client program uses every method of the standard library. More generally, we may want to exclude methods and constructors from compiled libraries. We can use the predicate ``fromSource`` to check whether a compilation unit is a source file, and refine our query as follows:
Running this query on a typical Java project results in lots of hits in the Java standard library. This makes sense, since no single client program uses every method of the standard library. More generally, we may want to exclude methods and constructors from compiled libraries. We can use the predicate ``fromSource`` to check whether a compilation unit is a source file, and refine our query:

.. code-block:: ql

Expand Down Expand Up @@ -142,7 +144,7 @@ A further special case is non-public default constructors: in the singleton patt

➤ `See this in the query console <https://lgtm.com/query/673060008/>`__. This change has a large effect on the results for some projects but little effect on the results for others. Use of this pattern varies widely between different projects.

Finally, on many Java projects there are methods that are invoked indirectly by reflection. Thus, while there are no calls invoking these methods, they are, in fact, used. It is in general very hard to identify such methods. A very common special case, however, is JUnit test methods, which are reflectively invoked by a test runner. The QL Java library has support for recognizing test classes of JUnit and other testing frameworks, which we can employ to filter out methods defined in such classes:
Finally, on many Java projects there are methods that are invoked indirectly by reflection. So, while there are no calls invoking these methods, they are, in fact, used. It is in general very hard to identify such methods. A very common special case, however, is JUnit test methods, which are reflectively invoked by a test runner. The QL Java library has support for recognizing test classes of JUnit and other testing frameworks, which we can employ to filter out methods defined in such classes:

.. code-block:: ql

Expand All @@ -159,9 +161,9 @@ Finally, on many Java projects there are methods that are invoked indirectly by

➤ `See this in the query console <https://lgtm.com/query/665760002/>`__. This should give a further reduction in the number of results returned.

What next?
----------
Further reading
---------------

- Find out how to query metadata and white space: :doc:`Tutorial: Annotations <annotations>`, :doc:`Tutorial: Javadoc <javadoc>`, and :doc:`Tutorial: Working with source locations <source-locations>`.
- Find out how specific classes in the AST are represented in the standard library for Java: :doc:`AST class reference <ast-class-reference>`.
- Find out how to query metadata and white space: :doc:`Annotations in Java <annotations>`, :doc:`Javadoc <javadoc>`, and :doc:`Working with source locations <source-locations>`.
- Find out how specific classes in the AST are represented in the standard library for Java: :doc:`Classes for working with Java code <ast-class-reference>`.
- Find out more about QL in the `QL language handbook <https://help.semmle.com/QL/ql-handbook/index.html>`__ and `QL language specification <https://help.semmle.com/QL/ql-spec/language.html>`__.
Loading