mirror of
https://github.com/hohn/codeql-info.git
synced 2025-12-16 20:53:04 +01:00
423 lines
36 KiB
HTML
423 lines
36 KiB
HTML
<!DOCTYPE html>
|
||
|
||
<html lang="en" data-content_root="../">
|
||
<head>
|
||
<meta charset="utf-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
|
||
|
||
<title>Annotations in Java — CodeQL</title>
|
||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=fa44fd50" />
|
||
<link rel="stylesheet" type="text/css" href="../_static/alabaster.css?v=93459777" />
|
||
<script src="../_static/documentation_options.js?v=5929fcd5"></script>
|
||
<script src="../_static/doctools.js?v=888ff710"></script>
|
||
<script src="../_static/sphinx_highlight.js?v=dc90522c"></script>
|
||
<link rel="icon" href="../_static/favicon.ico"/>
|
||
<link rel="index" title="Index" href="../genindex.html" />
|
||
<link rel="search" title="Search" href="../search.html" />
|
||
<link rel="next" title="Javadoc" href="javadoc.html" />
|
||
<link rel="prev" title="Navigating the call graph" href="navigating-the-call-graph.html" />
|
||
|
||
<title>CodeQL docs</title>
|
||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||
<link rel="stylesheet" href="../_static/custom.css" type="text/css" />
|
||
<link rel="stylesheet" href="../_static/primer.css" type="text/css" />
|
||
|
||
|
||
</head><body>
|
||
<header class="Header">
|
||
<div class="Header-item--full">
|
||
<a href="https://codeql.github.com/docs" class="Header-link f2 d-flex flex-items-center">
|
||
<!-- <%= octicon "mark-github", class: "mr-2", height: 32 %> -->
|
||
<svg height="32" class="octicon octicon-mark-github mr-2" viewBox="0 0 16 16" version="1.1" width="32"
|
||
aria-hidden="true">
|
||
<path fill-rule="evenodd"
|
||
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z">
|
||
</path>
|
||
</svg>
|
||
<span class="hide-sm">CodeQL documentation</span>
|
||
</a>
|
||
</div>
|
||
<div class="Header-item hide-sm hide-md">
|
||
<script src="https://addsearch.com/js/?key=93b4d287e2fc079a4089412b669785d5&categories=!0xhelp.semmle.com,0xcodeql.github.com,1xdocs,1xcodeql-standard-libraries,1xcodeql-query-help"></script>
|
||
</div>
|
||
<div class="Header-item">
|
||
|
||
<details class="dropdown details-reset details-overlay d-inline-block">
|
||
<summary class="btn bg-gray-dark text-white border" aria-haspopup="true">
|
||
CodeQL resources
|
||
<div class="dropdown-caret"></div>
|
||
</summary>
|
||
|
||
<ul class="dropdown-menu dropdown-menu-se dropdown-menu-dark">
|
||
<li><a class="dropdown-item" href="https://codeql.github.com/docs/codeql-overview">CodeQL overview</a></li>
|
||
<li class="dropdown-divider" role="separator"></li>
|
||
<div class="dropdown-header">
|
||
CodeQL tools
|
||
</div>
|
||
<li><a class="dropdown-item" href="https://codeql.github.com/docs/codeql-for-visual-studio-code">CodeQL for VS Code</a>
|
||
<li><a class="dropdown-item" href="https://codeql.github.com/docs/codeql-cli">CodeQL CLI</a>
|
||
</li>
|
||
<li class="dropdown-divider" role="separator"></li>
|
||
<div class="dropdown-header">
|
||
CodeQL guides
|
||
</div>
|
||
<li><a class="dropdown-item" href="https://codeql.github.com/docs/writing-codeql-queries">Writing CodeQL queries</a></li>
|
||
<li><a class="dropdown-item" href="https://codeql.github.com/docs/codeql-language-guides">CodeQL language guides</a>
|
||
<li class="dropdown-divider" role="separator"></li>
|
||
<div class="dropdown-header">
|
||
Reference docs
|
||
</div>
|
||
<li><a class="dropdown-item" href="https://codeql.github.com/docs/ql-language-reference/">QL language
|
||
reference</a>
|
||
<li><a class="dropdown-item" href="https://codeql.github.com/codeql-standard-libraries">CodeQL
|
||
standard-libraries</a>
|
||
<li><a class="dropdown-item" href="https://codeql.github.com/codeql-query-help">CodeQL
|
||
query help</a>
|
||
<li class="dropdown-divider" role="separator"></li>
|
||
<div class="dropdown-header">
|
||
Source files
|
||
</div>
|
||
<li><a class="dropdown-item" href="https://github.com/github/codeql">CodeQL repository</a>
|
||
</ul>
|
||
</details>
|
||
|
||
</div>
|
||
|
||
</header>
|
||
<main class="bg-gray-light clearfix">
|
||
<nav class="SideNav position-sticky top-0 col-lg-3 col-md-3 float-left p-4 hide-sm hide-md overflow-y-auto">
|
||
|
||
<ul class="current">
|
||
<li class="toctree-l1"><a class="reference internal" href="../codeql-overview/index.html">CodeQL overview</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="../codeql-for-visual-studio-code/index.html">CodeQL for Visual Studio Code</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="../codeql-cli/index.html">CodeQL CLI</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="../writing-codeql-queries/index.html">Writing CodeQL queries</a></li>
|
||
<li class="toctree-l1 current"><a class="reference internal" href="index.html">CodeQL language guides</a><ul class="current">
|
||
<li class="toctree-l2"><a class="reference internal" href="codeql-for-cpp.html">CodeQL for C and C++</a></li>
|
||
<li class="toctree-l2"><a class="reference internal" href="codeql-for-csharp.html">CodeQL for C#</a></li>
|
||
<li class="toctree-l2"><a class="reference internal" href="codeql-for-go.html">CodeQL for Go</a></li>
|
||
<li class="toctree-l2 current"><a class="reference internal" href="codeql-for-java.html">CodeQL for Java</a><ul class="current">
|
||
<li class="toctree-l3"><a class="reference internal" href="basic-query-for-java-code.html">Basic query for Java code</a></li>
|
||
<li class="toctree-l3"><a class="reference internal" href="codeql-library-for-java.html">CodeQL library for Java</a></li>
|
||
<li class="toctree-l3"><a class="reference internal" href="analyzing-data-flow-in-java.html">Analyzing data flow in Java</a></li>
|
||
<li class="toctree-l3"><a class="reference internal" href="types-in-java.html">Types in Java</a></li>
|
||
<li class="toctree-l3"><a class="reference internal" href="overflow-prone-comparisons-in-java.html">Overflow-prone comparisons in Java</a></li>
|
||
<li class="toctree-l3"><a class="reference internal" href="navigating-the-call-graph.html">Navigating the call graph</a></li>
|
||
<li class="toctree-l3 current"><a class="current reference internal" href="#">Annotations in Java</a></li>
|
||
<li class="toctree-l3"><a class="reference internal" href="javadoc.html">Javadoc</a></li>
|
||
<li class="toctree-l3"><a class="reference internal" href="working-with-source-locations.html">Working with source locations</a></li>
|
||
<li class="toctree-l3"><a class="reference internal" href="abstract-syntax-tree-classes-for-working-with-java-programs.html">Abstract syntax tree classes for working with Java programs</a></li>
|
||
</ul>
|
||
</li>
|
||
<li class="toctree-l2"><a class="reference internal" href="codeql-for-javascript.html">CodeQL for JavaScript</a></li>
|
||
<li class="toctree-l2"><a class="reference internal" href="codeql-for-python.html">CodeQL for Python</a></li>
|
||
<li class="toctree-l2"><a class="reference internal" href="codeql-for-ruby.html">CodeQL for Ruby</a></li>
|
||
</ul>
|
||
</li>
|
||
<li class="toctree-l1"><a class="reference internal" href="../ql-language-reference/index.html">QL language reference</a></li>
|
||
</ul>
|
||
|
||
|
||
</nav>
|
||
|
||
|
||
<div class="body col-sm-12 col-md-9 col-lg-9 float-left border-left">
|
||
|
||
<div class="hide-lg hide-xl px-4 pt-4">
|
||
|
||
<div class="related" role="navigation" aria-label="related navigation">
|
||
<ul>
|
||
<li class="nav-item nav-item-0"><a href="../contents.html">CodeQL</a> »</li>
|
||
<li class="nav-item nav-item-1"><a href="index.html"
|
||
>CodeQL language guides</a> »</li>
|
||
<li class="nav-item nav-item-2"><a href="codeql-for-java.html"
|
||
accesskey="U">CodeQL for Java</a> »</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
|
||
<article class="p-4 col-lg-10 col-md-10 col-sm-12">
|
||
|
||
<section id="annotations-in-java">
|
||
<span id="id1"></span><h1>Annotations in Java<a class="headerlink" href="#annotations-in-java" title="Link to this heading">¶</a></h1>
|
||
<p>CodeQL databases of Java projects contain information about all annotations attached to program elements.</p>
|
||
<section id="about-working-with-annotations">
|
||
<h2>About working with annotations<a class="headerlink" href="#about-working-with-annotations" title="Link to this heading">¶</a></h2>
|
||
<p>Annotations are represented by these CodeQL classes:</p>
|
||
<ul class="simple">
|
||
<li><p>The class <code class="docutils literal notranslate"><span class="pre">Annotatable</span></code> represents all entities that may have an annotation attached to them (that is, packages, reference types, fields, methods, and local variables).</p></li>
|
||
<li><p>The class <code class="docutils literal notranslate"><span class="pre">AnnotationType</span></code> represents a Java annotation type, such as <code class="docutils literal notranslate"><span class="pre">java.lang.Override</span></code>; annotation types are interfaces.</p></li>
|
||
<li><p>The class <code class="docutils literal notranslate"><span class="pre">AnnotationElement</span></code> represents an annotation element, that is, a member of an annotation type.</p></li>
|
||
<li><p>The class <code class="docutils literal notranslate"><span class="pre">Annotation</span></code> represents an annotation such as <code class="docutils literal notranslate"><span class="pre">@Override</span></code>; annotation values can be accessed through member predicate <code class="docutils literal notranslate"><span class="pre">getValue</span></code>.</p></li>
|
||
</ul>
|
||
<p>For example, the Java standard library defines an annotation <code class="docutils literal notranslate"><span class="pre">SuppressWarnings</span></code> that instructs the compiler not to emit certain kinds of warnings:</p>
|
||
<div class="highlight-java notranslate"><div class="highlight"><pre><span></span><span class="kn">package</span><span class="w"> </span><span class="nn">java.lang</span><span class="p">;</span>
|
||
|
||
<span class="kd">public</span><span class="w"> </span><span class="nd">@interface</span><span class="w"> </span><span class="n">SuppressWarnings</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="n">String</span><span class="o">[]</span><span class="w"> </span><span class="n">value</span><span class="p">;</span>
|
||
<span class="p">}</span>
|
||
</pre></div>
|
||
</div>
|
||
<p><code class="docutils literal notranslate"><span class="pre">SuppressWarnings</span></code> is represented as an <code class="docutils literal notranslate"><span class="pre">AnnotationType</span></code>, with <code class="docutils literal notranslate"><span class="pre">value</span></code> as its only <code class="docutils literal notranslate"><span class="pre">AnnotationElement</span></code>.</p>
|
||
<p>A typical usage of <code class="docutils literal notranslate"><span class="pre">SuppressWarnings</span></code> would be this annotation for preventing a warning about using raw types:</p>
|
||
<div class="highlight-java notranslate"><div class="highlight"><pre><span></span><span class="kd">class</span> <span class="nc">A</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="nd">@SuppressWarnings</span><span class="p">(</span><span class="s">"rawtypes"</span><span class="p">)</span>
|
||
<span class="w"> </span><span class="kd">public</span><span class="w"> </span><span class="nf">A</span><span class="p">(</span><span class="n">java</span><span class="p">.</span><span class="na">util</span><span class="p">.</span><span class="na">List</span><span class="w"> </span><span class="n">rawlist</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="p">}</span>
|
||
<span class="p">}</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The expression <code class="docutils literal notranslate"><span class="pre">@SuppressWarnings("rawtypes")</span></code> is represented as an <code class="docutils literal notranslate"><span class="pre">Annotation</span></code>. The string literal <code class="docutils literal notranslate"><span class="pre">"rawtypes"</span></code> is used to initialize the annotation element <code class="docutils literal notranslate"><span class="pre">value</span></code>, and its value can be extracted from the annotation by means of the <code class="docutils literal notranslate"><span class="pre">getValue</span></code> predicate.</p>
|
||
<p>We could then write this query to find all <code class="docutils literal notranslate"><span class="pre">@SuppressWarnings</span></code> annotations attached to constructors, and return both the annotation itself and the value of its <code class="docutils literal notranslate"><span class="pre">value</span></code> element:</p>
|
||
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>import java
|
||
|
||
from Constructor c, Annotation ann, AnnotationType anntp
|
||
where ann = c.getAnAnnotation() and
|
||
anntp = ann.getType() and
|
||
anntp.hasQualifiedName("java.lang", "SuppressWarnings")
|
||
select ann, ann.getValue("value")
|
||
</pre></div>
|
||
</div>
|
||
<p>➤ <a class="reference external" href="https://lgtm.com/query/1775658606775222283/">See the full query in the query console on LGTM.com</a>. Several of the LGTM.com demo projects use the <code class="docutils literal notranslate"><span class="pre">@SuppressWarnings</span></code> annotation. Looking at the <code class="docutils literal notranslate"><span class="pre">value</span></code>s of the annotation element returned by the query, we can see that the <em>apache/activemq</em> project uses the <code class="docutils literal notranslate"><span class="pre">"rawtypes"</span></code> value described above.</p>
|
||
<p>As another example, this query finds all annotation types that only have a single annotation element, which has name <code class="docutils literal notranslate"><span class="pre">value</span></code>:</p>
|
||
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>import java
|
||
|
||
from AnnotationType anntp
|
||
where forex(AnnotationElement elt |
|
||
elt = anntp.getAnAnnotationElement() |
|
||
elt.getName() = "value"
|
||
)
|
||
select anntp
|
||
</pre></div>
|
||
</div>
|
||
<p>➤ <a class="reference external" href="https://lgtm.com/query/2145264152490258283/">See the full query in the query console on LGTM.com</a>.</p>
|
||
</section>
|
||
<section id="example-finding-missing-override-annotations">
|
||
<h2>Example: Finding missing <code class="docutils literal notranslate"><span class="pre">@Override</span></code> annotations<a class="headerlink" href="#example-finding-missing-override-annotations" title="Link to this heading">¶</a></h2>
|
||
<p>In newer versions of Java, it’s recommended (though not required) that you annotate methods that override another method with an <code class="docutils literal notranslate"><span class="pre">@Override</span></code> annotation. These annotations, which are checked by the compiler, serve as documentation, and also help you avoid accidental overloading where overriding was intended.</p>
|
||
<p>For example, consider this example program:</p>
|
||
<div class="highlight-java notranslate"><div class="highlight"><pre><span></span><span class="kd">class</span> <span class="nc">Super</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="kd">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">m</span><span class="p">()</span><span class="w"> </span><span class="p">{}</span>
|
||
<span class="p">}</span>
|
||
|
||
<span class="kd">class</span> <span class="nc">Sub1</span><span class="w"> </span><span class="kd">extends</span><span class="w"> </span><span class="n">Super</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="nd">@Override</span><span class="w"> </span><span class="kd">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">m</span><span class="p">()</span><span class="w"> </span><span class="p">{}</span>
|
||
<span class="p">}</span>
|
||
|
||
<span class="kd">class</span> <span class="nc">Sub2</span><span class="w"> </span><span class="kd">extends</span><span class="w"> </span><span class="n">Super</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="kd">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">m</span><span class="p">()</span><span class="w"> </span><span class="p">{}</span>
|
||
<span class="p">}</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Here, both <code class="docutils literal notranslate"><span class="pre">Sub1.m</span></code> and <code class="docutils literal notranslate"><span class="pre">Sub2.m</span></code> override <code class="docutils literal notranslate"><span class="pre">Super.m</span></code>, but only <code class="docutils literal notranslate"><span class="pre">Sub1.m</span></code> is annotated with <code class="docutils literal notranslate"><span class="pre">@Override</span></code>.</p>
|
||
<p>We’ll now develop a query for finding methods like <code class="docutils literal notranslate"><span class="pre">Sub2.m</span></code> that should be annotated with <code class="docutils literal notranslate"><span class="pre">@Override</span></code>, but are not.</p>
|
||
<p>As a first step, let’s write a query that finds all <code class="docutils literal notranslate"><span class="pre">@Override</span></code> annotations. Annotations are expressions, so their type can be accessed using <code class="docutils literal notranslate"><span class="pre">getType</span></code>. Annotation types, on the other hand, are interfaces, so their qualified name can be queried using <code class="docutils literal notranslate"><span class="pre">hasQualifiedName</span></code>. Therefore we can implement the query like this:</p>
|
||
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>import java
|
||
|
||
from Annotation ann
|
||
where ann.getType().hasQualifiedName("java.lang", "Override")
|
||
select ann
|
||
</pre></div>
|
||
</div>
|
||
<p>As always, it is a good idea to try this query on a CodeQL database for a Java project to make sure it actually produces some results. On the earlier example, it should find the annotation on <code class="docutils literal notranslate"><span class="pre">Sub1.m</span></code>. Next, we encapsulate the concept of an <code class="docutils literal notranslate"><span class="pre">@Override</span></code> annotation as a CodeQL class:</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>class OverrideAnnotation extends Annotation {
|
||
OverrideAnnotation() {
|
||
this.getType().hasQualifiedName("java.lang", "Override")
|
||
}
|
||
}
|
||
</pre></div>
|
||
</div>
|
||
<p>This makes it very easy to write our query for finding methods that override another method, but don’t have an <code class="docutils literal notranslate"><span class="pre">@Override</span></code> annotation: we use predicate <code class="docutils literal notranslate"><span class="pre">overrides</span></code> to find out whether one method overrides another, and predicate <code class="docutils literal notranslate"><span class="pre">getAnAnnotation</span></code> (available on any <code class="docutils literal notranslate"><span class="pre">Annotatable</span></code>) to retrieve some annotation.</p>
|
||
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>import java
|
||
|
||
from Method overriding, Method overridden
|
||
where overriding.overrides(overridden) and
|
||
not overriding.getAnAnnotation() instanceof OverrideAnnotation
|
||
select overriding, "Method overrides another method, but does not have an @Override annotation."
|
||
</pre></div>
|
||
</div>
|
||
<p>➤ <a class="reference external" href="https://lgtm.com/query/7419756266089837339/">See this in the query console on LGTM.com</a>. 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 <code class="docutils literal notranslate"><span class="pre">overriding.fromSource()</span></code> to restrict the result to only report methods for which source code is available.</p>
|
||
</section>
|
||
<section id="example-finding-calls-to-deprecated-methods">
|
||
<h2>Example: Finding calls to deprecated methods<a class="headerlink" href="#example-finding-calls-to-deprecated-methods" title="Link to this heading">¶</a></h2>
|
||
<p>As another example, we can write a query that finds calls to methods marked with a <code class="docutils literal notranslate"><span class="pre">@Deprecated</span></code> annotation.</p>
|
||
<p>For example, consider this example program:</p>
|
||
<div class="highlight-java notranslate"><div class="highlight"><pre><span></span><span class="kd">class</span> <span class="nc">A</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="nd">@Deprecated</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">m</span><span class="p">()</span><span class="w"> </span><span class="p">{}</span>
|
||
|
||
<span class="w"> </span><span class="nd">@Deprecated</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">n</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="n">m</span><span class="p">();</span>
|
||
<span class="w"> </span><span class="p">}</span>
|
||
|
||
<span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">r</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="n">m</span><span class="p">();</span>
|
||
<span class="w"> </span><span class="p">}</span>
|
||
<span class="p">}</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Here, both <code class="docutils literal notranslate"><span class="pre">A.m</span></code> and <code class="docutils literal notranslate"><span class="pre">A.n</span></code> are marked as deprecated. Methods <code class="docutils literal notranslate"><span class="pre">n</span></code> and <code class="docutils literal notranslate"><span class="pre">r</span></code> both call <code class="docutils literal notranslate"><span class="pre">m</span></code>, but note that <code class="docutils literal notranslate"><span class="pre">n</span></code> itself is deprecated, so we probably should not warn about this call.</p>
|
||
<p>As in the previous example, we’ll start by defining a class for representing <code class="docutils literal notranslate"><span class="pre">@Deprecated</span></code> annotations:</p>
|
||
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>class DeprecatedAnnotation extends Annotation {
|
||
DeprecatedAnnotation() {
|
||
this.getType().hasQualifiedName("java.lang", "Deprecated")
|
||
}
|
||
}
|
||
</pre></div>
|
||
</div>
|
||
<p>Now we can define a class for representing deprecated methods:</p>
|
||
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>class DeprecatedMethod extends Method {
|
||
DeprecatedMethod() {
|
||
this.getAnAnnotation() instanceof DeprecatedAnnotation
|
||
}
|
||
}
|
||
</pre></div>
|
||
</div>
|
||
<p>Finally, we use these classes to find calls to deprecated methods, excluding calls that themselves appear in deprecated methods:</p>
|
||
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>import java
|
||
|
||
from Call call
|
||
where call.getCallee() instanceof DeprecatedMethod
|
||
and not call.getCaller() instanceof DeprecatedMethod
|
||
select call, "This call invokes a deprecated method."
|
||
</pre></div>
|
||
</div>
|
||
<p>In our example, this query flags the call to <code class="docutils literal notranslate"><span class="pre">A.m</span></code> in <code class="docutils literal notranslate"><span class="pre">A.r</span></code>, but not the one in <code class="docutils literal notranslate"><span class="pre">A.n</span></code>.</p>
|
||
<p>For more information about the class <code class="docutils literal notranslate"><span class="pre">Call</span></code>, see “<a class="reference internal" href="navigating-the-call-graph.html"><span class="doc">Navigating the call graph</span></a>.”</p>
|
||
<section id="improvements">
|
||
<h3>Improvements<a class="headerlink" href="#improvements" title="Link to this heading">¶</a></h3>
|
||
<p>The Java standard library provides another annotation type <code class="docutils literal notranslate"><span class="pre">java.lang.SupressWarnings</span></code> that can be used to suppress certain categories of warnings. In particular, it can be used to turn off warnings about calls to deprecated methods. Therefore, it makes sense to improve our query to ignore calls to deprecated methods from inside methods that are marked with <code class="docutils literal notranslate"><span class="pre">@SuppressWarnings("deprecated")</span></code>.</p>
|
||
<p>For instance, consider this slightly updated example:</p>
|
||
<div class="highlight-java notranslate"><div class="highlight"><pre><span></span><span class="kd">class</span> <span class="nc">A</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="nd">@Deprecated</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">m</span><span class="p">()</span><span class="w"> </span><span class="p">{}</span>
|
||
|
||
<span class="w"> </span><span class="nd">@Deprecated</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">n</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="n">m</span><span class="p">();</span>
|
||
<span class="w"> </span><span class="p">}</span>
|
||
|
||
<span class="w"> </span><span class="nd">@SuppressWarnings</span><span class="p">(</span><span class="s">"deprecated"</span><span class="p">)</span>
|
||
<span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">r</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="n">m</span><span class="p">();</span>
|
||
<span class="w"> </span><span class="p">}</span>
|
||
<span class="p">}</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Here, the programmer has explicitly suppressed warnings about deprecated calls in <code class="docutils literal notranslate"><span class="pre">A.r</span></code>, so our query should not flag the call to <code class="docutils literal notranslate"><span class="pre">A.m</span></code> any more.</p>
|
||
<p>To do so, we first introduce a class for representing all <code class="docutils literal notranslate"><span class="pre">@SuppressWarnings</span></code> annotations where the string <code class="docutils literal notranslate"><span class="pre">deprecated</span></code> occurs among the list of warnings to suppress:</p>
|
||
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>class SuppressDeprecationWarningAnnotation extends Annotation {
|
||
SuppressDeprecationWarningAnnotation() {
|
||
this.getType().hasQualifiedName("java.lang", "SuppressWarnings") and
|
||
this.getAValue().(Literal).getLiteral().regexpMatch(".*deprecation.*")
|
||
}
|
||
}
|
||
</pre></div>
|
||
</div>
|
||
<p>Here, we use <code class="docutils literal notranslate"><span class="pre">getAValue()</span></code> to retrieve any annotation value: in fact, annotation type <code class="docutils literal notranslate"><span class="pre">SuppressWarnings</span></code> only has a single annotation element, so every <code class="docutils literal notranslate"><span class="pre">@SuppressWarnings</span></code> annotation only has a single annotation value. Then, we ensure that it is a literal, obtain its string value using <code class="docutils literal notranslate"><span class="pre">getLiteral</span></code>, and check whether it contains the string <code class="docutils literal notranslate"><span class="pre">deprecation</span></code> using a regular expression match.</p>
|
||
<p>For real-world use, this check would have to be generalized a bit: for example, the OpenJDK Java compiler allows <code class="docutils literal notranslate"><span class="pre">@SuppressWarnings("all")</span></code> annotations to suppress all warnings. We may also want to make sure that <code class="docutils literal notranslate"><span class="pre">deprecation</span></code> is matched as an entire word, and not as part of another word, by changing the regular expression to <code class="docutils literal notranslate"><span class="pre">".*\\bdeprecation\\b.*"</span></code>.</p>
|
||
<p>Now we can extend our query to filter out calls in methods carrying a <code class="docutils literal notranslate"><span class="pre">SuppressDeprecationWarningAnnotation</span></code>:</p>
|
||
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>import java
|
||
|
||
// Insert the class definitions from above
|
||
|
||
from Call call
|
||
where call.getCallee() instanceof DeprecatedMethod
|
||
and not call.getCaller() instanceof DeprecatedMethod
|
||
and not call.getCaller().getAnAnnotation() instanceof SuppressDeprecationWarningAnnotation
|
||
select call, "This call invokes a deprecated method."
|
||
</pre></div>
|
||
</div>
|
||
<p>➤ <a class="reference external" href="https://lgtm.com/query/8706367340403790260/">See this in the query console on LGTM.com</a>. It’s fairly common for projects to contain calls to methods that appear to be deprecated.</p>
|
||
</section>
|
||
</section>
|
||
<section id="further-reading">
|
||
<h2>Further reading<a class="headerlink" href="#further-reading" title="Link to this heading">¶</a></h2>
|
||
<ul class="simple">
|
||
<li><p><a class="reference external" href="https://github.com/github/codeql/tree/main/java/ql/src">CodeQL queries for Java</a></p></li>
|
||
<li><p><a class="reference external" href="https://github.com/github/codeql/tree/main/java/ql/examples">Example queries for Java</a></p></li>
|
||
<li><p><a class="reference external" href="https://codeql.github.com/codeql-standard-libraries/java/">CodeQL library reference for Java</a></p></li>
|
||
</ul>
|
||
<ul class="simple">
|
||
<li><p>“<a class="reference internal" href="../ql-language-reference/index.html#ql-language-reference"><span class="std std-ref">QL language reference</span></a>”</p></li>
|
||
<li><p>“<a class="reference internal" href="../codeql-overview/codeql-tools.html#codeql-tools"><span class="std std-ref">CodeQL tools</span></a>”</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
|
||
|
||
</article>
|
||
|
||
<!-- GitHub footer, with links to terms and privacy statement -->
|
||
<div class="px-3 px-md-6 f6 py-4 d-sm-flex flex-justify-between flex-row-reverse flex-items-center border-top">
|
||
<ul class="list-style-none d-flex flex-items-center mb-3 mb-sm-0 lh-condensed-ultra">
|
||
<li class="mr-3">
|
||
<a href="https://twitter.com/github" title="GitHub on Twitter" style="color: #959da5;">
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 273.5 222.3" class="d-block" height="18">
|
||
<path
|
||
d="M273.5 26.3a109.77 109.77 0 0 1-32.2 8.8 56.07 56.07 0 0 0 24.7-31 113.39 113.39 0 0 1-35.7 13.6 56.1 56.1 0 0 0-97 38.4 54 54 0 0 0 1.5 12.8A159.68 159.68 0 0 1 19.1 10.3a56.12 56.12 0 0 0 17.4 74.9 56.06 56.06 0 0 1-25.4-7v.7a56.11 56.11 0 0 0 45 55 55.65 55.65 0 0 1-14.8 2 62.39 62.39 0 0 1-10.6-1 56.24 56.24 0 0 0 52.4 39 112.87 112.87 0 0 1-69.7 24 119 119 0 0 1-13.4-.8 158.83 158.83 0 0 0 86 25.2c103.2 0 159.6-85.5 159.6-159.6 0-2.4-.1-4.9-.2-7.3a114.25 114.25 0 0 0 28.1-29.1"
|
||
fill="currentColor"></path>
|
||
</svg>
|
||
</a>
|
||
</li>
|
||
<li class="mr-3">
|
||
<a href="https://www.facebook.com/GitHub" title="GitHub on Facebook" style="color: #959da5;">
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15.3 15.4" class="d-block" height="18">
|
||
<path
|
||
d="M14.5 0H.8a.88.88 0 0 0-.8.9v13.6a.88.88 0 0 0 .8.9h7.3v-6h-2V7.1h2V5.4a2.87 2.87 0 0 1 2.5-3.1h.5a10.87 10.87 0 0 1 1.8.1v2.1h-1.3c-1 0-1.1.5-1.1 1.1v1.5h2.3l-.3 2.3h-2v5.9h3.9a.88.88 0 0 0 .9-.8V.8a.86.86 0 0 0-.8-.8z"
|
||
fill="currentColor"></path>
|
||
</svg>
|
||
</a>
|
||
</li>
|
||
<li class="mr-3">
|
||
<a href="https://www.youtube.com/github" title="GitHub on YouTube" style="color: #959da5;">
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 19.17 13.6" class="d-block" height="16">
|
||
<path
|
||
d="M18.77 2.13A2.4 2.4 0 0 0 17.09.42C15.59 0 9.58 0 9.58 0a57.55 57.55 0 0 0-7.5.4A2.49 2.49 0 0 0 .39 2.13 26.27 26.27 0 0 0 0 6.8a26.15 26.15 0 0 0 .39 4.67 2.43 2.43 0 0 0 1.69 1.71c1.52.42 7.5.42 7.5.42a57.69 57.69 0 0 0 7.51-.4 2.4 2.4 0 0 0 1.68-1.71 25.63 25.63 0 0 0 .4-4.67 24 24 0 0 0-.4-4.69zM7.67 9.71V3.89l5 2.91z"
|
||
fill="currentColor"></path>
|
||
</svg>
|
||
</a>
|
||
</li>
|
||
<li class="mr-3 flex-self-start">
|
||
<a href="https://www.linkedin.com/company/github" title="GitHub on Linkedin" style="color: #959da5;">
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 19 18" class="d-block" height="18">
|
||
<path
|
||
d="M3.94 2A2 2 0 1 1 2 0a2 2 0 0 1 1.94 2zM4 5.48H0V18h4zm6.32 0H6.34V18h3.94v-6.57c0-3.66 4.77-4 4.77 0V18H19v-7.93c0-6.17-7.06-5.94-8.72-2.91z"
|
||
fill="currentColor"></path>
|
||
</svg>
|
||
</a>
|
||
</li>
|
||
<li>
|
||
<a href="https://github.com/github" title="GitHub's organization" style="color: #959da5;">
|
||
<svg version="1.1" width="20" height="20" viewBox="0 0 16 16" class="octicon octicon-mark-github"
|
||
aria-hidden="true">
|
||
<path fill-rule="evenodd"
|
||
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z">
|
||
</path>
|
||
</svg>
|
||
</a>
|
||
</li>
|
||
</ul>
|
||
<ul class="list-style-none d-flex text-gray">
|
||
<li class="mr-3">©
|
||
<script type="text/javascript">document.write(new Date().getFullYear());</script> GitHub, Inc.</li>
|
||
<li class="mr-3"><a
|
||
href="https://docs.github.com/github/site-policy/github-terms-of-service"
|
||
class="link-gray">Terms </a></li>
|
||
<li><a href="https://docs.github.com/github/site-policy/github-privacy-statement"
|
||
class="link-gray">Privacy </a></li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</main>
|
||
|
||
<script type="text/javascript">
|
||
$(document).ready(function () {
|
||
$(".toggle > *").hide();
|
||
$(".toggle .name").show();
|
||
$(".toggle .name").click(function () {
|
||
$(this).parent().children().not(".name").toggle(400);
|
||
$(this).parent().children(".name").toggleClass("open");
|
||
})
|
||
});
|
||
</script>
|
||
|
||
</body>
|
||
</html> |