pmd/pmd_userdocs_migrating_to_pmd7.html

5545 lines
386 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="Migrating to PMD 7 from PMD 6.x">
<meta name="keywords" content="pmduserdocs, ">
<title>Migration Guide for PMD 7 | PMD Source Code Analyzer</title>
<link rel="stylesheet" type="text/css" href="assets/fontawesome-free-5.15.4-web/css/all.min.css">
<link rel="stylesheet" type="text/css" href="assets/bootstrap-4.5.2-dist/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="css/syntax.css">
<link rel="stylesheet" type="text/css" href="css/modern-business.css">
<link rel="stylesheet" type="text/css" href="css/customstyles.css">
<link rel="stylesheet" type="text/css" href="css/theme-green.css">
<link rel="stylesheet" type="text/css" href="css/pmd-customstyles.css">
<link rel="shortcut icon" href="images/logo/favicon.ico" type="image/x-icon">
<link rel="icon" href="images/logo/favicon.ico" type="image/x-icon">
<link rel="alternate" type="application/rss+xml" title="" href="feed.xml">
</head>
<body>
<!-- Content is offset by the height of the topnav bar. -->
<!-- There's already a padding-top rule in modern-business.css, but it apparently doesn't work on Firefox 60 and Chrome 67 -->
<div id="topbar-content-offset">
<!-- Navigation -->
<nav class="navbar navbar-expand-lg fixed-top navbar-dark">
<div class="container topnavlinks">
<a class="navbar-brand fas fa-home fa-lg" href="index.html">&nbsp;<span class="projectTitle"> PMD Source Code Analyzer Project</span></a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto mt-2 mt-lg-0"></ul>
<ul class="navbar-nav">
<!-- toggle sidebar button -->
<li class="nav-item"><a id="tg-sb-link" class="nav-link" href="#"><i id="tg-sb-icon" class="fas fa-toggle-on"></i> Nav</a></li>
<!-- entries without drop-downs appear here -->
<li class="nav-item"><a class="nav-link" href="https://github.com/pmd/pmd/releases/latest" target="_blank">Download</a></li>
<li class="nav-item"><a class="nav-link" href="https://github.com/pmd/pmd" target="_blank">Fork us on github</a></li>
<!-- entries with drop-downs appear here -->
<!-- conditional logic to control which topnav appears for the audience defined in the configuration file.-->
</ul>
<form class="form-inline my-2 my-lg-0">
<input class="form-control mr-sm-2" type="search" placeholder="search..." id="search-input">
<ul id="results-container"></ul>
</form>
</div>
</div>
</nav>
<!-- Page Content -->
<div class="container-toc-wrapper">
<div class="container">
<div class="col-lg-12">&nbsp;</div>
<!-- Content Row -->
<div class="row">
<!-- Sidebar Column -->
<div class="col-md-3" id="tg-sb-sidebar">
<ul id="mysidebar" class="nav">
<li class="sidebarTitle">PMD 7.3.0-SNAPSHOT</li>
<div class="sidebarTitleDate">Release date: 28-June-2024</div>
<li>
<a href="#">About</a>
<ul>
<li><a href="index.html">Home</a></li>
<li><a href="pmd_release_notes.html">Release notes</a></li>
<li><a href="pmd_release_notes_pmd7.html">Release notes (PMD 7)</a></li>
<li><a href="pmd_about_help.html">Getting help</a></li>
<li><a href="pmd_about_release_policies.html">Release policies</a></li>
<li><a href="pmd_about_support_lifecycle.html">Support lifecycle</a></li>
</ul>
</li>
<li>
<a href="#">User Documentation</a>
<ul>
<li class="active"><a href="pmd_userdocs_migrating_to_pmd7.html">Migration Guide for PMD 7</a></li>
<li><a href="pmd_userdocs_installation.html">Installation and basic CLI usage</a></li>
<li><a href="pmd_userdocs_making_rulesets.html">Making rulesets</a></li>
<li><a href="pmd_userdocs_configuring_rules.html">Configuring rules</a></li>
<li><a href="pmd_userdocs_best_practices.html">Best practices</a></li>
<li><a href="pmd_userdocs_suppressing_warnings.html">Suppressing warnings</a></li>
<li><a href="pmd_userdocs_incremental_analysis.html">Incremental analysis</a></li>
<li><a href="pmd_userdocs_cli_reference.html">PMD CLI reference</a></li>
<li><a href="pmd_userdocs_report_formats.html">PMD Report formats</a></li>
<li><a href="pmd_userdocs_3rdpartyrulesets.html">3rd party rulesets</a></li>
<li class="subfolders">
<a href="#">CPD reference</a>
<ul>
<li><a href="pmd_userdocs_cpd.html">Copy-paste detection</a></li>
<li><a href="pmd_userdocs_cpd_report_formats.html">CPD Report formats</a></li>
</ul>
</li>
<li class="subfolders">
<a href="#">Extending PMD</a>
<ul>
<li><a href="pmd_userdocs_extending_writing_rules_intro.html">Introduction to writing rules</a></li>
<li><a href="pmd_userdocs_extending_your_first_rule.html">Your first rule</a></li>
<li><a href="pmd_userdocs_extending_writing_xpath_rules.html">XPath rules</a></li>
<li><a href="pmd_userdocs_extending_writing_java_rules.html">Java rules</a></li>
<li><a href="pmd_userdocs_extending_designer_reference.html">Rule designer reference</a></li>
<li><a href="pmd_userdocs_extending_defining_properties.html">Defining rule properties</a></li>
<li><a href="pmd_userdocs_extending_rule_guidelines.html">Rule guidelines</a></li>
<li><a href="pmd_userdocs_extending_testing.html">Testing your rules</a></li>
<li><a href="pmd_userdocs_extending_ast_dump.html">Creating (XML) dump of the AST</a></li>
</ul>
</li>
<li class="subfolders">
<a href="#">Tools / Integrations</a>
<ul>
<li><a href="pmd_userdocs_tools_maven.html">Maven PMD Plugin</a></li>
<li><a href="pmd_userdocs_tools_gradle.html">Gradle</a></li>
<li><a href="pmd_userdocs_tools_ant.html">Ant</a></li>
<li><a href="pmd_userdocs_tools_java_api.html">PMD Java API</a></li>
<li><a href="pmd_userdocs_tools_bld.html">bld PMD Extension</a></li>
<li><a href="pmd_userdocs_tools_ci.html">CI integrations</a></li>
<li><a href="pmd_userdocs_tools.html">Other Tools / Integrations</a></li>
</ul>
</li>
</ul>
</li>
<li>
<a href="#">Rule Reference</a>
<ul>
<li class="subfolders">
<a href="#">Apex Rules</a>
<ul>
<li><a href="pmd_rules_apex.html">Index</a></li>
<li><a href="pmd_rules_apex_bestpractices.html">Best Practices</a></li>
<li><a href="pmd_rules_apex_codestyle.html">Code Style</a></li>
<li><a href="pmd_rules_apex_design.html">Design</a></li>
<li><a href="pmd_rules_apex_documentation.html">Documentation</a></li>
<li><a href="pmd_rules_apex_errorprone.html">Error Prone</a></li>
<li><a href="pmd_rules_apex_performance.html">Performance</a></li>
<li><a href="pmd_rules_apex_security.html">Security</a></li>
</ul>
</li>
<li class="subfolders">
<a href="#">HTML Rules</a>
<ul>
<li><a href="pmd_rules_html.html">Index</a></li>
<li><a href="pmd_rules_html_bestpractices.html">Best Practices</a></li>
</ul>
</li>
<li class="subfolders">
<a href="#">Java Rules</a>
<ul>
<li><a href="pmd_rules_java.html">Index</a></li>
<li><a href="pmd_rules_java_bestpractices.html">Best Practices</a></li>
<li><a href="pmd_rules_java_codestyle.html">Code Style</a></li>
<li><a href="pmd_rules_java_design.html">Design</a></li>
<li><a href="pmd_rules_java_documentation.html">Documentation</a></li>
<li><a href="pmd_rules_java_errorprone.html">Error Prone</a></li>
<li><a href="pmd_rules_java_multithreading.html">Multithreading</a></li>
<li><a href="pmd_rules_java_performance.html">Performance</a></li>
<li><a href="pmd_rules_java_security.html">Security</a></li>
</ul>
</li>
<li class="subfolders">
<a href="#">Java Server Pages Rules</a>
<ul>
<li><a href="pmd_rules_jsp.html">Index</a></li>
<li><a href="pmd_rules_jsp_bestpractices.html">Best Practices</a></li>
<li><a href="pmd_rules_jsp_codestyle.html">Code Style</a></li>
<li><a href="pmd_rules_jsp_design.html">Design</a></li>
<li><a href="pmd_rules_jsp_errorprone.html">Error Prone</a></li>
<li><a href="pmd_rules_jsp_security.html">Security</a></li>
</ul>
</li>
<li class="subfolders">
<a href="#">JavaScript Rules</a>
<ul>
<li><a href="pmd_rules_ecmascript.html">Index</a></li>
<li><a href="pmd_rules_ecmascript_bestpractices.html">Best Practices</a></li>
<li><a href="pmd_rules_ecmascript_codestyle.html">Code Style</a></li>
<li><a href="pmd_rules_ecmascript_errorprone.html">Error Prone</a></li>
</ul>
</li>
<li class="subfolders">
<a href="#">Kotlin Rules</a>
<ul>
<li><a href="pmd_rules_kotlin.html">Index</a></li>
<li><a href="pmd_rules_kotlin_bestpractices.html">Best Practices</a></li>
<li><a href="pmd_rules_kotlin_errorprone.html">Error Prone</a></li>
</ul>
</li>
<li class="subfolders">
<a href="#">Maven POM Rules</a>
<ul>
<li><a href="pmd_rules_pom.html">Index</a></li>
<li><a href="pmd_rules_pom_errorprone.html">Error Prone</a></li>
</ul>
</li>
<li class="subfolders">
<a href="#">Modelica Rules</a>
<ul>
<li><a href="pmd_rules_modelica.html">Index</a></li>
<li><a href="pmd_rules_modelica_bestpractices.html">Best Practices</a></li>
</ul>
</li>
<li class="subfolders">
<a href="#">PLSQL Rules</a>
<ul>
<li><a href="pmd_rules_plsql.html">Index</a></li>
<li><a href="pmd_rules_plsql_bestpractices.html">Best Practices</a></li>
<li><a href="pmd_rules_plsql_codestyle.html">Code Style</a></li>
<li><a href="pmd_rules_plsql_design.html">Design</a></li>
<li><a href="pmd_rules_plsql_errorprone.html">Error Prone</a></li>
</ul>
</li>
<li class="subfolders">
<a href="#">Salesforce Visualforce Rules</a>
<ul>
<li><a href="pmd_rules_visualforce.html">Index</a></li>
<li><a href="pmd_rules_visualforce_security.html">Security</a></li>
</ul>
</li>
<li class="subfolders">
<a href="#">Scala Rules</a>
<ul>
<li><a href="pmd_rules_scala.html">Index</a></li>
</ul>
</li>
<li class="subfolders">
<a href="#">Swift Rules</a>
<ul>
<li><a href="pmd_rules_swift.html">Index</a></li>
<li><a href="pmd_rules_swift_bestpractices.html">Best Practices</a></li>
<li><a href="pmd_rules_swift_errorprone.html">Error Prone</a></li>
</ul>
</li>
<li class="subfolders">
<a href="#">Velocity Template Language (VTL) Rules</a>
<ul>
<li><a href="pmd_rules_velocity.html">Index</a></li>
<li><a href="pmd_rules_velocity_bestpractices.html">Best Practices</a></li>
<li><a href="pmd_rules_velocity_design.html">Design</a></li>
<li><a href="pmd_rules_velocity_errorprone.html">Error Prone</a></li>
</ul>
</li>
<li class="subfolders">
<a href="#">WSDL Rules</a>
<ul>
<li><a href="pmd_rules_wsdl.html">Index</a></li>
</ul>
</li>
<li class="subfolders">
<a href="#">XML Rules</a>
<ul>
<li><a href="pmd_rules_xml.html">Index</a></li>
<li><a href="pmd_rules_xml_bestpractices.html">Best Practices</a></li>
<li><a href="pmd_rules_xml_errorprone.html">Error Prone</a></li>
</ul>
</li>
<li class="subfolders">
<a href="#">XSL Rules</a>
<ul>
<li><a href="pmd_rules_xsl.html">Index</a></li>
<li><a href="pmd_rules_xsl_codestyle.html">Code Style</a></li>
<li><a href="pmd_rules_xsl_performance.html">Performance</a></li>
</ul>
</li>
</ul>
</li>
<li>
<a href="#">Language-Specific Documentation</a>
<ul>
<li><a href="pmd_languages_index.html">Overview</a></li>
<li><a href="pmd_languages_configuration.html">Language configuration</a></li>
<li><a href="pmd_languages_apex.html">Apex</a></li>
<li><a href="pmd_languages_cpp.html">C/C++</a></li>
<li><a href="pmd_languages_cs.html">C#</a></li>
<li><a href="pmd_languages_coco.html">Coco</a></li>
<li><a href="pmd_languages_dart.html">Dart</a></li>
<li><a href="pmd_languages_fortran.html">Fortran</a></li>
<li><a href="pmd_languages_gherkin.html">Gherkin</a></li>
<li><a href="pmd_languages_go.html">Go</a></li>
<li><a href="pmd_languages_html.html">HTML</a></li>
<li><a href="pmd_languages_java.html">Java</a></li>
<li><a href="pmd_languages_js_ts.html">JavaScript / TypeScript</a></li>
<li><a href="pmd_languages_jsp.html">JSP</a></li>
<li><a href="pmd_languages_julia.html">Julia</a></li>
<li><a href="pmd_languages_kotlin.html">Kotlin</a></li>
<li><a href="pmd_languages_lua.html">Lua</a></li>
<li><a href="pmd_languages_matlab.html">Matlab</a></li>
<li><a href="pmd_languages_modelica.html">Modelica</a></li>
<li><a href="pmd_languages_objectivec.html">Objective-C</a></li>
<li><a href="pmd_languages_perl.html">Perl</a></li>
<li><a href="pmd_languages_php.html">PHP</a></li>
<li><a href="pmd_languages_plsql.html">PLSQL</a></li>
<li><a href="pmd_languages_python.html">Python</a></li>
<li><a href="pmd_languages_ruby.html">Ruby</a></li>
<li><a href="pmd_languages_scala.html">Scala</a></li>
<li><a href="pmd_languages_swift.html">Swift</a></li>
<li><a href="pmd_languages_tsql.html">T-SQL</a></li>
<li><a href="pmd_languages_visualforce.html">Visualforce</a></li>
<li><a href="pmd_languages_velocity.html">Velocity Template Language (VTL)</a></li>
<li><a href="pmd_languages_xml.html">XML and XML dialects</a></li>
</ul>
</li>
<li>
<a href="#">Developer Documentation</a>
<ul>
<li><a href="pmd_devdocs_development.html">Developer resources</a></li>
<li><a href="pmd_devdocs_building.html">Building PMD from source</a></li>
<li><a href="https://github.com/pmd/pmd/blob/master/CONTRIBUTING.md" target="_blank">Contributing</a></li>
<li><a href="pmd_devdocs_writing_documentation.html">Writing documentation</a></li>
<li><a href="pmd_devdocs_roadmap.html">Roadmap</a></li>
<li><a href="pmd_devdocs_how_pmd_works.html">How PMD works</a></li>
<li><a href="pmd_devdocs_pmdtester.html">Pmdtester</a></li>
<li><a href="pmd_devdocs_rule_deprecation_policy.html">Rule Deprecation Policy</a></li>
<li class="subfolders">
<a href="#">Major contributions</a>
<ul>
<li><a href="pmd_devdocs_major_rule_guidelines.html">Rule Guidelines</a></li>
<li><a href="pmd_devdocs_major_adding_new_language_javacc.html">Adding a new language (JavaCC)</a></li>
<li><a href="pmd_devdocs_major_adding_new_language_antlr.html">Adding a new language (ANTLR)</a></li>
<li><a href="pmd_devdocs_major_adding_new_cpd_language.html">Adding a new CPD language</a></li>
</ul>
</li>
<li class="subfolders">
<a href="#">Experimental features</a>
<ul>
<li><a href="tag_experimental.html">List of experimental Features</a></li>
</ul>
</li>
</ul>
</li>
<li>
<a href="#">Project documentation</a>
<ul>
<li class="subfolders">
<a href="#">Trivia about PMD</a>
<ul>
<li><a href="pmd_projectdocs_trivia_news.html">PMD in the press</a></li>
<li><a href="pmd_projectdocs_trivia_products.html">Products & books related to PMD</a></li>
<li><a href="pmd_projectdocs_trivia_similarprojects.html">Similar projects</a></li>
<li><a href="pmd_projectdocs_trivia_meaning.html">What does 'PMD' mean?</a></li>
</ul>
</li>
<li><a href="pmd_projectdocs_logo.html">Logo</a></li>
<li><a href="pmd_projectdocs_faq.html">FAQ</a></li>
<li><a href="license.html">License</a></li>
<li><a href="pmd_projectdocs_credits.html">Credits</a></li>
<li><a href="pmd_release_notes_old.html">Old release notes</a></li>
<li><a href="pmd_projectdocs_decisions.html">Decisions</a></li>
<li class="subfolders">
<a href="#">Project management</a>
<ul>
<li><a href="pmd_projectdocs_committers_infrastructure.html">Infrastructure</a></li>
<li><a href="pmd_projectdocs_committers_releasing.html">Release process</a></li>
<li><a href="pmd_projectdocs_committers_merging_pull_requests.html">Merging pull requests</a></li>
<li><a href="pmd_projectdocs_committers_main_landing_page.html">Main Landing page</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
<!-- Content Column -->
<div class="col-md-9" id="tg-sb-content">
<header>
<div class="row">
<div class="col-lg-12">
<a href="./" role="button"
><i class="fa fa-home fa-lg"></i
></a>
» Migration Guide for PMD 7
<a
target="_blank"
href="https://github.com/pmd/pmd/blob/master/docs/pages/pmd/userdocs/migrating_to_pmd7.md"
class="float-right"
role="button"
><i class="fab fa-github fa-lg"></i> Edit on GitHub</a
>
</div>
</div>
<hr />
</header>
<div class="post-header">
<h1 class="post-title-main">Migration Guide for PMD 7</h1>
</div>
<div class="post-content" data-github-edit-url="https://github.com/pmd/pmd/blob/master/docs/pages/pmd/userdocs/migrating_to_pmd7.md">
<div class="summary">Migrating to PMD 7 from PMD 6.x</div>
<details id="inline-toc-details">
<summary>Table of Contents</summary>
<div id="inline-toc"><!-- empty, move TOC here when screen size too small --></div>
</details>
<div class="alert alert-warning" role="alert"><i class="fas fa-warning"></i> <b>Important:</b>
This document might be incomplete and doesnt answer all questions. In that case please reach out to us
by opening a <a href="https://github.com/pmd/pmd/discussions">discussion</a> so that we can improve this guide.
</div>
<h2 id="before-you-update">Before you update</h2>
<p>Before updating to PMD 7, you should first update to the latest PMD 6 version 6.55.0 and try to fix all
deprecation warnings.</p>
<p>There are a couple of deprecated things in PMD 6, you might encounter:</p>
<ul>
<li>
<p>Properties: In order to define property descriptors, you should use <a href="https://docs.pmd-code.org/apidocs/pmd-core/7.3.0-SNAPSHOT/net/sourceforge/pmd/properties/PropertyFactory.html#"><code>PropertyFactory</code></a> now.
This factory can create properties of any type. E.g. instead of <code class="language-plaintext highlighter-rouge">StringProperty.named(...)</code> use
<code class="language-plaintext highlighter-rouge">PropertyFactory.stringProperty(...)</code>.</p>
<p>Also note, that <code class="language-plaintext highlighter-rouge">uiOrder</code> is gone. You can just remove it.</p>
<p>See also <a href="pmd_userdocs_extending_defining_properties.html">Defining rule properties</a></p>
</li>
<li>
<p>When reporting a violation, you might see a deprecation of the <code class="language-plaintext highlighter-rouge">addViolation</code> methods. These methods have been moved
to <a href="https://docs.pmd-code.org/apidocs/pmd-core/7.3.0-SNAPSHOT/net/sourceforge/pmd/reporting/RuleContext.html#"><code>RuleContext</code></a>. E.g. instead of <code class="language-plaintext highlighter-rouge">addViolation(data, node, ...)</code> use <code class="language-plaintext highlighter-rouge">asCtx(data).addViolation(node, ...)</code>.</p>
</li>
<li>When you are calling PMD from CLI, you need to stop using deprecated CLI params, e.g.
<ul>
<li><code class="language-plaintext highlighter-rouge">-no-cache</code> ➡️ <code class="language-plaintext highlighter-rouge">--no-cache</code></li>
<li><code class="language-plaintext highlighter-rouge">-failOnViolation</code> ➡️ <code class="language-plaintext highlighter-rouge">--fail-on-violation</code></li>
<li><code class="language-plaintext highlighter-rouge">-reportfile</code> ➡️ <code class="language-plaintext highlighter-rouge">--report-file</code></li>
<li><code class="language-plaintext highlighter-rouge">-language</code> ➡️ <code class="language-plaintext highlighter-rouge">--use-version</code></li>
</ul>
</li>
<li>If you have written custom XPath rule, look out for warnings about deprecated XPath attributes. These warnings
might look like
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>WARNING: Use of deprecated attribute 'VariableId/@Image' by XPath rule 'VariableNaming' (in ruleset 'VariableNamingRule'), please use @Name instead
</code></pre></div> </div>
<p>and often already suggest an alternative.</p>
</li>
<li>If you still reference rulesets or rules the old way which has been deprecated since 6.46.0:
<ul>
<li><code class="language-plaintext highlighter-rouge">&lt;lang-name&gt;-&lt;ruleset-name&gt;</code>, eg <code class="language-plaintext highlighter-rouge">java-basic</code>, which resolves to <code class="language-plaintext highlighter-rouge">rulesets/java/basic.xml</code></li>
<li>the internal release number, eg <code class="language-plaintext highlighter-rouge">600</code>, which resolves to <code class="language-plaintext highlighter-rouge">rulesets/releases/600.xml</code></li>
</ul>
<p>Such usages produce deprecation warnings that should be easy to spot, e.g.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Ruleset reference 'java-basic' uses a deprecated form, use 'rulesets/java/basic.xml' instead
</code></pre></div> </div>
<p>Use the explicit forms of these references to be compatible with PMD 7.</p>
<p>Note: Since PMD 6, all rules are sorted into categories (such as “Best Practices”, “Design”, “Error Prone”)
and the old rulesets like <code class="language-plaintext highlighter-rouge">basic.xml</code> have been deprecated and have been removed with PMD 7.
It is about time to create a <a href="pmd_userdocs_making_rulesets.html">custom ruleset</a>.</p>
</li>
</ul>
<h2 id="approaching-700">Approaching 7.0.0</h2>
<p>After that, migrate to the release candidates, and fix any problems you encounter. Start with 7.0.0-rc1 via
7.0.0-rc2, 7.0.0-rc3 and 7.0.0-rc4 until you finally use 7.0.0.</p>
<p>You might encounter additionally the following types of problems:</p>
<ul>
<li>If you use any programmatic API of PMD, first avoid any usage of deprecated or internal classes/methods. These
are marked with one of these annotations: <code class="language-plaintext highlighter-rouge">@Deprecated</code>, <code class="language-plaintext highlighter-rouge">@DeprecatedUtil700</code>, <code class="language-plaintext highlighter-rouge">@InternalApi</code>.
<ul>
<li>Some of these classes are available until 7.0.0-rc4 but are finally removed with 7.0.0.</li>
<li>See <a href="pmd_release_notes_pmd7.html#api-changes">API changes</a> for details.</li>
</ul>
</li>
<li>Some rules have been removed, because they have been deprecated. See <a href="pmd_release_notes_pmd7.html#removed-rules">Removed Rules</a>.</li>
<li>Some rule properties have been removed or changed. See <a href="pmd_release_notes_pmd7.html#changed-rules">Changed Rules</a>.</li>
<li>The filenames of the assets of a release (the “binary distribution zip file”) have changed,
see <a href="#release-downloads">Release downloads</a>.</li>
<li>Some CLI options have been removed, because they have been deprecated. See <a href="#cli-changes">CLI Changes</a> for details.</li>
<li>If you call CPD programmatically, the API has changed, see <a href="pmd_release_notes_pmd7.html#new-programmatic-api-for-cpd">New Programmatic API for CPD</a>.</li>
<li>If you use Visualforce, then you need to change “vf” to “visualforce”, e.g. <code class="language-plaintext highlighter-rouge">category/vf/security.xml</code> ➡️ <code class="language-plaintext highlighter-rouge">category/visualforce/security.xml</code></li>
<li>If you use Velocity, then you need to change “vm” to “velocity”, e.g. <code class="language-plaintext highlighter-rouge">category/vm/...</code> ➡️ <code class="language-plaintext highlighter-rouge">category/velocity/...</code></li>
</ul>
<p>The following topics describe well known migration challenges in more detail.</p>
<h2 id="use-cases">Use cases</h2>
<h3 id="im-using-only-built-in-rules">Im using only built-in rules</h3>
<p>When you are using only built-in rules, then you should check, whether you use any deprecated rule. With PMD 7
many deprecated rules are finally removed. You can see a complete list of the <a href="pmd_release_notes_pmd7.html#removed-rules">removed rules</a>
in the release notes for PMD 7.
The release notes also mention the replacement rule, that should be used instead. For some rules, there is no
replacement.</p>
<p>Then many rules have been changed or improved. New properties have been added to make them more versatile or
properties have been removed, if they are not necessary anymore. See <a href="pmd_release_notes_pmd7.html#changed-rules">changed rules</a>
in the release notes for PMD 7.</p>
<p>All properties which accept multiple values now use a comma (<code class="language-plaintext highlighter-rouge">,</code>) as a delimiter. The previous default was a
pipe character (<code class="language-plaintext highlighter-rouge">|</code>). The delimiter is not configurable anymore. If needed, the comma can be escaped
with a backslash. This affects the following rules:
<a href="pmd_rules_java_bestpractices.html#avoidusinghardcodedip"><code class="language-plaintext highlighter-rouge">AvoidUsingHardCodedIP</code></a>,
<a href="pmd_rules_java_bestpractices.html#loosecoupling"><code class="language-plaintext highlighter-rouge">LooseCoupling</code></a>,
<a href="pmd_rules_java_bestpractices.html#unusedprivatefield"><code class="language-plaintext highlighter-rouge">UnusedPrivateField</code></a>,
<a href="pmd_rules_java_bestpractices.html#unusedprivatemethod"><code class="language-plaintext highlighter-rouge">UnusedPrivateMethod</code></a>,
<a href="pmd_rules_java_codestyle.html#atleastoneconstructor"><code class="language-plaintext highlighter-rouge">AtLeastOneConstructor</code></a>,
<a href="pmd_rules_java_codestyle.html#commentdefaultaccessmodifier"><code class="language-plaintext highlighter-rouge">CommentDefaultAccessModifier</code></a>,
<a href="pmd_rules_java_codestyle.html#fieldnamingconventions"><code class="language-plaintext highlighter-rouge">FieldNamingConventions</code></a>,
<a href="pmd_rules_java_codestyle.html#linguisticnaming"><code class="language-plaintext highlighter-rouge">LinguisticNaming</code></a>,
<a href="pmd_rules_java_codestyle.html#unnecessaryconstructor"><code class="language-plaintext highlighter-rouge">UnnecessaryConstructor</code></a>,
<a href="pmd_rules_java_design.html#cyclomaticcomplexity"><code class="language-plaintext highlighter-rouge">CyclomaticComplexity</code></a>,
<a href="pmd_rules_java_design.html#ncsscount"><code class="language-plaintext highlighter-rouge">NcssCount</code></a>,
<a href="pmd_rules_java_design.html#singularfield"><code class="language-plaintext highlighter-rouge">SingularField</code></a>,
<a href="pmd_rules_java_errorprone.html#avoidbranchingstatementaslastinloop"><code class="language-plaintext highlighter-rouge">AvoidBranchingStatementAsLastInLoop</code></a>,
<a href="pmd_rules_java_errorprone.html#closeresource"><code class="language-plaintext highlighter-rouge">CloseResource</code></a>.</p>
<p>A handful of rules are new to PMD 7. You might want to check these out: <a href="pmd_release_notes_pmd7.html#new-rules">new rules</a>.</p>
<p>Once you have reviewed your ruleset(s), you can switch to PMD 7.</p>
<h3 id="im-using-custom-rules">Im using custom rules</h3>
<h4 id="testing">Testing</h4>
<p>Ideally, you have written good tests already for your custom rules - see <a href="pmd_userdocs_extending_testing.html">Testing your rules</a>.
This helps to identify problems early on.</p>
<p>The base test classes <a href="https://docs.pmd-code.org/apidocs/pmd-test/7.3.0-SNAPSHOT/net/sourceforge/pmd/test/PmdRuleTst.html#"><code>PmdRuleTst</code></a> and <a href="https://docs.pmd-code.org/apidocs/pmd-test/7.3.0-SNAPSHOT/net/sourceforge/pmd/test/SimpleAggregatorTst.html#"><code>SimpleAggregatorTst</code></a> have been moved out
of package <code class="language-plaintext highlighter-rouge">net.sourceforge.pmd.testframework</code>. Youll need to adjust your imports.</p>
<h4 id="ruleset-xml">Ruleset XML</h4>
<p>The <code class="language-plaintext highlighter-rouge">&lt;rule&gt;</code> tag, that defines your custom rule, is required to have a <code class="language-plaintext highlighter-rouge">language</code> attribute now. This was always the
case for XPath rules, but is now a requirement for Java rules.</p>
<h4 id="xpath-rules">XPath rules</h4>
<p>If you have <strong>XPath based</strong> rules, the first step will be to migrate to XPath 2.0 and then to XPath 3.1.
XPath 2.0 is available in PMD 6 already and can be used right away. PMD 7 will use by default XPath 3.1 and
wont support XPath 1.0 anymore. The difference between XPath 2.0 and XPath 3.1 is not big, so your XPath 2.0
can be expected to work in PMD 7 without any further changes. So the migration path is to simply migrate to XPath 2.0.</p>
<p>After you have migrated your XPath rules to XPath 2.0, remove the “version” property, since that has been removed
with PMD 7. PMD 7 by default uses XPath 3.1. See below <a href="#xpath-migrating-from-10-to-20">XPath</a> for details.</p>
<p>Then change the <code class="language-plaintext highlighter-rouge">class</code> attribute of your rule to <code class="language-plaintext highlighter-rouge">net.sourceforge.pmd.lang.rule.xpath.XPathRule</code> - because the
class <a href="https://docs.pmd-code.org/apidocs/pmd-core/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/rule/xpath/XPathRule.html#"><code>XPathRule</code></a> has been moved into subpackage <a href="https://docs.pmd-code.org/apidocs/pmd-core/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/rule/xpath/package-summary.html#"><code>net.sourceforge.pmd.lang.rule.xpath</code></a>.</p>
<p>There are some general changes for AST nodes regarding the <code class="language-plaintext highlighter-rouge">@Image</code> attribute.
See below <a href="#general-ast-changes-to-avoid-image">General AST Changes to avoid @Image</a>.</p>
<p>Additional infos:</p>
<ul>
<li>The custom XPath function <code class="language-plaintext highlighter-rouge">typeOf</code> has been removed (deprecated since 6.4.0).
Use the function <code class="language-plaintext highlighter-rouge">pmd-java:typeIs</code> or <code class="language-plaintext highlighter-rouge">pmd-java:typeIsExactly</code> instead.
See <a href="pmd_userdocs_extending_writing_xpath_rules.html#pmd-extension-functions">PMD extension functions</a> for available
functions.</li>
</ul>
<h4 id="java-rules">Java rules</h4>
<p>If you have <strong>Java based rules</strong>, and you are using rulechain, this works a bit different now. The RuleChain API
has changed, see <a href="https://github.com/pmd/pmd/pull/2490">[core] Simplify the rulechain (#2490)</a> for the full details.
But in short, you dont call <code class="language-plaintext highlighter-rouge">addRuleChainVisit(...)</code> in the rules constructor anymore. Instead, you
override the method <a href="https://docs.pmd-code.org/apidocs/pmd-core/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/rule/AbstractRule.html#buildTargetSelector"><code>buildTargetSelector</code></a>:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="kd">protected</span> <span class="nc">RuleTargetSelector</span> <span class="nf">buildTargetSelector</span><span class="o">()</span> <span class="o">{</span>
<span class="k">return</span> <span class="nc">RuleTargetSelector</span><span class="o">.</span><span class="na">forTypes</span><span class="o">(</span><span class="nc">ASTVariableId</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
<span class="o">}</span>
</code></pre></div></div>
<h4 id="java-ast-changes">Java AST changes</h4>
<p>The API to <strong>navigate the AST</strong> also changed significantly:</p>
<ul>
<li>Tree traversal using <a href="#node-api">Node API</a></li>
<li>Consider using the new <a href="#nodestream-api">NodeStream API</a> to navigate with null-safety. This is optional.</li>
</ul>
<p>Additionally, if you have created rules for <strong>Java</strong> - regardless whether it is a XPath based rule or a Java based
rule - you might need to adjust your queries or visitor methods. The Java AST has been refactored substantially.
The easiest way is to use the <a href="pmd_userdocs_extending_designer_reference.html">PMD Rule Designer</a> to see the structure
of the AST. See the section <a href="#java-ast">Java AST</a> below for details.</p>
<h3 id="ive-extended-pmd-with-a-custom-language">Ive extended PMD with a custom language…</h3>
<p>The guides for <a href="pmd_devdocs_major_adding_new_language_javacc.html">Adding a new language with JavaCC</a> and
<a href="pmd_devdocs_major_adding_new_cpd_language.html">Adding a new CPD language</a> have been updated.</p>
<p>Most notable changes are:</p>
<ul>
<li>As an alternative, PMD 7 now supports ANTLR in addition to JavaCC:
<a href="pmd_devdocs_major_adding_new_language_antlr.html">Adding a new language with ANTLR</a>.</li>
<li>There is a shared ant script that wraps the calls to javacc: <code class="language-plaintext highlighter-rouge">javacc-wrapper.xml</code>. This should be used now.</li>
<li>PMDs parser adapter for JavaCC generated parsers is called now
<a href="https://docs.pmd-code.org/apidocs/pmd-core/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ast/impl/javacc/JjtreeParserAdapter.html#"><code>JjtreeParserAdapter</code></a>. This is the class that needs to be implemented now.</li>
<li>There is no need anymore to write a custom <code class="language-plaintext highlighter-rouge">TokenManager</code> - we have now a common base class for JavaCC generated
token managers. This base class is <a href="https://docs.pmd-code.org/apidocs/pmd-core/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ast/impl/javacc/AbstractTokenManager.html#"><code>AbstractTokenManager</code></a>.</li>
<li>A rule violation factory is not needed anymore. For language specific information on rule violations, there is
now a <a href="https://docs.pmd-code.org/apidocs/pmd-core/7.3.0-SNAPSHOT/net/sourceforge/pmd/reporting/ViolationDecorator.html#"><code>ViolationDecorator</code></a> that a language can implement. These ViolationDecorators
are called when a violation is reported and they can provide the additional information. This information can be
used by renderers via <a href="https://docs.pmd-code.org/apidocs/pmd-core/7.3.0-SNAPSHOT/net/sourceforge/pmd/reporting/RuleViolation.html#getAdditionalInfo()"><code>RuleViolation#getAdditionalInfo</code></a>.</li>
<li>A parser visitor adapter is not needed anymore. The visitor interface now provides a default implementation.
Instead, a base visitor for the language should be created, which extends <a href="https://docs.pmd-code.org/apidocs/pmd-core/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ast/AstVisitorBase.html#"><code>AstVisitorBase</code></a>.</li>
<li>A rule chain visitor is not needed anymore. PMD provides a common implementation that fits all languages.</li>
</ul>
<h3 id="ive-extended-pmd-with-a-custom-feature">Ive extended PMD with a custom feature…</h3>
<p>In that case we cant provide a general guide unless we know the specific custom feature. If you are having difficulties
finding your way around the PMD source code and javadocs and you dont see the aspect of PMD documented you are
using, we are probably missing documentation. Please reach out to us by opening a
<a href="https://github.com/pmd/pmd/discussions">discussion</a>. We then can enhance the documentation and/or the PMD API.</p>
<h2 id="special-topics">Special topics</h2>
<h3 id="release-downloads">Release downloads</h3>
<ul>
<li>The asset filenames of PMD on <a href="https://github.com/pmd/pmd/releases">GitHub Releases</a> are
now <code class="language-plaintext highlighter-rouge">pmd-dist-&lt;version&gt;-bin.zip</code>, <code class="language-plaintext highlighter-rouge">pmd-dist-&lt;version&gt;-src.zip</code> and <code class="language-plaintext highlighter-rouge">pmd-dist-&lt;version&gt;-doc.zip</code>.
Keep that in mind, if you have an automated download script.</li>
<li>The structure inside the ZIP files stay the same, e.g. we still provide inside the binary distribution
ZIP file the base directory <code class="language-plaintext highlighter-rouge">pmd-bin-&lt;version&gt;</code>.</li>
</ul>
<h3 id="cli-changes">CLI Changes</h3>
<p>The CLI has been revamped completely
(see <a href="pmd_release_notes_pmd7.html#revamped-command-line-interface">Release Notes: Revamped Command Line Interface</a>).</p>
<p>Most notable changes:</p>
<ul>
<li>Unified start script on all platforms for all commands (PMD, CPD, Designer). Instead of <code class="language-plaintext highlighter-rouge">run.sh</code> and <code class="language-plaintext highlighter-rouge">pmd.bat</code>,
we now have <code class="language-plaintext highlighter-rouge">pmd</code> only (technically on Windows, there is still a <code class="language-plaintext highlighter-rouge">pmd.bat</code>, but it behaves the same).
<ul>
<li>Executing PMD from CLI now means: <code class="language-plaintext highlighter-rouge">run.sh pmd</code> / <code class="language-plaintext highlighter-rouge">pmd.bat</code> ➡️ <code class="language-plaintext highlighter-rouge">pmd check</code></li>
<li>Executing CPD: <code class="language-plaintext highlighter-rouge">run.sh cpd</code> / <code class="language-plaintext highlighter-rouge">cpd.bat</code> ➡️ <code class="language-plaintext highlighter-rouge">pmd cpd</code></li>
<li>Executing Designer: <code class="language-plaintext highlighter-rouge">run.sh designer</code> / <code class="language-plaintext highlighter-rouge">designer.bat</code> ➡️ <code class="language-plaintext highlighter-rouge">pmd designer</code></li>
<li>Executing CPD GUI: <code class="language-plaintext highlighter-rouge">run.sh cpd-gui</code> / <code class="language-plaintext highlighter-rouge">cpdgui.bat</code> ➡️ <code class="language-plaintext highlighter-rouge">pmd cpd-gui</code></li>
</ul>
</li>
<li>There are some changes to the CLI arguments:
<ul>
<li>
<p><code class="language-plaintext highlighter-rouge">--fail-on-violation false</code> ➡️ <code class="language-plaintext highlighter-rouge">--no-fail-on-violation</code></p>
<p>If you dont replace this argument, then “false” will be interpreted as a file to analyze. You might see then
an error message such as <code class="language-plaintext highlighter-rouge">[main] ERROR net.sourceforge.pmd.cli.commands.internal.PmdCommand - No such file false</code>.</p>
</li>
<li>PMD tries to display a progress bar. If you dont want this (e.g. on a CI build server), you can disable this
with <code class="language-plaintext highlighter-rouge">--no-progress</code>.</li>
<li><code class="language-plaintext highlighter-rouge">--no-ruleset-compatibility</code> has been removed without replacement.</li>
<li><code class="language-plaintext highlighter-rouge">--stress</code> (or <code class="language-plaintext highlighter-rouge">-stress</code>) has been removed without replacement.</li>
</ul>
</li>
</ul>
<h3 id="custom-distribution-packages">Custom distribution packages</h3>
<p>When creating a custom distribution which only integrates the languages you need, there are some changes to apply:</p>
<ul>
<li>In addition to the language dependencies you want, you also need add a dependency to
<code class="language-plaintext highlighter-rouge">net.sourceforge.pmd:pmd-cli</code> in order to get the CLI classes.</li>
<li>When fetching the scripts for the CLI with “maven-dependency-plugin”, you need to additionally fetch the
logging configuration. That means, the line
<code class="language-plaintext highlighter-rouge">&lt;includes&gt;scripts/**,LICENSE&lt;/includes&gt;</code> needs to be changed to <code class="language-plaintext highlighter-rouge">&lt;includes&gt;scripts/**,LICENSE,conf/**&lt;/includes&gt;</code>.</li>
<li>Since the assembly descriptor <code class="language-plaintext highlighter-rouge">pmd-bin</code> includes now optionally also a BOM (bill of material). If you want to
create this for your custom distribution, simply add the following plugin configuration:
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nt">&lt;plugin&gt;</span>
<span class="nt">&lt;groupId&gt;</span>org.cyclonedx<span class="nt">&lt;/groupId&gt;</span>
<span class="nt">&lt;artifactId&gt;</span>cyclonedx-maven-plugin<span class="nt">&lt;/artifactId&gt;</span>
<span class="nt">&lt;version&gt;</span>2.7.11<span class="nt">&lt;/version&gt;</span>
<span class="nt">&lt;configuration&gt;</span>
<span class="nt">&lt;outputName&gt;</span>pmd-${project.version}-cyclonedx<span class="nt">&lt;/outputName&gt;</span>
<span class="nt">&lt;/configuration&gt;</span>
<span class="nt">&lt;executions&gt;</span>
<span class="nt">&lt;execution&gt;</span>
<span class="nt">&lt;phase&gt;</span>package<span class="nt">&lt;/phase&gt;</span>
<span class="nt">&lt;goals&gt;</span>
<span class="nt">&lt;goal&gt;</span>makeAggregateBom<span class="nt">&lt;/goal&gt;</span>
<span class="nt">&lt;/goals&gt;</span>
<span class="nt">&lt;/execution&gt;</span>
<span class="nt">&lt;/executions&gt;</span>
<span class="nt">&lt;/plugin&gt;</span>
</code></pre></div> </div>
</li>
<li>The artifact name for PMD Designer has been renamed, you need to use now <code class="language-plaintext highlighter-rouge">net.sourceforge.pmd:pmd-designer</code>
instead of “pmd-ui”.</li>
</ul>
<div class="alert alert-info" role="alert"><i class="fas fa-info-circle"></i> <b>Note:</b>
The examples on <a href="https://github.com/pmd/pmd-examples">https://github.com/pmd/pmd-examples</a> have been updated.
</div>
<h3 id="rule-tests-are-now-using-junit5">Rule tests are now using JUnit5</h3>
<p>When you have custom rules, and you have written rule tests according to the guide
<a href="pmd_userdocs_extending_testing.html">Testing your rules</a>, you might want to consider upgrading your other tests to
<a href="https://junit.org/junit5/">JUnit 5</a>. The tests in PMD 7 have been migrated to JUnit5 - including the rule tests
for the built-in rules.</p>
<p>When executing the rule tests, you need to make sure to have JUnit5 on the classpath - which you automatically
get when you depend on <code class="language-plaintext highlighter-rouge">net.sourceforge.pmd:pmd-test</code>. If you also have JUnit4 tests, you need to make sure
to have a <a href="https://junit.org/junit5/docs/current/user-guide/#migrating-from-junit4-running">junit-vintage-engine</a>
as well on the test classpath, so that all tests are executed. That means, you might
need to add now a dependency to JUnit4 explicitly if needed.</p>
<h3 id="cpd-reported-endcolumn-is-now-exclusive">CPD: Reported endcolumn is now exclusive</h3>
<p>In PMD 6, the reported position of the duplicated tokens in CPD where always including, e.g. the following
described a duplication of length 4 in PMD 6: beginLine=1, endLine=1, beginColumn=1, endColumn=4 - these are
the first 4 character in the first line. With PMD 7, the endColumn is now <strong>excluding</strong>. The same duplication
will be reported in PMD 7 as: beginLine=1, endLine=1, beginColumn=1, endColumn=5.</p>
<p>The reported positions in a file follow now the usual meaning: line numbering starts from 1, begin line and end line
are inclusive, begin column is inclusive and end column is exclusive. This is the usual behavior of the most
common text editors and the PMD part already used that meaning in RuleViolations for a long time in PMD 6 already.</p>
<p>This only affects the XML report format as the others dont provide column information.</p>
<h3 id="node-api">Node API</h3>
<p>Starting from one node in the AST, you can navigate to children or parents with the following methods. This is
the “traditional” way for simple cases. For more complex cases, consider to use the new <a href="#nodestream-api">NodeStream API</a>.</p>
<p>Many methods available in PMD 6 have been deprecated and removed for a slicker API with consistent naming,
that also integrates tightly with the NodeStream API.</p>
<ul>
<li><code class="language-plaintext highlighter-rouge">getNthParent(n)</code> ➡️ <code class="language-plaintext highlighter-rouge">ancestors().get(n - 1)</code></li>
<li><code class="language-plaintext highlighter-rouge">getFirstParentOfType(parentType)</code> ➡️ <code class="language-plaintext highlighter-rouge">ancestors(parentType).first()</code></li>
<li><code class="language-plaintext highlighter-rouge">getParentsOfType(parentType)</code> ➡️ <code class="language-plaintext highlighter-rouge">ancestors(parentType).toList()</code></li>
<li><code class="language-plaintext highlighter-rouge">findChildrenOfType(childType)</code> ➡️ <code class="language-plaintext highlighter-rouge">children(childType).toList()</code></li>
<li><code class="language-plaintext highlighter-rouge">findDescendantsOfType(targetType)</code> ➡️ <code class="language-plaintext highlighter-rouge">descendants(targetType).toList()</code></li>
<li><code class="language-plaintext highlighter-rouge">getFirstChildOfType(childType)</code> ➡️ <code class="language-plaintext highlighter-rouge">firstChild(childType)</code></li>
<li><code class="language-plaintext highlighter-rouge">getFirstDescendantOfType(descendantType)</code> ➡️ <code class="language-plaintext highlighter-rouge">descendants(descendantType).first()</code></li>
<li><code class="language-plaintext highlighter-rouge">hasDescendantOfType(type)</code> ➡️ <code class="language-plaintext highlighter-rouge">descendants(type).nonEmpty()</code></li>
</ul>
<div class="alert alert-success" role="alert"><i class="fas fa-check-square-o"></i> <b>Tip:</b> First use PMD 7.0.0-rc3, which still has these methods. These methods are marked as
deprecated, so you can then start to change them. The replacement method is usually provided in the javadocs.
That way you avoid being confronted with just compile errors.</div>
<p>Unchanged methods that work as before:</p>
<ul>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-core/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ast/Node.html#getParent()"><code>getParent</code></a></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-core/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ast/Node.html#getChild(int)"><code>getChild</code></a></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-core/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ast/Node.html#getNumChildren()"><code>getNumChildren</code></a></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-core/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ast/Node.html#getIndexInParent()"><code>getIndexInParent</code></a></li>
</ul>
<p>New methods:</p>
<ul>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-core/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ast/Node.html#getFirstChild()"><code>getFirstChild</code></a></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-core/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ast/Node.html#getLastChild()"><code>getLastChild</code></a></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-core/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ast/Node.html#getPreviousSibling()"><code>getPreviousSibling</code></a></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-core/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ast/Node.html#getNextSibling()"><code>getNextSibling</code></a></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-core/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ast/Node.html#getRoot()"><code>getRoot</code></a></li>
</ul>
<p>New methods that integrate with NodeStream:</p>
<ul>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-core/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ast/Node.html#children()"><code>children</code></a> - returns a NodeStream containing all the children of this node.
Note: in PMD 6, this method returned an <code class="language-plaintext highlighter-rouge">Iterable</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-core/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ast/Node.html#descendants()"><code>descendants</code></a></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-core/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ast/Node.html#descendantsOrSelf()"><code>descendantsOrSelf</code></a></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-core/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ast/Node.html#ancestors()"><code>ancestors</code></a></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-core/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ast/Node.html#ancestorsOrSelf()"><code>ancestorsOrSelf</code></a></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-core/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ast/Node.html#children(java.lang.Class)"><code>children</code></a></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-core/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ast/Node.html#firstChild(java.lang.Class)"><code>firstChild</code></a></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-core/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ast/Node.html#descendants(java.lang.Class)"><code>descendants</code></a></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-core/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ast/Node.html#ancestors(java.lang.Class)"><code>ancestors</code></a></li>
</ul>
<p>Methods removed completely:</p>
<ul>
<li><code class="language-plaintext highlighter-rouge">getFirstParentOfAnyType(parentTypes)</code>: There is no direct replacement, but something along the lines:
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="n">ancestors</span><span class="o">()</span>
<span class="o">.</span><span class="na">filter</span><span class="o">(</span><span class="n">n</span> <span class="o">-&gt;</span> <span class="nc">Arrays</span><span class="o">.</span><span class="na">stream</span><span class="o">(</span><span class="n">classes</span><span class="o">)</span>
<span class="o">.</span><span class="na">anyMatch</span><span class="o">(</span><span class="n">c</span> <span class="o">-&gt;</span> <span class="n">c</span><span class="o">.</span><span class="na">isInstance</span><span class="o">(</span><span class="n">n</span><span class="o">)))</span>
<span class="o">.</span><span class="na">first</span><span class="o">();</span>
</code></pre></div> </div>
</li>
<li><code class="language-plaintext highlighter-rouge">findChildNodesWithXPath</code>: Has been removed, because it is very inefficient. Use NodeStream instead.</li>
<li><code class="language-plaintext highlighter-rouge">hasDescendantMatchingXPath</code>: Has been removed, because it is very inefficient. Use NodeStream instead.</li>
<li><code class="language-plaintext highlighter-rouge">jjt*</code> like <code class="language-plaintext highlighter-rouge">jjtGetParent</code>. These methods were implementation specific. Use the equivalent methods like <code class="language-plaintext highlighter-rouge">getParent()</code>.</li>
</ul>
<p>See <a href="https://docs.pmd-code.org/apidocs/pmd-core/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ast/Node.html#"><code>Node</code></a> for the details.</p>
<h3 id="nodestream-api">NodeStream API</h3>
<p>In java rule implementations, you often need to navigate the AST to find the interesting nodes. In PMD 6, this
was often done by calling <code class="language-plaintext highlighter-rouge">jjtGetChild(int)</code> or <code class="language-plaintext highlighter-rouge">jjtGetParent(int)</code> and then checking the node type
with <code class="language-plaintext highlighter-rouge">instanceof</code>. There are also helper methods available, like <code class="language-plaintext highlighter-rouge">getFirstChildOfType(Class)</code> or
<code class="language-plaintext highlighter-rouge">findDescendantsOfType(Class)</code>. These methods might return <code class="language-plaintext highlighter-rouge">null</code> and you need to check this for every
level.</p>
<p>The new <strong>NodeStream API</strong> provides easy to use methods that follow the Java Stream API (<code class="language-plaintext highlighter-rouge">java.util.stream</code>).</p>
<p>Many complex predicates about nodes can be expressed by testing the emptiness of a node stream.
E.g. the following tests if the node is a variable declarator id initialized to the value <code class="language-plaintext highlighter-rouge">0</code>:</p>
<p>Example:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nc">NodeStream</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="n">someNode</span><span class="o">)</span> <span class="c1">// the stream here is empty if the node is null</span>
<span class="o">.</span><span class="na">filterIs</span><span class="o">(</span><span class="nc">ASTVariableId</span><span class="o">.</span><span class="na">class</span><span class="o">)</span> <span class="c1">// the stream here is empty if the node was not a variable id</span>
<span class="o">.</span><span class="na">followingSiblings</span><span class="o">()</span> <span class="c1">// the stream here contains only the siblings, not the original node</span>
<span class="o">.</span><span class="na">children</span><span class="o">(</span><span class="nc">ASTNumericLiteral</span><span class="o">.</span><span class="na">class</span><span class="o">)</span>
<span class="o">.</span><span class="na">filter</span><span class="o">(</span><span class="nl">ASTNumericLiteral:</span><span class="o">:</span><span class="n">isIntLiteral</span><span class="o">)</span>
<span class="o">.</span><span class="na">filterMatching</span><span class="o">(</span><span class="nl">ASTNumericLiteral:</span><span class="o">:</span><span class="n">getValueAsInt</span><span class="o">,</span> <span class="mi">0</span><span class="o">)</span>
<span class="o">.</span><span class="na">nonEmpty</span><span class="o">();</span> <span class="c1">// If the stream is non empty here, then all the pipeline matched</span>
</code></pre></div></div>
<p>See <a href="https://docs.pmd-code.org/apidocs/pmd-core/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ast/NodeStream.html#"><code>NodeStream</code></a> for the details.
Note: This was implemented via <a href="https://github.com/pmd/pmd/pull/1622">PR #1622 [core] NodeStream API</a></p>
<h3 id="xpath-migrating-from-10-to-20">XPath: Migrating from 1.0 to 2.0</h3>
<p>XPath 1.0 and 2.0 have some incompatibilities. The <a href="https://www.w3.org/TR/xpath20/#id-incompat-in-false-mode">XPath 2.0 specification</a>
describes them precisely. Those are however mostly corner cases and XPath
rules usually dont feature any of them.</p>
<p>The incompatibilities that are most relevant to migrating your rules are not
caused by the specification, but by the different engines we use to run
XPath 1.0 and 2.0 queries. Heres a list of known incompatibilities:</p>
<ul>
<li>The namespace prefixes <code class="language-plaintext highlighter-rouge">fn:</code> and <code class="language-plaintext highlighter-rouge">string:</code> should not be mentioned explicitly.
In XPath 2.0 mode, the engine will complain about an undeclared namespace, but
the functions are in the default namespace. Removing the namespace prefixes fixes it.
<ul>
<li><code><b style="color:red">fn:</b>substring("Foo", 1)</code><code class="language-plaintext highlighter-rouge">substring("Foo", 1)</code></li>
</ul>
</li>
<li>Conversely, calls to custom PMD functions like <code class="language-plaintext highlighter-rouge">typeIs</code> <em>must</em> be prefixed
with the namespace of the declaring module (<code class="language-plaintext highlighter-rouge">pmd-java</code>).
<ul>
<li><code class="language-plaintext highlighter-rouge">typeIs("Foo")</code><code><b style="color:green">pmd-java:</b>typeIs("Foo")</code></li>
</ul>
</li>
<li>Boolean attribute values on our 1.0 engine are represented as the string values
<code class="language-plaintext highlighter-rouge">"true"</code> and <code class="language-plaintext highlighter-rouge">"false"</code>. In 2.0 mode though, boolean values are truly represented
as boolean values, which in XPath may only be obtained through the functions
<code class="language-plaintext highlighter-rouge">true()</code> and <code class="language-plaintext highlighter-rouge">false()</code>.
If your XPath 1.0 rule tests an attribute like <code class="language-plaintext highlighter-rouge">@Private="true"</code>, then it just
needs to be changed to <code class="language-plaintext highlighter-rouge">@Private=true()</code> when migrating. A type error will warn
you that you must update the comparison. More is explained on <a href="https://github.com/pmd/pmd/issues/1244">issue #1244</a>.
<ul>
<li><code class="language-plaintext highlighter-rouge">"true"</code>, <code class="language-plaintext highlighter-rouge">'true'</code><code class="language-plaintext highlighter-rouge">true()</code></li>
<li><code class="language-plaintext highlighter-rouge">"false"</code>, <code class="language-plaintext highlighter-rouge">'false'</code><code class="language-plaintext highlighter-rouge">false()</code></li>
</ul>
</li>
<li>In XPath 1.0, comparing a number to a string coerces the string to a number.
In XPath 2.0, a type error occurs. Like for boolean values, numeric values are
represented by our 1.0 implementation as strings, meaning that <code class="language-plaintext highlighter-rouge">@BeginLine &gt; "1"</code>
worked —thats not the case in 2.0 mode.
<ul>
<li><code>@ArgumentCount &gt; <b style="color:red">'</b>1<b style="color:red">'</b></code><code class="language-plaintext highlighter-rouge">@ArgumentCount &gt; 1</code></li>
</ul>
</li>
<li>In XPath 1.0, the expression <code class="language-plaintext highlighter-rouge">/Foo</code> matches the <em>children</em> of the root named <code class="language-plaintext highlighter-rouge">Foo</code>.
In XPath 2.0, that expression matches the root, if it is named <code class="language-plaintext highlighter-rouge">Foo</code>. Consider the following tree:
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">Foo</span>
<span class="err">└─</span> <span class="nc">Foo</span>
<span class="err">└─</span> <span class="nc">Foo</span>
</code></pre></div> </div>
<p>Then <code class="language-plaintext highlighter-rouge">/Foo</code> will match the root in XPath 2.0, and the other nodes (but not the root) in XPath 1.0.
See e.g. <a href="https://github.com/pmd/pmd/issues/1919#issuecomment-512865434">an issue caused by this</a> in Apex,
with nested classes.</p>
</li>
<li>The custom function “pmd:matches” which checks a regular expression against a string has been removed,
since there is a built-in function available since XPath 2.0 which can be used instead. If you use “pmd:matches”
simply remove the “pmd:” prefix.</li>
</ul>
<h3 id="general-ast-changes-to-avoid-image">General AST Changes to avoid @Image</h3>
<p>An abstract syntax tree should be abstract, but in the same time, should not be too abstract. One of the
base interfaces for PMDs AST for all languages is <a href="https://docs.pmd-code.org/apidocs/pmd-core/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ast/Node.html#"><code>Node</code></a>, which provides
the methods <a href="https://docs.pmd-code.org/apidocs/pmd-core/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ast/Node.html#getImage()"><code>getImage</code></a> and <a href="https://docs.pmd-code.org/apidocs/pmd-core/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ast/Node.html#hasImageEqualTo(java.lang.String)"><code>hasImageEqualTo</code></a>.
However, these methods dont necessarily make sense for all nodes in all contexts. Thats why <code class="language-plaintext highlighter-rouge">getImage()</code>
often returns just <code class="language-plaintext highlighter-rouge">null</code>. Also, the name is not very describing. AST nodes should try to use more specific
names, such as <code class="language-plaintext highlighter-rouge">getValue()</code> or <code class="language-plaintext highlighter-rouge">getName()</code>.</p>
<p>For PMD 7, most languages have been adapted. And when writing XPath rules, you need to replace <code class="language-plaintext highlighter-rouge">@Image</code> with
whatever is appropriate now (e.g. <code class="language-plaintext highlighter-rouge">@Name</code>). See below for details.</p>
<h4 id="apex-and-visualforce">Apex and Visualforce</h4>
<p>There are many usages of <code class="language-plaintext highlighter-rouge">@Image</code>. These will be refactored after PMD 7 is released
by deprecating the attribute and providing alternatives.</p>
<p>See also issue <a href="https://github.com/pmd/pmd/issues/4787">Deprecate getImage/@Image #4787</a>.</p>
<h4 id="html">Html</h4>
<ul>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-html/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/html/ast/ASTHtmlTextNode.html#"><code>ASTHtmlTextNode</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Text</code>, <code class="language-plaintext highlighter-rouge">@NormalizedText</code> ➡️ <code class="language-plaintext highlighter-rouge">@Text</code>, <code class="language-plaintext highlighter-rouge">@Text</code> ➡️ <code class="language-plaintext highlighter-rouge">@WholeText</code>.</li>
</ul>
<h4 id="java">Java</h4>
<p>There are still many usages of <code class="language-plaintext highlighter-rouge">@Image</code> which are not refactored yet. This will be done after PMD 7 is released
by deprecating the attribute and providing alternatives.</p>
<p>See also issue <a href="https://github.com/pmd/pmd/issues/4787">Deprecate getImage/@Image #4787</a>.</p>
<p>Some nodes have already the image attribute (and others) deprecated. These deprecated attributes are removed now:</p>
<ul>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTAnnotationTypeDeclaration.html#"><code>ASTAnnotationTypeDeclaration</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@SimpleName</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTAnonymousClassDeclaration.html#"><code>ASTAnonymousClassDeclaration</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@SimpleName</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTClassDeclaration.html#"><code>ASTClassDeclaration</code></a> (previously “ASTClassOrInterfaceDeclaration”): <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@SimpleName</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTEnumDeclaration.html#"><code>ASTEnumDeclaration</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@SimpleName</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTFieldDeclaration.html#"><code>ASTFieldDeclaration</code></a>: <code class="language-plaintext highlighter-rouge">@VariableName</code> ➡️ <code class="language-plaintext highlighter-rouge">VariableId/@Name</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTMethodDeclaration.html#"><code>ASTMethodDeclaration</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Name</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTMethodDeclaration.html#"><code>ASTMethodDeclaration</code></a>: <code class="language-plaintext highlighter-rouge">@MethodName</code> ➡️ <code class="language-plaintext highlighter-rouge">@Name</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTRecordDeclaration.html#"><code>ASTRecordDeclaration</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@SimpleName</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTVariableId.html#"><code>ASTVariableId</code></a> (previously “ASTVariableDeclaratorId”): <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Name</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTVariableId.html#"><code>ASTVariableId</code></a> (previously “ASTVariableDeclaratorId”): <code class="language-plaintext highlighter-rouge">@VariableName</code> ➡️ <code class="language-plaintext highlighter-rouge">@Name</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTVariableId.html#"><code>ASTVariableId</code></a> (previously “ASTVariableDeclaratorId”): <code class="language-plaintext highlighter-rouge">@Array</code> ➡️ <code class="language-plaintext highlighter-rouge">@ArrayType</code></li>
</ul>
<h4 id="javascript">JavaScript</h4>
<ul>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-javascript/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ecmascript/ast/ASTAssignment.html#"><code>ASTAssignment</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Operator</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-javascript/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ecmascript/ast/ASTBigIntLiteral.html#"><code>ASTBigIntLiteral</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Value</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-javascript/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ecmascript/ast/ASTBreakStatement.html#"><code>ASTBreakStatement</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">Name/@Identifier</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-javascript/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ecmascript/ast/ASTContinueStatement.html#"><code>ASTContinueStatement</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">Name/@Identifier</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-javascript/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ecmascript/ast/ASTErrorNode.html#"><code>ASTErrorNode</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Message</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-javascript/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ecmascript/ast/ASTFunctionNode.html#"><code>ASTFunctionNode</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">Name/@Identifier</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-javascript/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ecmascript/ast/ASTInfixExpression.html#"><code>ASTInfixExpression</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Operator</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-javascript/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ecmascript/ast/ASTKeywordLiteral.html#"><code>ASTKeywordLiteral</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Literal</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-javascript/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ecmascript/ast/ASTLabel.html#"><code>ASTLabel</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Name</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-javascript/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ecmascript/ast/ASTName.html#"><code>ASTName</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Identifier</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-javascript/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ecmascript/ast/ASTNumberLiteral.html#"><code>ASTNumberLiteral</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Value</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-javascript/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ecmascript/ast/ASTObjectProperty.html#"><code>ASTObjectProperty</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Operator</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-javascript/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ecmascript/ast/ASTPropertyGet.html#"><code>ASTPropertyGet</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Operator</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-javascript/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ecmascript/ast/ASTRegExpLiteral.html#"><code>ASTRegExpLiteral</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Value</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-javascript/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ecmascript/ast/ASTStringLiteral.html#"><code>ASTStringLiteral</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Value</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-javascript/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ecmascript/ast/ASTUnaryExpression.html#"><code>ASTUnaryExpression</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Operator</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-javascript/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ecmascript/ast/ASTUpdateExpression.html#"><code>ASTUpdateExpression</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Operator</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-javascript/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ecmascript/ast/ASTXmlDotQuery.html#"><code>ASTXmlDotQuery</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Operator</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-javascript/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ecmascript/ast/ASTXmlMemberGet.html#"><code>ASTXmlMemberGet</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Operator</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-javascript/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ecmascript/ast/ASTXmlPropRef.html#"><code>ASTXmlPropRef</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">Name[last()]/@Identifier</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-javascript/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/ecmascript/ast/ASTXmlString.html#"><code>ASTXmlString</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Xml</code></li>
</ul>
<h4 id="jsp">JSP</h4>
<ul>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-jsp/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/jsp/ast/ASTAttributeValue.html#"><code>ASTAttributeValue</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Value</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-jsp/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/jsp/ast/ASTCData.html#"><code>ASTCData</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Content</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-jsp/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/jsp/ast/ASTCommentTag.html#"><code>ASTCommentTag</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Content</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-jsp/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/jsp/ast/ASTElExpression.html#"><code>ASTElExpression</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Content</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-jsp/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/jsp/ast/ASTHtmlScript.html#"><code>ASTHtmlScript</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Content</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-jsp/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/jsp/ast/ASTJspComment.html#"><code>ASTJspComment</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Content</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-jsp/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/jsp/ast/ASTJspDeclaration.html#"><code>ASTJspDeclaration</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Content</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-jsp/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/jsp/ast/ASTJspExpression.html#"><code>ASTJspExpression</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Content</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-jsp/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/jsp/ast/ASTJspExpressionInAttribute.html#"><code>ASTJspExpressionInAttribute</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Content</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-jsp/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/jsp/ast/ASTJspScriptlet.html#"><code>ASTJspScriptlet</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Content</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-jsp/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/jsp/ast/ASTText.html#"><code>ASTText</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Content</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-jsp/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/jsp/ast/ASTUnparsedText.html#"><code>ASTUnparsedText</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Content</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-jsp/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/jsp/ast/ASTValueBinding.html#"><code>ASTValueBinding</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Content</code></li>
</ul>
<h4 id="modelica">Modelica</h4>
<ul>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-modelica/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/modelica/ast/ASTAddOp.html#"><code>ASTAddOp</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Operator</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-modelica/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/modelica/ast/ASTDerClassSpecifier.html#"><code>ASTDerClassSpecifier</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@SimpleClassName</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-modelica/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/modelica/ast/ASTEnumerationShortClassSpecifier.html#"><code>ASTEnumerationShortClassSpecifier</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@SimpleClassName</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-modelica/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/modelica/ast/ASTExtendingLongClassSpecifier.html#"><code>ASTExtendingLongClassSpecifier</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@SimpleClassName</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-modelica/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/modelica/ast/ASTFactor.html#"><code>ASTFactor</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Operator</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-modelica/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/modelica/ast/ASTLanguageSpecification.html#"><code>ASTLanguageSpecification</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@ExternalLanguage</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-modelica/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/modelica/ast/ASTMulOp.html#"><code>ASTMulOp</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Operator</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-modelica/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/modelica/ast/ASTName.html#"><code>ASTName</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Name</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-modelica/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/modelica/ast/ASTNumberLiteral.html#"><code>ASTNumberLiteral</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Value</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-modelica/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/modelica/ast/ASTRelOp.html#"><code>ASTRelOp</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Operator</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-modelica/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/modelica/ast/ASTSimpleLongClassSpecifier.html#"><code>ASTSimpleLongClassSpecifier</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@SimpleClassName</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-modelica/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/modelica/ast/ASTSimpleName.html#"><code>ASTSimpleName</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Name</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-modelica/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/modelica/ast/ASTSimpleShortClassSpecifier.html#"><code>ASTSimpleShortClassSpecifier</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@SimpleClassName</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-modelica/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/modelica/ast/ASTStoredDefinition.html#"><code>ASTStoredDefinition</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Name</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-modelica/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/modelica/ast/ASTStringComment.html#"><code>ASTStringComment</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Comment</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-modelica/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/modelica/ast/ASTStringLiteral.html#"><code>ASTStringLiteral</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Value</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-modelica/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/modelica/ast/ASTWithinClause.html#"><code>ASTWithinClause</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Name</code></li>
</ul>
<h4 id="plsql">PLSQL</h4>
<p>There are many usages of <code class="language-plaintext highlighter-rouge">@Image</code>. These will be refactored after PMD 7 is released
by deprecating the attribute and providing alternatives.</p>
<p>See also issue <a href="https://github.com/pmd/pmd/issues/4787">Deprecate getImage/@Image #4787</a>.</p>
<h4 id="scala">Scala</h4>
<ul>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-scala_2.13/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/scala/ast/ASTLitBoolean.html#"><code>ASTLitBoolean</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Value</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-scala_2.13/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/scala/ast/ASTLitByte.html#"><code>ASTLitByte</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Value</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-scala_2.13/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/scala/ast/ASTLitChar.html#"><code>ASTLitChar</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Value</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-scala_2.13/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/scala/ast/ASTLitDouble.html#"><code>ASTLitDouble</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Value</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-scala_2.13/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/scala/ast/ASTLitFloat.html#"><code>ASTLitFloat</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Value</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-scala_2.13/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/scala/ast/ASTLitInt.html#"><code>ASTLitInt</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Value</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-scala_2.13/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/scala/ast/ASTLitLong.html#"><code>ASTLitLong</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Value</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-scala_2.13/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/scala/ast/ASTLitNull.html#"><code>ASTLitNull</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Value</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-scala_2.13/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/scala/ast/ASTLitShort.html#"><code>ASTLitShort</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Value</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-scala_2.13/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/scala/ast/ASTLitString.html#"><code>ASTLitString</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Value</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-scala_2.13/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/scala/ast/ASTLitSymbol.html#"><code>ASTLitSymbol</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Value</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-scala_2.13/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/scala/ast/ASTLitUnit.html#"><code>ASTLitUnit</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Value</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-scala_2.13/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/scala/ast/ASTNameAnonymous.html#"><code>ASTNameAnonymous</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Value</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-scala_2.13/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/scala/ast/ASTNameIndeterminate.html#"><code>ASTNameIndeterminate</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Value</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-scala_2.13/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/scala/ast/ASTTermName.html#"><code>ASTTermName</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Value</code></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-scala_2.13/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/scala/ast/ASTTypeName.html#"><code>ASTTypeName</code></a>: <code class="language-plaintext highlighter-rouge">@Image</code> ➡️ <code class="language-plaintext highlighter-rouge">@Value</code></li>
</ul>
<h4 id="xml-and-pom">XML (and POM)</h4>
<p>When using <a href="https://docs.pmd-code.org/apidocs/pmd-core/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/rule/xpath/XPathRule.html#"><code>XPathRule</code></a>, text of text nodes was exposed as <code class="language-plaintext highlighter-rouge">@Image</code> of
normal element type nodes. Now the attribute is called <code class="language-plaintext highlighter-rouge">@Text</code>.</p>
<p>Note: In general, it is recommended to use <a href="https://docs.pmd-code.org/apidocs/pmd-xml/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/xml/rule/DomXPathRule.html#"><code>DomXPathRule</code></a> instead,
which exposes text nodes as real XPath/XML text nodes which conforms to the XPath spec.
There is no difference, text of text nodes can be selected using <code class="language-plaintext highlighter-rouge">text()</code>.</p>
<h3 id="java-ast">Java AST</h3>
<p>The Java grammar has been refactored substantially in order to make it easier to maintain and more correct
regarding the Java Language Specification.</p>
<p>Here you can see the most important changes as a comparison between the PMD 6 AST (“Old AST”) and
PMD 7 AST (“New AST”) and with some background info about the changes.</p>
<p>When in doubt, it is recommended to use the <a href="pmd_userdocs_extending_designer_reference.html">PMD Designer</a>
which can also display the AST.</p>
<h4 id="renamed-classes--interfaces">Renamed classes / interfaces</h4>
<ul>
<li>AccessNode ➡️ <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ModifierOwner.html#"><code>ModifierOwner</code></a></li>
<li>ClassOrInterfaceType ➡️ ClassType (<a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTClassType.html#"><code>ASTClassType</code></a>)</li>
<li>ClassOrInterfaceDeclaration ➡️ ClassDeclaration (<a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTClassDeclaration.html#"><code>ASTClassDeclaration</code></a>)</li>
<li>AnyTypeDeclaration ➡️ TypeDeclaration (<a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTTypeDeclaration.html#"><code>ASTTypeDeclaration</code></a>)</li>
<li>MethodOrConstructorDeclaration ➡️ ExecutableDeclaration (<a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTExecutableDeclaration.html#"><code>ASTExecutableDeclaration</code></a>)</li>
<li>VariableDeclaratorId ➡️ VariableId (<a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTVariableId.html#"><code>ASTVariableId</code></a>)</li>
<li>ClassOrInterfaceBody ➡️ ClassBody (<a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTClassBody.html#"><code>ASTClassBody</code></a>)</li>
</ul>
<h4 id="annotations">Annotations</h4>
<ul>
<li>What: Annotations are consolidated into a single node. <code class="language-plaintext highlighter-rouge">SingleMemberAnnotation</code>, <code class="language-plaintext highlighter-rouge">NormalAnnotation</code> and <code class="language-plaintext highlighter-rouge">MarkerAnnotation</code>
are removed in favour of <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTAnnotation.html#"><code>ASTAnnotation</code></a>. The Name node is removed, replaced by a
<a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTClassType.html#"><code>ASTClassType</code></a>.</li>
<li>Why: Those different node types implement a syntax-only distinction, that only makes semantically equivalent annotations
have different possible representations. For example, <code class="language-plaintext highlighter-rouge">@A</code> and <code class="language-plaintext highlighter-rouge">@A()</code> are semantically equivalent, yet they were
parsed as MarkerAnnotation resp. NormalAnnotation. Similarly, <code class="language-plaintext highlighter-rouge">@A("")</code> and <code class="language-plaintext highlighter-rouge">@A(value="")</code> were parsed as
SingleMemberAnnotation resp. NormalAnnotation. This also makes parsing much simpler. The nested ClassOrInterface
type is used to share the disambiguation logic.</li>
<li>Related issue: <a href="https://github.com/pmd/pmd/pull/2282">[java] Use single node for annotations (#2282)</a></li>
</ul>
<details>
<summary>Annotation AST Examples</summary>
<table>
<tr><th>Code</th><th>Old AST (PMD 6)</th><th>New AST (PMD 7)</th></tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@A</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">MarkerAnnotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ClassOrInterfaceType</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span></code></pre></figure>
</td></tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@A</span><span class="o">()</span></code></pre></figure>
</td>
<td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">NormalAnnotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span></code></pre></figure>
</td>
<td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">AnnotationMemberList</span></code></pre></figure>
</td>
</tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@A</span><span class="o">(</span><span class="n">value</span><span class="o">=</span><span class="s">"v"</span><span class="o">)</span></code></pre></figure>
</td>
<td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">NormalAnnotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">MemberValuePairs</span>
<span class="err">└─</span> <span class="nx">MemberValuePair</span> <span class="dl">"</span><span class="s2">value</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">MemberValue</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err">└─</span> <span class="nx">Literal</span> <span class="dl">'</span><span class="s1">"v"</span><span class="dl">'</span></code></pre></figure>
</td>
<td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">AnnotationMemberList</span>
<span class="err">└─</span> <span class="nx">MemberValuePair</span> <span class="dl">"</span><span class="s2">value</span><span class="dl">"</span> <span class="p">[</span> <span class="p">@</span><span class="nd">Shorthand</span> <span class="o">=</span> <span class="kc">false</span><span class="p">()</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">StringLiteral</span> <span class="dl">'</span><span class="s1">"v"</span><span class="dl">'</span></code></pre></figure>
</td>
</tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@A</span><span class="o">(</span><span class="s">"v"</span><span class="o">)</span></code></pre></figure>
</td>
<td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">SingleMemberAnnotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">MemberValue</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err">└─</span> <span class="nx">Literal</span> <span class="dl">'</span><span class="s1">"v"</span><span class="dl">'</span></code></pre></figure>
</td>
<td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">AnnotationMemberList</span>
<span class="err">└─</span> <span class="nx">MemberValuePair</span> <span class="dl">"</span><span class="s2">value</span><span class="dl">"</span> <span class="p">[</span> <span class="p">@</span><span class="nd">Shorthand</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">StringLiteral</span> <span class="dl">'</span><span class="s1">"v"</span><span class="dl">'</span></code></pre></figure>
</td>
</tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@A</span><span class="o">(</span><span class="n">value</span><span class="o">=</span><span class="s">"v"</span><span class="o">,</span> <span class="n">on</span><span class="o">=</span><span class="kc">true</span><span class="o">)</span></code></pre></figure>
</td>
<td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">NormalAnnotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">MemberValuePairs</span>
<span class="err">├─</span> <span class="nx">MemberValuePair</span> <span class="dl">"</span><span class="s2">value</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">MemberValue</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Literal</span> <span class="dl">'</span><span class="s1">"v"</span><span class="dl">'</span>
<span class="err">└─</span> <span class="nx">MemberValuePair</span> <span class="dl">"</span><span class="s2">on</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">MemberValue</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err">└─</span> <span class="nx">Literal</span>
<span class="err">└─</span> <span class="nx">BooleanLiteral</span> <span class="p">[</span> <span class="p">@</span><span class="nd">True</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span></code></pre></figure>
</td>
<td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">AnnotationMemberList</span>
<span class="err">├─</span> <span class="nx">MemberValuePair</span> <span class="dl">"</span><span class="s2">value</span><span class="dl">"</span> <span class="p">[</span> <span class="p">@</span><span class="nd">Shorthand</span> <span class="o">=</span> <span class="kc">false</span><span class="p">()</span> <span class="p">]</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">StringLiteral</span> <span class="dl">'</span><span class="s1">"v"</span><span class="dl">'</span>
<span class="err">└─</span> <span class="nx">MemberValuePair</span> <span class="dl">"</span><span class="s2">on</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">BooleanLiteral</span> <span class="p">[</span> <span class="p">@</span><span class="nd">True</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span></code></pre></figure>
</td>
</tr>
</table>
</details>
<h5 id="annotation-nesting">Annotation nesting</h5>
<ul>
<li>What: <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTAnnotation.html#"><code>ASTAnnotation</code></a>s are now nested within the node, to which they are applied to.
E.g. if a method is annotated, the Annotation node is now a child of a <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTModifierList.html#"><code>ASTModifierList</code></a>,
inside the <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTMethodDeclaration.html#"><code>ASTMethodDeclaration</code></a>.</li>
<li>Why: Fixes a lot of inconsistencies, where sometimes the annotations were inside the node, and sometimes just
somewhere in the parent, with no real structure.</li>
<li>Related issue: <a href="https://github.com/pmd/pmd/pull/1875">[java] Move annotations inside the node they apply to (#1875)</a></li>
</ul>
<details>
<summary>Annotation nesting Examples</summary>
<table>
<tr><th>Code</th><th>Old AST (PMD 6)</th><th>New AST (PMD 7)</th></tr>
<tr><td>
Method
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@A</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">set</span><span class="o">(</span><span class="kt">int</span> <span class="n">x</span><span class="o">)</span> <span class="o">{</span> <span class="o">}</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">ClassOrInterfaceBodyDeclaration</span>
<span class="err">├─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">MarkerAnnotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">MethodDeclaration</span>
<span class="err">├─</span> <span class="nx">ResultType</span><span class="p">[</span> <span class="p">@</span><span class="nd">Void</span> <span class="o">=</span> <span class="kc">true</span> <span class="p">]</span>
<span class="err">├─</span> <span class="p">...</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">MethodDeclaration</span>
<span class="err">├─</span> <span class="nx">ModifierList</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">VoidType</span>
<span class="err">├─</span> <span class="p">...</span></code></pre></figure>
</td></tr>
<tr><td>
Top-level type declaration
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@A</span> <span class="kd">class</span> <span class="nc">C</span> <span class="o">{}</span></code></pre></figure>
</td>
<td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">TypeDeclaration</span>
<span class="err">├─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">MarkerAnnotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ClassOrInterfaceDeclaration</span> <span class="dl">"</span><span class="s2">C</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ClassOrInterfaceBody</span></code></pre></figure>
</td>
<td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">ClassDeclaration</span>
<span class="err">├─</span> <span class="nx">ModifierList</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ClassBody</span></code></pre></figure>
</td>
</tr>
<tr><td>
Cast expression
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kt">var</span> <span class="n">x</span> <span class="o">=</span> <span class="o">(</span><span class="nd">@A</span> <span class="no">T</span><span class="o">.</span><span class="nd">@B</span> <span class="no">S</span><span class="o">)</span> <span class="n">expr</span><span class="o">;</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">CastExpression</span>
<span class="err">├─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">MarkerAnnotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">Type</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ReferenceType</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ClassOrInterfaceType</span> <span class="dl">"</span><span class="s2">T.S</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">B</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">MarkerAnnotation</span> <span class="dl">"</span><span class="s2">B</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">B</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">expr</span><span class="dl">"</span></code></pre></figure>
</td>
<td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">CastExpression</span>
<span class="err">├─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">S</span><span class="dl">"</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">T</span><span class="dl">"</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">B</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">B</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">VariableAccess</span> <span class="dl">"</span><span class="s2">expr</span><span class="dl">"</span></code></pre></figure>
</td></tr>
<tr><td>
Cast expression with intersection
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kt">var</span> <span class="n">x</span> <span class="o">=</span> <span class="o">(</span><span class="nd">@A</span> <span class="no">T</span> <span class="o">&amp;</span> <span class="no">S</span><span class="o">)</span> <span class="n">expr</span><span class="o">;</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">CastExpression</span>
<span class="err">├─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">MarkerAnnotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">Type</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ReferenceType</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ClassOrInterfaceType</span> <span class="dl">"</span><span class="s2">T</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">ReferenceType</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ClassOrInterfaceType</span> <span class="dl">"</span><span class="s2">S</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">expr</span><span class="dl">"</span></code></pre></figure>
</td>
<td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">CastExpression</span>
<span class="err">├─</span> <span class="nx">IntersectionType</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">T</span><span class="dl">"</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">S</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">VariableAccess</span> <span class="dl">"</span><span class="s2">expr</span><span class="dl">"</span></code></pre></figure>
Notice <code>@A</code> binds to <code>T</code>, not <code>T &amp; S</code>
</td></tr>
<tr><td>
Constructor call
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="k">new</span> <span class="nd">@A</span> <span class="no">T</span><span class="o">()</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">AllocationExpression</span>
<span class="err">├─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">MarkerAnnotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">ClassOrInterfaceType</span> <span class="dl">"</span><span class="s2">T</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">Arguments</span></code></pre></figure>
</td>
<td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">ConstructorCall</span>
<span class="err">├─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">T</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ArgumentList</span></code></pre></figure>
</td></tr>
<tr><td>
Array allocation
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="k">new</span> <span class="nd">@A</span> <span class="kt">int</span><span class="o">[</span><span class="mi">0</span><span class="o">]</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">AllocationExpression</span>
<span class="err">├─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">MarkerAnnotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">PrimitiveType</span> <span class="dl">"</span><span class="s2">int</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ArrayDimsAndInits</span>
<span class="err">└─</span> <span class="nx">Expression</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err">└─</span> <span class="nx">Literal</span> <span class="dl">"</span><span class="s2">0</span><span class="dl">"</span></code></pre></figure>
</td>
<td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">ArrayAllocation</span>
<span class="err">└─</span> <span class="nx">ArrayType</span>
<span class="err">├─</span> <span class="nx">PrimitiveType</span> <span class="dl">"</span><span class="s2">int</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ArrayDimensions</span>
<span class="err">└─</span> <span class="nx">ArrayDimExpr</span>
<span class="err">└─</span> <span class="nx">NumericLiteral</span> <span class="dl">"</span><span class="s2">0</span><span class="dl">"</span></code></pre></figure>
</td></tr>
<tr><td>
Array type
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@A</span> <span class="kt">int</span> <span class="nd">@B</span><span class="o">[]</span> <span class="n">x</span><span class="o">;</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">LocalVariableDeclaration</span>
<span class="err">├─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">MarkerAnnotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">Type</span><span class="p">[</span> <span class="p">@</span><span class="nd">ArrayType</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ReferenceType</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">PrimitiveType</span> <span class="dl">"</span><span class="s2">int</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">B</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">MarkerAnnotation</span> <span class="dl">"</span><span class="s2">B</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">B</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">VariableDeclarator</span>
<span class="err">└─</span> <span class="nx">VariableDeclaratorId</span> <span class="dl">"</span><span class="s2">x</span><span class="dl">"</span></code></pre></figure>
</td>
<td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">LocalVariableDeclaration</span>
<span class="err">├─</span> <span class="nx">ModifierList</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">ArrayType</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">PrimitiveType</span> <span class="dl">"</span><span class="s2">int</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ArrayDimensions</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ArrayTypeDim</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">B</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">B</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">VariableDeclarator</span>
<span class="err">└─</span> <span class="nx">VariableId</span> <span class="dl">"</span><span class="s2">x</span><span class="dl">"</span></code></pre></figure>
</td></tr>
<tr><td>
Type parameters
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="o">&lt;</span><span class="nd">@A</span> <span class="no">T</span><span class="o">,</span> <span class="nd">@B</span> <span class="no">S</span> <span class="kd">extends</span> <span class="nd">@C</span> <span class="nc">Object</span><span class="o">&gt;</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">TypeParameters</span>
<span class="err">├─</span> <span class="nx">TypeParameter</span> <span class="dl">"</span><span class="s2">T</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">MarkerAnnotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">TypeParameter</span> <span class="dl">"</span><span class="s2">S</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">B</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">MarkerAnnotation</span> <span class="dl">"</span><span class="s2">B</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">B</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">TypeBound</span>
<span class="err">├─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">C</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">MarkerAnnotation</span> <span class="dl">"</span><span class="s2">C</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">C</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ClassOrInterfaceType</span> <span class="dl">"</span><span class="s2">Object</span><span class="dl">"</span></code></pre></figure>
</td>
<td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">TypeParameters</span>
<span class="err">├─</span> <span class="nx">TypeParameter</span> <span class="dl">"</span><span class="s2">T</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">TypeParameter</span> <span class="dl">"</span><span class="s2">S</span><span class="dl">"</span> <span class="p">[</span> <span class="p">@</span><span class="nd">TypeBound</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">B</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">B</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">Object</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">C</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">C</span><span class="dl">"</span></code></pre></figure>
<ul>
<li>TypeParameter<em>s</em> now only can have TypeParameter as a child</li>
<li>Annotations that apply to the param are <em>in</em> the param</li>
<li>Annotations that apply to the bound are <em>in</em> the type</li>
<li>This removes the need for TypeBound, because annotations are cleanly placed.</li>
</ul>
</td></tr>
<tr><td>
Enum constants
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kd">enum</span> <span class="no">E</span> <span class="o">{</span>
<span class="nd">@A</span> <span class="no">E1</span><span class="o">,</span> <span class="nd">@B</span> <span class="no">E2</span><span class="o">;</span>
<span class="o">}</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">EnumBody</span>
<span class="err">├─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">MarkerAnnotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">EnumConstant</span> <span class="dl">"</span><span class="s2">E1</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">B</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">MarkerAnnotation</span> <span class="dl">"</span><span class="s2">B</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">B</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">EnumConstant</span> <span class="dl">"</span><span class="s2">E2</span><span class="dl">"</span></code></pre></figure>
</td>
<td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">EnumBody</span>
<span class="err">├─</span> <span class="nx">EnumConstant</span> <span class="dl">"</span><span class="s2">E1</span><span class="dl">"</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">ModifierList</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">VariableId</span> <span class="dl">"</span><span class="s2">E1</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">EnumConstant</span> <span class="dl">"</span><span class="s2">E2</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">ModifierList</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">B</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">B</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">VariableId</span> <span class="dl">"</span><span class="s2">E2</span><span class="dl">"</span></code></pre></figure>
<ul>
<li>Annotations are not just randomly in the enum body anymore</li>
</ul>
</td></tr>
</table>
</details>
<h4 id="types">Types</h4>
<h5 id="type-and-referencetype">Type and ReferenceType</h5>
<ul>
<li>What:
<ul>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTType.html#"><code>ASTType</code></a> and <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTReferenceType.html#"><code>ASTReferenceType</code></a> have been turned into
interfaces, implemented by <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTPrimitiveType.html#"><code>ASTPrimitiveType</code></a>, <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTClassType.html#"><code>ASTClassType</code></a>,
and the new node <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTArrayType.html#"><code>ASTArrayType</code></a>. This reduces the depth of the relevant
subtrees, and allows to explore them more easily and consistently.</li>
</ul>
</li>
<li>Why:
<ul>
<li>some syntactic contexts only allow reference types, other allow any kind of type. If you want to match all types
of a program, then matching Type would be the intuitive solution. But in 6.0.x, it wouldnt have sufficed,
since in some contexts, no Type node was pushed, only a ReferenceType</li>
<li>Regardless of the original syntactic context, any reference type <em>is</em> a type, and searching for ASTType should
yield all the types in the tree.</li>
<li>Using interfaces allows to abstract behaviour and make a nicer and safer API.</li>
</ul>
</li>
<li><strong>Migrating</strong>
<ul>
<li>There is currently no way to match abstract types (or interfaces) with XPath, so <code class="language-plaintext highlighter-rouge">Type</code>
and <code class="language-plaintext highlighter-rouge">ReferenceType</code> name tests wont match anything anymore.</li>
<li><code class="language-plaintext highlighter-rouge">Type/ReferenceType/ClassOrInterfaceType</code> ➡️ <code class="language-plaintext highlighter-rouge">ClassType</code></li>
<li><code class="language-plaintext highlighter-rouge">Type/PrimitiveType</code> ➡️ <code class="language-plaintext highlighter-rouge">PrimitiveType</code>.</li>
<li><code class="language-plaintext highlighter-rouge">Type/ReferenceType[@ArrayDepth &gt; 1]/ClassOrInterfaceType</code> ➡️ <code class="language-plaintext highlighter-rouge">ArrayType/ClassType</code>.</li>
<li><code class="language-plaintext highlighter-rouge">Type/ReferenceType/PrimitiveType</code> ➡️ <code class="language-plaintext highlighter-rouge">ArrayType/PrimitiveType</code>.</li>
<li>Note that in most cases you should check the type of a variable with e.g.
<code class="language-plaintext highlighter-rouge">VariableId[pmd-java:typeIs("java.lang.String[]")]</code> because it
considers the additional dimensions on declarations like <code class="language-plaintext highlighter-rouge">String foo[];</code>.
The Java equivalent is <code class="language-plaintext highlighter-rouge">TypeHelper.isA(id, String[].class);</code></li>
</ul>
</li>
</ul>
<details>
<summary>Type and ReferenceType Examples</summary>
<table>
<tr><th>Code</th><th>Old AST (PMD 6)</th><th>New AST (PMD 7)</th></tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="c1">// in the context of a variable declaration</span>
<span class="nc">List</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">&gt;</span> <span class="n">strs</span><span class="o">;</span></code></pre></figure>
</td>
<td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">Type</span> <span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="err">└─</span> <span class="nx">ReferenceType</span>
<span class="err">└─</span> <span class="nx">ClassOrInterfaceType</span> <span class="dl">"</span><span class="s2">List</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">TypeArguments</span>
<span class="err">└─</span> <span class="nx">TypeArgument</span>
<span class="err">└─</span> <span class="nx">ReferenceType</span> <span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="err">└─</span> <span class="nx">ClassOrInterfaceType</span> <span class="dl">"</span><span class="s2">String</span><span class="dl">"</span></code></pre></figure>
<ol>
<li>Notice that there is a Type node here, since a local var can have a primitive type.</li>
<li>In contrast, notice that there is no Type here, since only reference types are allowed as type arguments.</li>
</ol>
</td>
<td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">List</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">TypeArguments</span>
<span class="err">└─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">String</span><span class="dl">"</span></code></pre></figure>
<ul>
<li>ClassType implements ASTReferenceType, which implements ASTType.</li>
</ul>
</td>
</tr>
</table>
</details>
<h5 id="array-changes">Array changes</h5>
<ul>
<li>What: Additional nodes <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTArrayType.html#"><code>ASTArrayType</code></a>, <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTArrayTypeDim.html#"><code>ASTArrayTypeDim</code></a>,
<a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTArrayDimensions.html#"><code>ASTArrayDimensions</code></a>, <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTArrayAllocation.html#"><code>ASTArrayAllocation</code></a>.</li>
<li>Why: Support annotated array types (<a href="https://github.com/pmd/pmd/issues/997">[java] Java8 parsing corner case with annotated array types (#997)</a>)</li>
<li>Related issue: <a href="https://github.com/pmd/pmd/pull/1981">[java] Simplify array allocation expressions (#1981)</a></li>
</ul>
<details>
<summary>Array Examples</summary>
<table>
<tr><th>Code</th><th>Old AST (PMD 6)</th><th>New AST (PMD 7)</th></tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nc">String</span><span class="o">[][]</span> <span class="n">myArray</span><span class="o">;</span></code></pre></figure>
</td>
<td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">Type</span><span class="p">[</span> <span class="p">@</span><span class="nd">ArrayType</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">ReferenceType</span>
<span class="err">└─</span> <span class="nx">ClassOrInterfaceType</span><span class="p">[</span> <span class="p">@</span><span class="nd">Array</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">][</span> <span class="p">@</span><span class="nd">ArrayDepth</span> <span class="o">=</span> <span class="mi">2</span> <span class="p">]</span> <span class="dl">"</span><span class="s2">String</span><span class="dl">"</span></code></pre></figure>
</td>
<td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">ArrayType</span><span class="p">[</span> <span class="p">@</span><span class="nd">ArrayDepth</span> <span class="o">=</span> <span class="mi">2</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">String</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ArrayDimensions</span><span class="p">[</span> <span class="p">@</span><span class="nd">Size</span> <span class="o">=</span> <span class="mi">2</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">ArrayTypeDim</span>
<span class="err">└─</span> <span class="nx">ArrayTypeDim</span></code></pre></figure>
</td>
</tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nc">String</span> <span class="nd">@Annotation1</span><span class="o">[]</span> <span class="nd">@Annotation2</span><span class="o">[]</span> <span class="n">myArray</span><span class="o">;</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">Type</span><span class="p">[</span> <span class="p">@</span><span class="nd">ArrayType</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">ReferenceType</span>
<span class="err">├─</span> <span class="nx">ClassOrInterfaceType</span><span class="p">[</span> <span class="p">@</span><span class="nd">Array</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">][</span> <span class="p">@</span><span class="nd">ArrayDepth</span> <span class="o">=</span> <span class="mi">2</span> <span class="p">]</span> <span class="dl">"</span><span class="s2">String</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">Annotation1</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">MarkerAnnotation</span> <span class="dl">"</span><span class="s2">Annotation1</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">Annotation1</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">Annotation2</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">MarkerAnnotation</span> <span class="dl">"</span><span class="s2">Annotation2</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">Annotation2</span><span class="dl">"</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">ArrayType</span><span class="p">[</span> <span class="p">@</span><span class="nd">ArrayDepth</span> <span class="o">=</span> <span class="mi">2</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">String</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ArrayDimensions</span><span class="p">[</span> <span class="p">@</span><span class="nd">Size</span> <span class="o">=</span> <span class="mi">2</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">ArrayTypeDim</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">Annotation1</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">Annotation1</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ArrayTypeDim</span>
<span class="err">└─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">Annotation2</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">Annotation2</span><span class="dl">"</span></code></pre></figure>
</td></tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="k">new</span> <span class="kt">int</span><span class="o">[</span><span class="mi">2</span><span class="o">][];</span>
<span class="k">new</span> <span class="nd">@Bar</span> <span class="kt">int</span><span class="o">[</span><span class="mi">3</span><span class="o">][</span><span class="mi">2</span><span class="o">];</span>
<span class="k">new</span> <span class="nc">Foo</span><span class="o">[]</span> <span class="o">{</span> <span class="n">f</span><span class="o">,</span> <span class="n">g</span> <span class="o">};</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">AllocationExpression</span>
<span class="err">├─</span> <span class="nx">PrimitiveType</span> <span class="dl">"</span><span class="s2">int</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ArrayDimsAndInits</span><span class="p">[</span> <span class="p">@</span><span class="nd">ArrayDepth</span> <span class="o">=</span> <span class="mi">2</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">Expression</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err">└─</span> <span class="nx">Literal</span> <span class="dl">"</span><span class="s2">2</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">AllocationExpression</span>
<span class="err">├─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">Bar</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">MarkerAnnotation</span> <span class="dl">"</span><span class="s2">Bar</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">Bar</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">PrimitiveType</span> <span class="dl">"</span><span class="s2">int</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ArrayDimsAndInits</span><span class="p">[</span> <span class="p">@</span><span class="nd">ArrayDepth</span> <span class="o">=</span> <span class="mi">2</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">Expression</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Literal</span> <span class="dl">"</span><span class="s2">3</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">Expression</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err">└─</span> <span class="nx">Literal</span> <span class="dl">"</span><span class="s2">2</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">AllocationExpression</span>
<span class="err">├─</span> <span class="nx">ClassOrInterfaceType</span> <span class="dl">"</span><span class="s2">Foo</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ArrayDimsAndInits</span><span class="p">[</span> <span class="p">@</span><span class="nd">ArrayDepth</span> <span class="o">=</span> <span class="mi">1</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">ArrayInitializer</span>
<span class="err">├─</span> <span class="nx">VariableInitializer</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Expression</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">f</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">VariableInitializer</span>
<span class="err">└─</span> <span class="nx">Expression</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">g</span><span class="dl">"</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">ArrayAllocation</span><span class="p">[</span> <span class="p">@</span><span class="nd">ArrayDepth</span> <span class="o">=</span> <span class="mi">2</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">ArrayType</span><span class="p">[</span> <span class="p">@</span><span class="nd">ArrayDepth</span> <span class="o">=</span> <span class="mi">2</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">PrimitiveType</span> <span class="dl">"</span><span class="s2">int</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ArrayDimensions</span><span class="p">[</span> <span class="p">@</span><span class="nd">Size</span> <span class="o">=</span> <span class="mi">2</span><span class="p">]</span>
<span class="err">├─</span> <span class="nx">ArrayDimExpr</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">NumericLiteral</span> <span class="dl">"</span><span class="s2">2</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ArrayTypeDim</span>
<span class="err">└─</span> <span class="nx">ArrayAllocation</span><span class="p">[</span> <span class="p">@</span><span class="nd">ArrayDepth</span> <span class="o">=</span> <span class="mi">2</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">ArrayType</span><span class="p">[</span> <span class="p">@</span><span class="nd">Array</span> <span class="nx">Depth</span> <span class="o">=</span> <span class="mi">2</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">PrimitiveType</span> <span class="dl">"</span><span class="s2">int</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">Bar</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">Bar</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ArrayDimensions</span><span class="p">[</span> <span class="p">@</span><span class="nd">Size</span> <span class="o">=</span> <span class="mi">2</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">ArrayDimExpr</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">NumericLiteral</span> <span class="dl">"</span><span class="s2">3</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ArrayDimExpr</span>
<span class="err">└─</span> <span class="nx">NumericLiteral</span> <span class="dl">"</span><span class="s2">2</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ArrayAllocation</span><span class="p">[</span> <span class="p">@</span><span class="nd">ArrayDepth</span> <span class="o">=</span> <span class="mi">1</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">ArrayType</span><span class="p">[</span> <span class="p">@</span><span class="nd">ArrayDepth</span> <span class="o">=</span> <span class="mi">1</span> <span class="p">]</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">Foo</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ArrayDimensions</span><span class="p">[</span> <span class="p">@</span><span class="nd">Size</span> <span class="o">=</span> <span class="mi">1</span> <span class="p">]</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ArrayTypeDim</span>
<span class="err">└─</span> <span class="nx">ArrayInitializer</span><span class="p">[</span> <span class="p">@</span><span class="nd">Length</span> <span class="o">=</span> <span class="mi">2</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">VariableAccess</span> <span class="dl">"</span><span class="s2">f</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">VariableAccess</span> <span class="dl">"</span><span class="s2">g</span><span class="dl">"</span></code></pre></figure>
</td></tr>
</table>
</details>
<h5 id="classtype-nesting">ClassType nesting</h5>
<ul>
<li>What: <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTClassType.html#"><code>ASTClassType</code></a> (formerly ASTClassOrInterfaceType) appears to be left recursive now,
and encloses its qualifying type.</li>
<li>Why: To preserve the position of annotations and type arguments</li>
<li>Related issue: <a href="https://github.com/pmd/pmd/issues/1150">[java] ClassOrInterfaceType AST improvements (#1150)</a></li>
</ul>
<details>
<summary>ClassType Examples</summary>
<table>
<tr><th>Code</th><th>Old AST (PMD 6)</th><th>New AST (PMD 7)</th></tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nc">Map</span><span class="o">.</span><span class="na">Entry</span><span class="o">&lt;</span><span class="no">K</span><span class="o">,</span><span class="no">V</span><span class="o">&gt;</span></code></pre></figure>
</td>
<td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">ClassOrInterfaceType</span> <span class="dl">"</span><span class="s2">Map.Entry</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">TypeArguments</span>
<span class="err">├─</span> <span class="nx">TypeArgument</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ReferenceType</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ClassOrInterfaceType</span> <span class="dl">"</span><span class="s2">K</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">TypeArgument</span>
<span class="err">└─</span> <span class="nx">ReferenceType</span>
<span class="err">└─</span> <span class="nx">ClassOrInterfaceType</span> <span class="dl">"</span><span class="s2">V</span><span class="dl">"</span></code></pre></figure>
</td>
<td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">Entry</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">Map</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">TypeArguments</span><span class="p">[</span> <span class="p">@</span><span class="nd">Size</span> <span class="o">=</span> <span class="mi">2</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">K</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">V</span><span class="dl">"</span></code></pre></figure>
</td>
</tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nc">First</span><span class="o">&lt;</span><span class="no">K</span><span class="o">&gt;.</span><span class="na">Second</span><span class="o">.</span><span class="na">Third</span><span class="o">&lt;</span><span class="no">V</span><span class="o">&gt;</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">ClassOrInterfaceType</span> <span class="dl">"</span><span class="s2">First.Second.Third</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">TypeArguments</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">TypeArgument</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ReferenceType</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ClassOrInterfaceType</span> <span class="dl">"</span><span class="s2">K</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">TypeArguments</span>
<span class="err">└─</span> <span class="nx">TypeArgument</span>
<span class="err">└─</span> <span class="nx">ReferenceType</span>
<span class="err">└─</span> <span class="nx">ClassOrInterfaceType</span> <span class="dl">"</span><span class="s2">V</span><span class="dl">"</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">Third</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">Second</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">First</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">TypeArguments</span><span class="p">[</span> <span class="p">@</span><span class="nd">Size</span> <span class="o">=</span> <span class="mi">1</span><span class="p">]</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">K</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">TypeArguments</span><span class="p">[</span> <span class="p">@</span><span class="nd">Size</span> <span class="o">=</span> <span class="mi">1</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">V</span><span class="dl">"</span></code></pre></figure>
</td></tr>
</table>
</details>
<h5 id="typeargument-and-wildcardtype">TypeArgument and WildcardType</h5>
<ul>
<li>What:
<ul>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-java/7.2.0/net/sourceforge/pmd/lang/java/ast/ASTTypeArgument.html#"><code>ASTTypeArgument</code></a> is removed. Instead, the <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTTypeArguments.html#"><code>ASTTypeArguments</code></a> node contains directly
a sequence of <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTType.html#"><code>ASTType</code></a> nodes. To support this, the new node type <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTWildcardType.html#"><code>ASTWildcardType</code></a>
captures the syntax previously parsed as a TypeArgument.</li>
<li>The <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.2.0/net/sourceforge/pmd/lang/java/ast/ASTWildcardBounds.html#"><code>ASTWildcardBounds</code></a> node is removed. Instead, the bound is a direct child of the WildcardType.</li>
</ul>
</li>
<li>Why: Because wildcard types are types in their own right, and having a node to represent them skims several levels
of nesting off.</li>
</ul>
<details>
<summary>TypeArgument and WildcardType Examples</summary>
<table>
<tr><th>Code</th><th>Old AST (PMD 6)</th><th>New AST (PMD 7)</th></tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nc">Entry</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="o">?</span> <span class="kd">extends</span> <span class="nc">Node</span><span class="o">&gt;</span></code></pre></figure>
</td>
<td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">ClassOrInterfaceType</span> <span class="dl">"</span><span class="s2">Entry</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">TypeArguments</span>
<span class="err">├─</span> <span class="nx">TypeArgument</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ReferenceType</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ClassOrInterfaceType</span> <span class="dl">"</span><span class="s2">String</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">TypeArgument</span><span class="p">[</span> <span class="p">@</span><span class="nd">Wildcard</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">WildcardBounds</span><span class="p">[</span> <span class="p">@</span><span class="nd">UpperBound</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">ReferenceType</span>
<span class="err">└─</span> <span class="nx">ClassOrInterfaceType</span> <span class="dl">"</span><span class="s2">Node</span><span class="dl">"</span></code></pre></figure>
</td>
<td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">Entry</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">TypeArguments</span><span class="p">[</span> <span class="p">@</span><span class="nd">Size</span> <span class="o">=</span> <span class="mi">2</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">String</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">WildcardType</span><span class="p">[</span> <span class="p">@</span><span class="nd">UpperBound</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">Node</span><span class="dl">"</span></code></pre></figure>
</td>
</tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nc">List</span><span class="o">&lt;?&gt;</span></code></pre></figure>
</td>
<td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">ClassOrInterfaceType</span> <span class="dl">"</span><span class="s2">List</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">TypeArguments</span>
<span class="err">└─</span> <span class="nx">TypeArgument</span><span class="p">[</span> <span class="p">@</span><span class="nd">Wildcard</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span></code></pre></figure>
</td>
<td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">List</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">TypeArguments</span><span class="p">[</span> <span class="p">@</span><span class="nd">Size</span> <span class="o">=</span> <span class="mi">1</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">WildcardType</span><span class="p">[</span> <span class="p">@</span><span class="nd">UpperBound</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span></code></pre></figure>
</td>
</tr>
</table>
</details>
<h4 id="declarations">Declarations</h4>
<h5 id="import-and-package-declarations">Import and Package declarations</h5>
<ul>
<li>What: Remove the Name node in imports and package declaration nodes.</li>
<li>Why: Name is a TypeNode, but its equivalent to <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTAmbiguousName.html#"><code>ASTAmbiguousName</code></a> in that it describes nothing
about what it represents. The name in an import may represent a method name, a type name, a field name…
Its too ambiguous to treat in the parser and could just be the image of the import, or package, or module.</li>
<li>Related issue: <a href="https://github.com/pmd/pmd/pull/1888">[java] Remove Name nodes in Import- and PackageDeclaration (#1888)</a></li>
</ul>
<details>
<summary>Import and Package declarations Examples</summary>
<table>
<tr><th>Code</th><th>Old AST (PMD 6)</th><th>New AST (PMD 7)</th></tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kn">import</span> <span class="nn">java.util.ArrayList</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">static</span> <span class="n">java</span><span class="o">.</span><span class="na">util</span><span class="o">.</span><span class="na">Comparator</span><span class="o">.</span><span class="na">reverseOrder</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.*</span><span class="o">;</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">├─</span> <span class="nx">ImportDeclaration</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">java.util.ArrayList</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">ImportDeclaration</span><span class="p">[</span> <span class="p">@</span><span class="nd">Static</span><span class="o">=</span><span class="kc">true</span><span class="p">()</span> <span class="p">]</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">java.util.Comparator.reverseOrder</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ImportDeclaration</span><span class="p">[</span> <span class="p">@</span><span class="nd">ImportOnDemand</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">java.util</span><span class="dl">"</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">├─</span> <span class="nx">ImportDeclaration</span> <span class="dl">"</span><span class="s2">java.util.ArrayList</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">ImportDeclaration</span><span class="p">[</span> <span class="p">@</span><span class="nd">Static</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span> <span class="dl">"</span><span class="s2">java.util.Comparator.reverseOrder</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ImportDeclaration</span><span class="p">[</span> <span class="p">@</span><span class="nd">ImportOnDemand</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span> <span class="dl">"</span><span class="s2">java.util</span><span class="dl">"</span></code></pre></figure>
</td></tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kn">package</span> <span class="nn">com.example.tool</span><span class="o">;</span></code></pre></figure>
</td>
<td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">PackageDeclaration</span>
<span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">com.example.tool</span><span class="dl">"</span></code></pre></figure>
</td>
<td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">PackageDeclaration</span> <span class="dl">"</span><span class="s2">com.example.tool</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ModifierList</span></code></pre></figure>
</td></tr>
</table>
</details>
<h5 id="modifier-lists">Modifier lists</h5>
<ul>
<li>What: <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ModifierOwner.html#"><code>ModifierOwner</code></a> (formerly AccessNode) is now based on a node: <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTModifierList.html#"><code>ASTModifierList</code></a>.
That node represents
modifiers occurring before a declaration. It provides a flexible API to query modifiers, both explicit and
implicit. All declaration nodes now have such a modifier list, even if its implicit (no explicit modifiers).</li>
<li>Why: ModifierOwner (formerly AccessNode) gave a lot of irrelevant methods to its subtypes.
E.g. <code class="language-plaintext highlighter-rouge">ASTFieldDeclaration::isSynchronized</code>
makes no sense. Now, these irrelevant methods dont clutter the API. The API of ModifierList is both more
general and flexible.</li>
<li>Related issue: <a href="https://github.com/pmd/pmd/pull/2259">[java] Rework AccessNode (#2259)</a></li>
</ul>
<details>
<summary>Modifier lists Examples</summary>
<table>
<tr><th>Code</th><th>Old AST (PMD 6)</th><th>New AST (PMD 7)</th></tr>
<tr><td>
Method
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@A</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">set</span><span class="o">(</span><span class="kd">final</span> <span class="kt">int</span> <span class="n">x</span><span class="o">,</span> <span class="kt">int</span> <span class="n">y</span><span class="o">)</span> <span class="o">{</span> <span class="o">}</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">ClassOrInterfaceBodyDeclaration</span>
<span class="err">├─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">MarkerAnnotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">MethodDeclaration</span><span class="p">[</span> <span class="p">@</span><span class="nd">Public</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span> <span class="dl">"</span><span class="s2">set</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">ResultType</span><span class="p">[</span> <span class="p">@</span><span class="nd">Void</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">MethodDeclarator</span>
<span class="err">└─</span> <span class="nx">FormalParameters</span><span class="p">[</span> <span class="p">@</span><span class="nd">Size</span> <span class="o">=</span> <span class="mi">2</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">FormalParameter</span><span class="p">[</span> <span class="p">@</span><span class="nd">Final</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">Type</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">PrimitiveType</span> <span class="dl">"</span><span class="s2">int</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">VariableDeclaratorId</span> <span class="dl">"</span><span class="s2">x</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">FormalParameter</span><span class="p">[</span> <span class="p">@</span><span class="nd">Final</span> <span class="o">=</span> <span class="kc">false</span><span class="p">()</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">Type</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">PrimitiveType</span> <span class="dl">"</span><span class="s2">int</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">VariableDeclaratorId</span> <span class="dl">"</span><span class="s2">y</span><span class="dl">"</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">MethodDeclaration</span><span class="p">[</span> <span class="nx">pmd</span><span class="o">-</span><span class="nx">java</span><span class="p">:</span><span class="nx">modifiers</span><span class="p">()</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">public</span><span class="dl">'</span> <span class="p">]</span> <span class="dl">"</span><span class="s2">set</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">ModifierList</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">VoidType</span>
<span class="err">└─</span> <span class="nx">FormalParameters</span>
<span class="err">├─</span> <span class="nx">FormalParameter</span><span class="p">[</span> <span class="nx">pmd</span><span class="o">-</span><span class="nx">java</span><span class="p">:</span><span class="nx">modifiers</span><span class="p">()</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">final</span><span class="dl">'</span> <span class="p">]</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">ModifierList</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">VariableId</span> <span class="dl">"</span><span class="s2">x</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">FormalParameter</span><span class="p">[</span> <span class="nx">pmd</span><span class="o">-</span><span class="nx">java</span><span class="p">:</span><span class="nx">modifiers</span><span class="p">()</span> <span class="o">=</span> <span class="p">()</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">ModifierList</span>
<span class="err">└─</span> <span class="nx">VariableId</span> <span class="dl">"</span><span class="s2">y</span><span class="dl">"</span></code></pre></figure>
</td></tr>
<tr><td>
Top-level type declaration
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kd">public</span> <span class="nd">@A</span> <span class="kd">class</span> <span class="nc">C</span> <span class="o">{}</span></code></pre></figure>
</td>
<td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">TypeDeclaration</span>
<span class="err">├─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">MarkerAnnotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ClassOrInterfaceDeclaration</span><span class="p">[</span> <span class="p">@</span><span class="nd">Public</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span> <span class="dl">"</span><span class="s2">C</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ClassOrInterfaceBody</span></code></pre></figure>
</td>
<td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">ClassDeclaration</span><span class="p">[</span> <span class="nx">pmd</span><span class="o">-</span><span class="nx">java</span><span class="p">:</span><span class="nx">modifiers</span><span class="p">()</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">public</span><span class="dl">'</span> <span class="p">]</span> <span class="dl">"</span><span class="s2">C</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">ModifierList</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ClassBody</span></code></pre></figure>
</td>
</tr>
</table>
</details>
<h5 id="flattened-body-declarations">Flattened body declarations</h5>
<ul>
<li>What: Removes <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.2.0/net/sourceforge/pmd/lang/java/ast/ASTClassOrInterfaceBodyDeclaration.html#"><code>ASTClassOrInterfaceBodyDeclaration</code></a>, <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.2.0/net/sourceforge/pmd/lang/java/ast/ASTTypeDeclaration.html#"><code>ASTTypeDeclaration</code></a>,
and <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.2.0/net/sourceforge/pmd/lang/java/ast/ASTAnnotationTypeMemberDeclaration.html#"><code>ASTAnnotationTypeMemberDeclaration</code></a>.
These were unnecessary since annotations are nested (see above <a href="#annotation-nesting">Annotation nesting</a>).</li>
<li>Why: This flattens the tree, makes it less verbose and simpler.</li>
<li>Related issue: <a href="https://github.com/pmd/pmd/pull/2300">[java] Flatten body declarations (#2300)</a></li>
</ul>
<details>
<summary>Flattened body declarations Examples</summary>
<table>
<tr><th>Code</th><th>Old AST (PMD 6)</th><th>New AST (PMD 7)</th></tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kd">public</span> <span class="kd">class</span> <span class="nc">Flat</span> <span class="o">{</span>
<span class="kd">private</span> <span class="kt">int</span> <span class="n">f</span><span class="o">;</span>
<span class="o">}</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">CompilationUnit</span>
<span class="err">└─</span> <span class="nx">TypeDeclaration</span>
<span class="err">└─</span> <span class="nx">ClassOrInterfaceDeclaration</span> <span class="dl">"</span><span class="s2">Flat</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ClassOrInterfaceBody</span>
<span class="err">└─</span> <span class="nx">ClassOrInterfaceBodyDeclaration</span>
<span class="err">└─</span> <span class="nx">FieldDeclaration</span>
<span class="err">├─</span> <span class="nx">Type</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">PrimitiveType</span> <span class="dl">"</span><span class="s2">int</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">VariableDeclarator</span>
<span class="err">└─</span> <span class="nx">VariableDeclaratorId</span> <span class="dl">"</span><span class="s2">f</span><span class="dl">"</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">CompilationUnit</span>
<span class="err">└─</span> <span class="nx">ClassDeclaration</span> <span class="dl">"</span><span class="s2">Flat</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">ModifierList</span>
<span class="err">└─</span> <span class="nx">ClassBody</span>
<span class="err">└─</span> <span class="nx">FieldDeclaration</span>
<span class="err">├─</span> <span class="nx">ModifierList</span>
<span class="err">├─</span> <span class="nx">PrimitiveType</span> <span class="dl">"</span><span class="s2">int</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">VariableDeclarator</span>
<span class="err">└─</span> <span class="nx">VariableId</span> <span class="dl">"</span><span class="s2">f</span><span class="dl">"</span></code></pre></figure>
</td></tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kd">public</span> <span class="nd">@interface</span> <span class="nc">FlatAnnotation</span> <span class="o">{</span>
<span class="nc">String</span> <span class="nf">value</span><span class="o">()</span> <span class="k">default</span> <span class="s">""</span><span class="o">;</span>
<span class="o">}</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">CompilationUnit</span>
<span class="err">└─</span> <span class="nx">TypeDeclaration</span>
<span class="err">└─</span> <span class="nx">AnnotationTypeDeclaration</span> <span class="dl">"</span><span class="s2">FlatAnnotation</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">AnnotationTypeBody</span>
<span class="err">└─</span> <span class="nx">AnnotationTypeMemberDeclaration</span>
<span class="err">└─</span> <span class="nx">AnnotationMethodDeclaration</span> <span class="dl">"</span><span class="s2">value</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">Type</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ReferenceType</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ClassOrInterfaceType</span> <span class="dl">"</span><span class="s2">String</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">DefaultValue</span>
<span class="err">└─</span> <span class="nx">MemberValue</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err">└─</span> <span class="nx">Literal</span> <span class="dl">"</span><span class="se">\"\"</span><span class="dl">"</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">CompilationUnit</span>
<span class="err">└─</span> <span class="nx">AnnotationTypeDeclaration</span> <span class="dl">"</span><span class="s2">FlatAnnotation</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">ModifierList</span>
<span class="err">└─</span> <span class="nx">AnnotationTypeBody</span>
<span class="err">└─</span> <span class="nx">MethodDeclaration</span> <span class="dl">"</span><span class="s2">value</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">ModifierList</span>
<span class="err">├─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">String</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">FormalParameters</span>
<span class="err">└─</span> <span class="nx">DefaultValue</span>
<span class="err">└─</span> <span class="nx">StringLiteral</span> <span class="dl">"</span><span class="se">\"\"</span><span class="dl">"</span></code></pre></figure>
</td></tr>
</table>
</details>
<h5 id="module-declarations">Module declarations</h5>
<ul>
<li>What: Removes the generic Name node and uses instead <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTClassType.html#"><code>ASTClassType</code></a> where appropriate. Also
uses specific node types for different directives (requires, exports, uses, provides).</li>
<li>Why: Simplify queries, support type resolution</li>
<li>Related issue: <a href="https://github.com/pmd/pmd/pull/3890">[java] Improve module grammar (#3890)</a></li>
</ul>
<details>
<summary>Module declarations Examples</summary>
<table>
<tr><th>Code</th><th>Old AST (PMD 6)</th><th>New AST (PMD 7)</th></tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="n">open</span> <span class="n">module</span> <span class="n">com</span><span class="o">.</span><span class="na">example</span><span class="o">.</span><span class="na">foo</span> <span class="o">{</span>
<span class="n">requires</span> <span class="n">com</span><span class="o">.</span><span class="na">example</span><span class="o">.</span><span class="na">foo</span><span class="o">.</span><span class="na">http</span><span class="o">;</span>
<span class="n">requires</span> <span class="n">java</span><span class="o">.</span><span class="na">logging</span><span class="o">;</span>
<span class="n">requires</span> <span class="n">transitive</span> <span class="n">com</span><span class="o">.</span><span class="na">example</span><span class="o">.</span><span class="na">foo</span><span class="o">.</span><span class="na">network</span><span class="o">;</span>
<span class="n">exports</span> <span class="n">com</span><span class="o">.</span><span class="na">example</span><span class="o">.</span><span class="na">foo</span><span class="o">.</span><span class="na">bar</span><span class="o">;</span>
<span class="n">exports</span> <span class="n">com</span><span class="o">.</span><span class="na">example</span><span class="o">.</span><span class="na">foo</span><span class="o">.</span><span class="na">internal</span> <span class="n">to</span> <span class="n">com</span><span class="o">.</span><span class="na">example</span><span class="o">.</span><span class="na">foo</span><span class="o">.</span><span class="na">probe</span><span class="o">;</span>
<span class="n">uses</span> <span class="n">com</span><span class="o">.</span><span class="na">example</span><span class="o">.</span><span class="na">foo</span><span class="o">.</span><span class="na">spi</span><span class="o">.</span><span class="na">Intf</span><span class="o">;</span>
<span class="n">provides</span> <span class="n">com</span><span class="o">.</span><span class="na">example</span><span class="o">.</span><span class="na">foo</span><span class="o">.</span><span class="na">spi</span><span class="o">.</span><span class="na">Intf</span> <span class="n">with</span> <span class="n">com</span><span class="o">.</span><span class="na">example</span><span class="o">.</span><span class="na">foo</span><span class="o">.</span><span class="na">Impl</span><span class="o">;</span>
<span class="o">}</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">CompilationUnit</span>
<span class="err">└─</span> <span class="nx">ModuleDeclaration</span><span class="p">[</span> <span class="p">@</span><span class="nd">Image</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">com.example.foo</span><span class="dl">'</span> <span class="p">][</span> <span class="p">@</span><span class="nd">Open</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">ModuleDirective</span><span class="p">[</span> <span class="p">@</span><span class="nd">Type</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">REQUIRES</span><span class="dl">'</span> <span class="p">]</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ModuleName</span><span class="p">[</span> <span class="p">@</span><span class="nd">Image</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">com.example.foo.http</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">ModuleDirective</span><span class="p">[</span> <span class="p">@</span><span class="nd">Type</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">REQUIRES</span><span class="dl">'</span> <span class="p">]</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ModuleName</span><span class="p">[</span> <span class="p">@</span><span class="nd">Image</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">java.logging</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">ModuleDirective</span><span class="p">[</span> <span class="p">@</span><span class="nd">Type</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">REQUIRES</span><span class="dl">'</span> <span class="p">][</span> <span class="p">@</span><span class="nd">RequiresModifier</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">TRANSITIVE</span><span class="dl">'</span> <span class="p">]</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ModuleName</span><span class="p">[</span> <span class="p">@</span><span class="nd">Image</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">com.example.foo.network</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">ModuleDirective</span><span class="p">[</span> <span class="p">@</span><span class="nd">Type</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">EXPORTS</span><span class="dl">'</span> <span class="p">]</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Name</span><span class="p">[</span> <span class="p">@</span><span class="nd">Image</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">com.example.foo.bar</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">ModuleDirective</span><span class="p">[</span> <span class="p">@</span><span class="nd">Type</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">EXPORTS</span><span class="dl">'</span> <span class="p">]</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">Name</span><span class="p">[</span> <span class="p">@</span><span class="nd">Image</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">com.example.foo.internal</span><span class="dl">'</span> <span class="p">]</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ModuleName</span><span class="p">[</span> <span class="p">@</span><span class="nd">Image</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">com.example.foo.probe</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">ModuleDirective</span><span class="p">[</span> <span class="p">@</span><span class="nd">Type</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">USES</span><span class="dl">'</span> <span class="p">]</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Name</span><span class="p">[</span> <span class="p">@</span><span class="nd">Image</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">com.example.foo.spi.Intf</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">ModuleDirective</span><span class="p">[</span> <span class="p">@</span><span class="nd">Type</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">PROVIDES</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">Name</span><span class="p">[</span> <span class="p">@</span><span class="nd">Image</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">com.example.foo.spi.Intf</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">Name</span><span class="p">[</span> <span class="p">@</span><span class="nd">Image</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">com.example.foo.Impl</span><span class="dl">'</span> <span class="p">]</span></code></pre></figure>
</td>
<td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">CompilationUnit</span>
<span class="err">└─</span> <span class="nx">ModuleDeclaration</span><span class="p">[</span> <span class="p">@</span><span class="nd">Name</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">com.example.foo</span><span class="dl">'</span> <span class="p">][</span> <span class="p">@</span><span class="nd">Open</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">ModuleName</span><span class="p">[</span> <span class="p">@</span><span class="nd">Name</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">com.example.foo</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">ModuleRequiresDirective</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ModuleName</span><span class="p">[</span> <span class="p">@</span><span class="nd">Name</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">com.example.foo.http</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">ModuleRequiresDirective</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ModuleName</span><span class="p">[</span> <span class="p">@</span><span class="nd">Name</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">java.logging</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">ModuleRequiresDirective</span><span class="p">[</span> <span class="p">@</span><span class="nd">Transitive</span> <span class="o">=</span> <span class="kc">true</span> <span class="p">]</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ModuleName</span><span class="p">[</span> <span class="p">@</span><span class="nd">Name</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">com.example.foo.network</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">ModuleExportsDirective</span><span class="p">[</span> <span class="p">@</span><span class="nd">PackageName</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">com.example.foo.bar</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">ModuleExportsDirective</span><span class="p">[</span> <span class="p">@</span><span class="nd">PackageName</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">com.example.foo.internal</span><span class="dl">'</span> <span class="p">]</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ModuleName</span> <span class="p">[</span> <span class="p">@</span><span class="nd">Name</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">com.example.foo.probe</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">ModuleUsesDirective</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ClassType</span><span class="p">[</span> <span class="nx">pmd</span><span class="o">-</span><span class="nx">java</span><span class="p">:</span><span class="nx">typeIs</span><span class="p">(</span><span class="dl">"</span><span class="s2">com.example.foo.spi.Intf</span><span class="dl">"</span><span class="p">)</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">ModuleProvidesDirective</span>
<span class="err">├─</span> <span class="nx">ClassType</span><span class="p">[</span> <span class="nx">pmd</span><span class="o">-</span><span class="nx">java</span><span class="p">:</span><span class="nx">typeIs</span><span class="p">(</span><span class="dl">"</span><span class="s2">com.example.foo.spi.Intf</span><span class="dl">"</span><span class="p">)</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">ClassType</span><span class="p">[</span> <span class="nx">pmd</span><span class="o">-</span><span class="nx">java</span><span class="p">:</span><span class="nx">typeIs</span><span class="p">(</span><span class="dl">"</span><span class="s2">com.example.foo.Impl</span><span class="dl">"</span><span class="p">)</span> <span class="p">]</span></code></pre></figure>
</td></tr>
</table>
</details>
<h5 id="anonymous-class-declarations">Anonymous class declarations</h5>
<ul>
<li>What: A separate node type <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTAnonymousClassDeclaration.html#"><code>ASTAnonymousClassDeclaration</code></a> is introduced for anonymous classes.</li>
<li>Why: Unify the AST for type declarations including anonymous class declaration in constructor calls
and enums.</li>
<li>Related issues:
<ul>
<li><a href="https://github.com/pmd/pmd/issues/905">[java] Add new node for anonymous class declaration (#905)</a></li>
<li><a href="https://github.com/pmd/pmd/pull/1759">[java] New expression and type grammar (#1759)</a></li>
</ul>
</li>
</ul>
<details>
<summary>Anonymous class declarations Examples</summary>
<table>
<tr><th>Code</th><th>Old AST (PMD 6)</th><th>New AST (PMD 7)</th></tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nc">Object</span> <span class="n">anonymous</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Object</span><span class="o">()</span> <span class="o">{</span> <span class="o">};</span></code></pre></figure>
</td>
<td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">LocalVariableDeclaration</span>
<span class="err">├─</span> <span class="nx">Type</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ReferenceType</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ClassOrInterfaceType</span><span class="p">[</span> <span class="p">@</span><span class="nd">Image</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">Object</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">VariableDeclarator</span>
<span class="err">├─</span> <span class="nx">VariableDeclaratorId</span> <span class="dl">"</span><span class="s2">anonymous</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">VariableInitializer</span>
<span class="err">└─</span> <span class="nx">Expression</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err">└─</span> <span class="nx">AllocationExpression</span>
<span class="err">├─</span> <span class="nx">ClassOrInterfaceType</span><span class="p">[</span> <span class="p">@</span><span class="nd">AnonymousClass</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">][</span> <span class="p">@</span><span class="nd">Image</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">Object</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">Arguments</span>
<span class="err">└─</span> <span class="nx">ClassOrInterfaceBody</span></code></pre></figure>
</td>
<td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">LocalVariableDeclaration</span>
<span class="err">├─</span> <span class="nx">ModifierList</span>
<span class="err">├─</span> <span class="nx">ClassType</span><span class="p">[</span> <span class="p">@</span><span class="nd">SimpleName</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">Object</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">VariableDeclarator</span>
<span class="err">├─</span> <span class="nx">VariableId</span><span class="p">[</span> <span class="p">@</span><span class="nd">Name</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">anonymous</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">ConstructorCall</span>
<span class="err">├─</span> <span class="nx">ClassType</span><span class="p">[</span> <span class="p">@</span><span class="nd">SimpleName</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">Object</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">ArgumentList</span>
<span class="err">└─</span> <span class="nx">AnonymousClassDeclaration</span>
<span class="err">├─</span> <span class="nx">ModifierList</span>
<span class="err">└─</span> <span class="nx">ClassBody</span></code></pre></figure>
</td></tr>
</table>
</details>
<h4 id="method-and-constructor-declarations">Method and Constructor declarations</h4>
<h5 id="method-grammar-simplification">Method grammar simplification</h5>
<ul>
<li>What: Simplify and align the grammar used for method and constructor declarations. The methods in an annotation
type are now also method declarations.</li>
<li>Why: The method declaration had a nested node “MethodDeclarator”, which was not available for constructor
declarations. This made it difficult to write rules, that concern both methods and constructors without
explicitly differentiate between these two.</li>
<li>Related issue: <a href="https://github.com/pmd/pmd/pull/2034">[java] Align method and constructor declaration grammar (#2034)</a></li>
</ul>
<details>
<summary>Method grammar Examples</summary>
<table>
<tr><th>Code</th><th>Old AST (PMD 6)</th><th>New AST (PMD 7)</th></tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kd">public</span> <span class="kd">class</span> <span class="nc">Sample</span> <span class="o">{</span>
<span class="kd">public</span> <span class="nf">Sample</span><span class="o">(</span><span class="kt">int</span> <span class="n">arg</span><span class="o">)</span> <span class="kd">throws</span> <span class="nc">Exception</span> <span class="o">{</span>
<span class="kd">super</span><span class="o">();</span>
<span class="n">greet</span><span class="o">(</span><span class="n">arg</span><span class="o">);</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">greet</span><span class="o">(</span><span class="kt">int</span> <span class="n">arg</span><span class="o">)</span> <span class="kd">throws</span> <span class="nc">Exception</span> <span class="o">{</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Hello"</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">ClassOrInterfaceBody</span>
<span class="err">├─</span> <span class="nx">ClassOrInterfaceBodyDeclaration</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ConstructorDeclaration</span><span class="p">[</span> <span class="p">@</span><span class="nd">Image</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">Sample</span><span class="dl">'</span> <span class="p">]</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">FormalParameters</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">FormalParameter</span>
<span class="err"></span> <span class="err"></span> <span class="err">├─</span> <span class="p">...</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">NameList</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">Name</span><span class="p">[</span> <span class="p">@</span><span class="nd">Image</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">Exception</span><span class="dl">'</span> <span class="p">]</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">ExplicitConstructorInvocation</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">Arguments</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">BlockStatement</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Statement</span>
<span class="err"></span> <span class="err">└─</span> <span class="p">...</span>
<span class="err">└─</span> <span class="nx">ClassOrInterfaceBodyDeclaration</span>
<span class="err">└─</span> <span class="nx">MethodDeclaration</span><span class="p">[</span> <span class="p">@</span><span class="nd">Name</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">greet</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">ResultType</span>
<span class="err">├─</span> <span class="nx">MethodDeclarator</span><span class="p">[</span> <span class="p">@</span><span class="nd">Image</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">greet</span><span class="dl">'</span> <span class="p">]</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">FormalParameters</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">FormalParameter</span>
<span class="err"></span> <span class="err">├─</span> <span class="p">...</span>
<span class="err">├─</span> <span class="nx">NameList</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Name</span><span class="p">[</span> <span class="p">@</span><span class="nd">Image</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">Exception</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">Block</span>
<span class="err">└─</span> <span class="nx">BlockStatement</span>
<span class="err">└─</span> <span class="nx">Statement</span>
<span class="err">└─</span> <span class="p">...</span></code></pre></figure>
</td>
<td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">ClassBody</span>
<span class="err">├─</span> <span class="nx">ConstructorDeclaration</span><span class="p">[</span> <span class="p">@</span><span class="nd">Name</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">Sample</span><span class="dl">'</span> <span class="p">]</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">ModifierList</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">FormalParameters</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">FormalParameter</span>
<span class="err"></span> <span class="err"></span> <span class="err">├─</span> <span class="p">...</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">ThrowsList</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">ClassType</span><span class="p">[</span> <span class="p">@</span><span class="nd">SimpleName</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">Exception</span><span class="dl">'</span> <span class="p">]</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Block</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">ExplicitConstructorInvocation</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">ArgumentList</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ExpressionStatement</span>
<span class="err"></span> <span class="err">└─</span> <span class="p">...</span>
<span class="err">└─</span> <span class="nx">MethodDeclaration</span><span class="p">[</span> <span class="p">@</span><span class="nd">Name</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">greet</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">ModifierList</span>
<span class="err">├─</span> <span class="nx">VoidType</span>
<span class="err">├─</span> <span class="nx">FormalParameters</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">FormalParameter</span>
<span class="err"></span> <span class="err">├─</span> <span class="p">...</span>
<span class="err">├─</span> <span class="nx">ThrowsList</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ClassType</span><span class="p">[</span> <span class="p">@</span><span class="nd">SimpleName</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">Exception</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">Block</span>
<span class="err">└─</span> <span class="nx">ExpressionStatement</span>
<span class="err">└─</span> <span class="p">...</span></code></pre></figure>
</td></tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kd">public</span> <span class="nd">@interface</span> <span class="nc">MyAnnotation</span> <span class="o">{</span>
<span class="kt">int</span> <span class="nf">value</span><span class="o">()</span> <span class="k">default</span> <span class="mi">1</span><span class="o">;</span>
<span class="o">}</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">AnnotationTypeDeclaration</span><span class="p">[</span> <span class="p">@</span><span class="nd">SimpleName</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">MyAnnotation</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">AnnotationTypeBody</span>
<span class="err">└─</span> <span class="nx">AnnotationTypeMemberDeclaration</span>
<span class="err">└─</span> <span class="nx">AnnotationMethodDeclaration</span><span class="p">[</span> <span class="p">@</span><span class="nd">Image</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">value</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">Type</span> <span class="p">...</span>
<span class="err">└─</span> <span class="nx">DefaultValue</span> <span class="p">...</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">AnnotationTypeDeclaration</span><span class="p">[</span> <span class="p">@</span><span class="nd">SimpleName</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">MyAnnotation</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">ModifierList</span>
<span class="err">└─</span> <span class="nx">AnnotationTypeBody</span>
<span class="err">└─</span> <span class="nx">MethodDeclaration</span><span class="p">[</span> <span class="p">@</span><span class="nd">Name</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">value</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">ModifierList</span>
<span class="err">├─</span> <span class="nx">PrimitiveType</span>
<span class="err">├─</span> <span class="nx">FormalParameters</span>
<span class="err">└─</span> <span class="nx">DefaultValue</span> <span class="p">...</span></code></pre></figure>
</td></tr>
</table>
</details>
<h5 id="formal-parameters">Formal parameters</h5>
<ul>
<li>What: Use <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTFormalParameter.html#"><code>ASTFormalParameter</code></a> only for method and constructor declaration. Lambdas use
<a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTLambdaParameter.html#"><code>ASTLambdaParameter</code></a>, catch clauses use <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTCatchParameter.html#"><code>ASTCatchParameter</code></a>.</li>
<li>Why: FormalParameters API is different from the other ones.
<ul>
<li>FormalParameter must mention a type node.</li>
<li>LambdaParameter can be inferred</li>
<li>CatchParameter cannot be varargs</li>
<li>CatchParameter can have multiple exception types (a <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTUnionType.html#"><code>ASTUnionType</code></a> now)</li>
</ul>
</li>
</ul>
<details>
<summary>Formal parameters Examples</summary>
<table>
<tr><th>Code</th><th>Old AST (PMD 6)</th><th>New AST (PMD 7)</th></tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="k">try</span> <span class="o">{</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nd">@A</span> <span class="nc">IOException</span> <span class="o">|</span> <span class="nc">IllegalArgumentException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="o">}</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">TryStatement</span>
<span class="err">├─</span> <span class="nx">Block</span>
<span class="err">└─</span> <span class="nx">CatchStatement</span>
<span class="err">├─</span> <span class="nx">FormalParameter</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">Annotation</span><span class="p">[</span> <span class="p">@</span><span class="nd">AnnotationName</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">A</span><span class="dl">'</span> <span class="p">]</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">MarkerAnnotation</span><span class="p">[</span> <span class="p">@</span><span class="nd">AnnotationName</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">A</span><span class="dl">'</span> <span class="p">]</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">Name</span><span class="p">[</span> <span class="p">@</span><span class="nd">Image</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">A</span><span class="dl">'</span> <span class="p">]</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">Type</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">ReferenceType</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">ClassOrInterfaceType</span><span class="p">[</span> <span class="p">@</span><span class="nd">Image</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">IOException</span><span class="dl">'</span> <span class="p">]</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">Type</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">ReferenceType</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">ClassOrInterfaceType</span><span class="p">[</span> <span class="p">@</span><span class="nd">Image</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">IllegalArgumentException</span><span class="dl">'</span> <span class="p">]</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">VariableDeclaratorId</span><span class="p">[</span> <span class="p">@</span><span class="nd">Name</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">e</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">Block</span></code></pre></figure>
</td>
<td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">TryStatement</span>
<span class="err">├─</span> <span class="nx">Block</span>
<span class="err">└─</span> <span class="nx">CatchClause</span>
<span class="err">├─</span> <span class="nx">CatchParameter</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">ModifierList</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">Annotation</span><span class="p">[</span> <span class="p">@</span><span class="nd">SimpleName</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">A</span><span class="dl">'</span> <span class="p">]</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">ClassType</span><span class="p">[</span> <span class="p">@</span><span class="nd">SimpleName</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">A</span><span class="dl">'</span> <span class="p">]</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">UnionType</span>
<span class="err"></span> <span class="err"></span> <span class="err">├─</span> <span class="nx">ClassType</span><span class="p">[</span> <span class="p">@</span><span class="nd">SimpleName</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">IOException</span><span class="dl">'</span> <span class="p">]</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">ClassType</span><span class="p">[</span> <span class="p">@</span><span class="nd">SimpleName</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">IllegalArgumentException</span><span class="dl">'</span> <span class="p">]</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">VariableId</span><span class="p">[</span> <span class="p">@</span><span class="nd">Name</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">e</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">Block</span></code></pre></figure>
</td></tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="o">(</span><span class="n">a</span><span class="o">,</span> <span class="n">b</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="o">{};</span>
<span class="n">c</span> <span class="o">-&gt;</span> <span class="o">{};</span>
<span class="o">(</span><span class="nd">@A</span> <span class="kt">var</span> <span class="n">d</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="o">{};</span>
<span class="o">(</span><span class="nd">@A</span> <span class="kt">int</span> <span class="n">e</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="o">{};</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">StatementExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err">└─</span> <span class="nx">LambdaExpression</span>
<span class="err">├─</span> <span class="nx">VariableDeclaratorId</span><span class="p">[</span> <span class="p">@</span><span class="nd">Name</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">a</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">VariableDeclaratorId</span><span class="p">[</span> <span class="p">@</span><span class="nd">Name</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">b</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">Block</span>
<span class="err">└─</span> <span class="nx">StatementExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err">└─</span> <span class="nx">LambdaExpression</span>
<span class="err">├─</span> <span class="nx">VariableDeclaratorId</span><span class="p">[</span> <span class="p">@</span><span class="nd">Name</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">c</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">Block</span>
<span class="err">└─</span> <span class="nx">StatementExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err">└─</span> <span class="nx">LambdaExpression</span>
<span class="err">├─</span> <span class="nx">FormalParameters</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">FormalParameter</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">Annotation</span><span class="p">[</span> <span class="p">@</span><span class="nd">AnnotationName</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">A</span><span class="dl">'</span> <span class="p">]</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">MarkerAnnotation</span><span class="p">[</span> <span class="p">@</span><span class="nd">AnnotationName</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">A</span><span class="dl">'</span> <span class="p">]</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">Name</span><span class="p">[</span> <span class="p">@</span><span class="nd">Image</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">A</span><span class="dl">'</span> <span class="p">]</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">VariableDeclaratorId</span><span class="p">[</span> <span class="p">@</span><span class="nd">Name</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">d</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">Block</span>
<span class="err">└─</span> <span class="nx">StatementExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err">└─</span> <span class="nx">LambdaExpression</span>
<span class="err">├─</span> <span class="nx">FormalParameters</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">FormalParameter</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">Annotation</span><span class="p">[</span> <span class="p">@</span><span class="nd">AnnotationName</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">A</span><span class="dl">'</span> <span class="p">]</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">MarkerAnnotation</span><span class="p">[</span> <span class="p">@</span><span class="nd">AnnotationName</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">A</span><span class="dl">'</span> <span class="p">]</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">Name</span><span class="p">[</span> <span class="p">@</span><span class="nd">Image</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">A</span><span class="dl">'</span> <span class="p">]</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">Type</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">PrimitiveType</span><span class="p">[</span> <span class="p">@</span><span class="nd">Image</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">int</span><span class="dl">'</span> <span class="p">]</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">VariableDeclaratorId</span><span class="p">[</span> <span class="p">@</span><span class="nd">Name</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">e</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">Block</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">ExpressionStatement</span>
<span class="err">└─</span> <span class="nx">LambdaExpression</span>
<span class="err">├─</span> <span class="nx">LambdaParameterList</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">LambdaParameter</span>
<span class="err"></span> <span class="err"></span> <span class="err">├─</span> <span class="nx">ModifierList</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">VariableId</span><span class="p">[</span> <span class="p">@</span><span class="nd">Name</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">a</span><span class="dl">'</span> <span class="p">]</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">LambdaParameter</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">ModifierList</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">VariableId</span><span class="p">[</span> <span class="p">@</span><span class="nd">Name</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">b</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">Block</span>
<span class="err">└─</span> <span class="nx">ExpressionStatement</span>
<span class="err">└─</span> <span class="nx">LambdaExpression</span>
<span class="err">├─</span> <span class="nx">LambdaParameterList</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">LambdaParameter</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">ModifierList</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">VariableId</span><span class="p">[</span> <span class="p">@</span><span class="nd">Name</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">c</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">Block</span>
<span class="err">└─</span> <span class="nx">ExpressionStatement</span>
<span class="err">└─</span> <span class="nx">LambdaExpression</span>
<span class="err">├─</span> <span class="nx">LambdaParameterList</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">LambdaParameter</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">ModifierList</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">Annotation</span><span class="p">[</span> <span class="p">@</span><span class="nd">SimpleName</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">A</span><span class="dl">'</span> <span class="p">]</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">ClassType</span><span class="p">[</span> <span class="p">@</span><span class="nd">SimpleName</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">A</span><span class="dl">'</span> <span class="p">]</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">VariableId</span><span class="p">[</span> <span class="p">@</span><span class="nd">Name</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">d</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">Block</span>
<span class="err">└─</span> <span class="nx">ExpressionStatement</span>
<span class="err">└─</span> <span class="nx">LambdaExpression</span>
<span class="err">├─</span> <span class="nx">LambdaParameterList</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">LambdaParameter</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">ModifierList</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">Annotation</span><span class="p">[</span> <span class="p">@</span><span class="nd">SimpleName</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">A</span><span class="dl">'</span> <span class="p">]</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">ClassType</span><span class="p">[</span> <span class="p">@</span><span class="nd">SimpleName</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">A</span><span class="dl">'</span> <span class="p">]</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">PrimitiveType</span><span class="p">[</span> <span class="p">@</span><span class="nd">Kind</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">int</span><span class="dl">'</span> <span class="p">]</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">VariableId</span><span class="p">[</span> <span class="p">@</span><span class="nd">Name</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">e</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">Block</span></code></pre></figure>
</td></tr>
</table>
</details>
<h5 id="new-node-for-explicit-receiver-parameter">New node for explicit receiver parameter</h5>
<ul>
<li>What: A separate node type <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTReceiverParameter.html#"><code>ASTReceiverParameter</code></a> is introduced to differentiate it from formal parameters.</li>
<li>Why: A receiver parameter is not a formal parameter, even though it looks like one: it doesnt declare a variable,
and doesnt affect the arity of the method or constructor. Its so rarely used that giving it its own node avoids
matching it by mistake and simplifies the API and grammar of the ubiquitous <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTFormalParameter.html#"><code>ASTFormalParameter</code></a>
and <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTVariableId.html#"><code>ASTVariableId</code></a>.</li>
<li>Related issue: <a href="https://github.com/pmd/pmd/pull/1980">[java] Separate receiver parameter from formal parameter (#1980)</a></li>
</ul>
<details>
<summary>explicit receiver parameter Examples</summary>
<table>
<tr><th>Code</th><th>Old AST (PMD 6)</th><th>New AST (PMD 7)</th></tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kt">void</span> <span class="nf">myMethod</span><span class="o">(</span><span class="nd">@A</span> <span class="nc">Foo</span> <span class="k">this</span><span class="o">,</span> <span class="nc">Foo</span> <span class="n">other</span><span class="o">)</span> <span class="o">{}</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">FormalParameters</span> <span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="err">├─</span> <span class="nx">FormalParameter</span><span class="p">[</span> <span class="p">@</span><span class="nd">ExplicitReceiverParameter</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">MarkerAnnotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">Type</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">ReferenceType</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">ClassOrInterfaceType</span> <span class="dl">"</span><span class="s2">Foo</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">VariableDeclaratorId</span><span class="p">[</span> <span class="p">@</span><span class="nd">ExplicitReceiverParameter</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span> <span class="dl">"</span><span class="s2">this</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">FormalParameter</span>
<span class="err">├─</span> <span class="nx">Type</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ReferenceType</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ClassOrInterfaceType</span> <span class="dl">"</span><span class="s2">Foo</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">VariableDeclaratorId</span> <span class="dl">"</span><span class="s2">other</span><span class="dl">"</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">FormalParameters</span> <span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="err">├─</span> <span class="nx">ReceiverParameter</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">Foo</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">FormalParameter</span>
<span class="err">├─</span> <span class="nx">ModifierList</span>
<span class="err">├─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">Foo</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">VariableId</span> <span class="dl">"</span><span class="s2">other</span><span class="dl">"</span></code></pre></figure>
</td></tr>
</table>
</details>
<h5 id="varargs">Varargs</h5>
<ul>
<li>What: parse the varargs ellipsis as an <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTArrayType.html#"><code>ASTArrayType</code></a>.</li>
<li>Why: this improves regularity of the grammar, and allows type annotations to be added to the ellipsis</li>
</ul>
<details>
<summary>Varargs Examples</summary>
<table>
<tr><th>Code</th><th>Old AST (PMD 6)</th><th>New AST (PMD 7)</th></tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kt">void</span> <span class="nf">myMethod</span><span class="o">(</span><span class="kt">int</span><span class="o">...</span> <span class="n">is</span><span class="o">)</span> <span class="o">{}</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">FormalParameter</span><span class="p">[</span> <span class="p">@</span><span class="nd">Varargs</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">Type</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">PrimitiveType</span> <span class="dl">"</span><span class="s2">int</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">VariableDeclaratorId</span> <span class="dl">"</span><span class="s2">is</span><span class="dl">"</span></code></pre></figure>
</td>
<td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">FormalParameter</span><span class="p">[</span> <span class="p">@</span><span class="nd">Varargs</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">ModifierList</span>
<span class="err">├─</span> <span class="nx">ArrayType</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">PrimitiveType</span> <span class="dl">"</span><span class="s2">int</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ArrayDimensions</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ArrayTypeDim</span><span class="p">[</span> <span class="p">@</span><span class="nd">Varargs</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">VariableId</span> <span class="dl">"</span><span class="s2">is</span><span class="dl">"</span></code></pre></figure>
</td></tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kt">void</span> <span class="nf">myMethod</span><span class="o">(</span><span class="kt">int</span> <span class="nd">@A</span> <span class="o">...</span> <span class="n">is</span><span class="o">)</span> <span class="o">{}</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">FormalParameter</span><span class="p">[</span> <span class="p">@</span><span class="nd">Varargs</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">Type</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">PrimitiveType</span> <span class="dl">"</span><span class="s2">int</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">MarkerAnnotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">VariableDeclaratorId</span> <span class="dl">"</span><span class="s2">is</span><span class="dl">"</span></code></pre></figure>
</td>
<td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">FormalParameter</span><span class="p">[</span> <span class="p">@</span><span class="nd">Varargs</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">ModifierList</span>
<span class="err">├─</span> <span class="nx">ArrayType</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">PrimitiveType</span> <span class="dl">"</span><span class="s2">int</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ArrayDimensions</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ArrayTypeDim</span><span class="p">[</span> <span class="p">@</span><span class="nd">Varargs</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Annotation</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">VariableId</span> <span class="dl">"</span><span class="s2">is</span><span class="dl">"</span></code></pre></figure>
</td></tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kt">void</span> <span class="nf">myMethod</span><span class="o">(</span><span class="kt">int</span><span class="o">[]...</span> <span class="n">is</span><span class="o">)</span> <span class="o">{}</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">FormalParameter</span><span class="p">[</span> <span class="p">@</span><span class="nd">Varargs</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">Type</span><span class="p">[</span> <span class="p">@</span><span class="nd">ArrayType</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ReferenceType</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">PrimitiveType</span> <span class="dl">"</span><span class="s2">int</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">VariableDeclaratorId</span> <span class="dl">"</span><span class="s2">is</span><span class="dl">"</span></code></pre></figure>
</td>
<td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">FormalParameter</span><span class="p">[</span> <span class="p">@</span><span class="nd">Varargs</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">ModifierList</span>
<span class="err">├─</span> <span class="nx">ArrayType</span> <span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">PrimitiveType</span> <span class="dl">"</span><span class="s2">int</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ArrayDimensions</span> <span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">ArrayTypeDim</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ArrayTypeDim</span><span class="p">[</span> <span class="p">@</span><span class="nd">Varargs</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">VariableId</span> <span class="dl">"</span><span class="s2">is</span><span class="dl">"</span></code></pre></figure>
</td></tr>
</table>
</details>
<h5 id="add-void-type-node-to-replace-resulttype">Add void type node to replace ResultType</h5>
<ul>
<li>What: Add a <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTVoidType.html#"><code>ASTVoidType</code></a> node to replace <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.2.0/net/sourceforge/pmd/lang/java/ast/ASTResultType.html#"><code>ASTResultType</code></a>.</li>
<li>Why: This means we dont need the ResultType wrapper when the method is not void, and the result type node is never null.</li>
<li>Related issue: <a href="https://github.com/pmd/pmd/pull/2715">[java] Add void type node to replace ResultType (#2715)</a></li>
</ul>
<details>
<summary>Void Type Examples</summary>
<table>
<tr><th>Code</th><th>Old AST (PMD 6)</th><th>New AST (PMD 7)</th></tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kt">void</span> <span class="nf">foo</span><span class="o">();</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">MethodDeclaration</span> <span class="dl">"</span><span class="s2">foo</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">ResultType</span><span class="p">[</span> <span class="p">@</span><span class="nd">Void</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">MethodDeclarator</span>
<span class="err">└─</span> <span class="nx">FormalParameters</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">MethodDeclaration</span> <span class="dl">"</span><span class="s2">foo</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">ModifierList</span>
<span class="err">├─</span> <span class="nx">VoidType</span>
<span class="err">└─</span> <span class="nx">FormalParameters</span></code></pre></figure>
</td></tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kt">int</span> <span class="nf">foo</span><span class="o">();</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">MethodDeclaration</span> <span class="dl">"</span><span class="s2">foo</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">ResultType</span><span class="p">[</span> <span class="p">@</span><span class="nd">Void</span> <span class="o">=</span> <span class="kc">false</span><span class="p">()</span> <span class="p">]</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Type</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">PrimitiveType</span> <span class="dl">"</span><span class="s2">int</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">MethodDeclarator</span>
<span class="err">└─</span> <span class="nx">FormalParameters</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">MethodDeclaration</span> <span class="dl">"</span><span class="s2">foo</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">ModifierList</span>
<span class="err">├─</span> <span class="nx">PrimitiveType</span> <span class="dl">"</span><span class="s2">int</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">FormalParameters</span></code></pre></figure>
</td></tr>
</table>
</details>
<h4 id="statements">Statements</h4>
<h5 id="statements-are-flattened">Statements are flattened</h5>
<ul>
<li>What: Statements are flattened. There are no superfluous BlockStatement and Statement nodes anymore.
All children of a <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTBlock.html#"><code>ASTBlock</code></a> are by definition
<a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTStatement.html#"><code>ASTStatement</code></a>s, which is now an interface implemented by all statements.</li>
<li>Why: This simplifies the tree traversal. The removed nodes BlockStatement and Statement didnt add any
additional information. We only need a Statement abstraction. BlockStatement was used to enforce, that no
variable or local class declaration is found alone as the child of e.g. an unbraced if, else, for, etc.
This is a parser-only distinction thats not that useful for analysis later on.</li>
<li>Related issue: <a href="https://github.com/pmd/pmd/pull/2164">[java] Improve statement grammar (#2164)</a></li>
</ul>
<details>
<summary>Statements Examples</summary>
<table>
<tr><th>Code</th><th>Old AST (PMD 6)</th><th>New AST (PMD 7)</th></tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kt">int</span> <span class="n">i</span><span class="o">;</span>
<span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="o">;</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">Block</span>
<span class="err">├─</span> <span class="nx">BlockStatement</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">LocalVariableDeclaration</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">Type</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">PrimitiveType</span> <span class="dl">"</span><span class="s2">int</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">VariableDeclarator</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">VariableDeclaratorId</span> <span class="dl">"</span><span class="s2">i</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">BlockStatement</span>
<span class="err">└─</span> <span class="nx">Statement</span>
<span class="err">└─</span> <span class="nx">StatementExpression</span>
<span class="err">├─</span> <span class="nx">PrimaryExpression</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">i</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">AssignmentOperator</span> <span class="dl">"</span><span class="s2">=</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">Expression</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err">└─</span> <span class="nx">Literal</span> <span class="dl">"</span><span class="s2">1</span><span class="dl">"</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">Block</span>
<span class="err">├─</span> <span class="nx">LocalVariableDeclaration</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">ModifierList</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">PrimitiveType</span> <span class="dl">"</span><span class="s2">int</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">VariableDeclarator</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">VariableId</span> <span class="dl">"</span><span class="s2">i</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ExpressionStatement</span>
<span class="err">└─</span> <span class="nx">AssignmentExpression</span> <span class="dl">"</span><span class="s2">=</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">VariableAccess</span> <span class="dl">"</span><span class="s2">i</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">NumericLiteral</span> <span class="dl">"</span><span class="s2">1</span><span class="dl">"</span></code></pre></figure>
</td></tr>
</table>
</details>
<h5 id="new-node-for-for-each-statements">New node for For-each statements</h5>
<ul>
<li>What: New node for For-each statements: <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTForeachStatement.html#"><code>ASTForeachStatement</code></a> instead of ForStatement.</li>
<li>Why: This makes it a lot easier to distinguish in the AST between For-loops and For-Each-loops. E.g. some
rules only apply to one or the other, and it was complicated to write a rule that works with both different
subtrees (for loops have additional children ForInit and ForUpdate)</li>
<li>Related issue: <a href="https://github.com/pmd/pmd/pull/2164">[java] Improve statement grammar (#2164)</a></li>
</ul>
<details>
<summary>For-each statement Examples</summary>
<table>
<tr><th>Code</th><th>Old AST (PMD 6)</th><th>New AST (PMD 7)</th></tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="k">for</span> <span class="o">(</span><span class="nc">String</span> <span class="n">s</span> <span class="o">:</span> <span class="nc">List</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="s">"a"</span><span class="o">,</span> <span class="s">"b"</span><span class="o">))</span> <span class="o">{</span> <span class="o">}</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">BlockStatement</span>
<span class="err">└─</span> <span class="nx">Statement</span>
<span class="err">└─</span> <span class="nx">ForStatement</span><span class="p">[</span> <span class="p">@</span><span class="nd">Foreach</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">LocalVariableDeclaration</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">Type</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">ReferenceType</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">ClassOrInterfaceType</span> <span class="dl">"</span><span class="s2">String</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">VariableDeclarator</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">VariableDeclaratorId</span> <span class="dl">"</span><span class="s2">s</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">Expression</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">PrimaryPrefix</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">List.of</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">PrimarySuffix</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Arguments</span> <span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ArgumentList</span> <span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">Expression</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">Literal</span><span class="p">[</span> <span class="p">@</span><span class="nd">StringLiteral</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">][</span> <span class="p">@</span><span class="nd">Image</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">"a"</span><span class="dl">'</span> <span class="p">]</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Expression</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Literal</span><span class="p">[</span> <span class="p">@</span><span class="nd">StringLiteral</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">][</span> <span class="p">@</span><span class="nd">Image</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">"b"</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">Statement</span>
<span class="err">└─</span> <span class="nx">Block</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">Block</span>
<span class="err">└─</span> <span class="nx">ForeachStatement</span>
<span class="err">├─</span> <span class="nx">LocalVariableDeclaration</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">ModifierList</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">String</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">VariableDeclarator</span> <span class="dl">"</span><span class="s2">s</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">VariableId</span> <span class="dl">"</span><span class="s2">s</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">MethodCall</span> <span class="dl">"</span><span class="s2">of</span><span class="dl">"</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">TypeExpression</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">List</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ArgumentList</span> <span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">StringLiteral</span><span class="p">[</span> <span class="p">@</span><span class="nd">Image</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">"a"</span><span class="dl">'</span> <span class="p">]</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">StringLiteral</span><span class="p">[</span> <span class="p">@</span><span class="nd">Image</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">"b"</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">Block</span></code></pre></figure>
</td></tr>
</table>
</details>
<h5 id="new-nodes-for-expressionstatement-localclassstatement">New nodes for ExpressionStatement, LocalClassStatement</h5>
<ul>
<li>What: Renamed StatementExpression to <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTExpressionStatement.html#"><code>ASTExpressionStatement</code></a>.
Added new node <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTLocalClassStatement.html#"><code>ASTLocalClassStatement</code></a>.</li>
<li>Why: ExpressionStatement is now a <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTStatement.html#"><code>ASTStatement</code></a>, that can be used as a child in a
block. It itself has only one child, which is some kind of <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTExpression.html#"><code>ASTExpression</code></a>,
which can be really any kind of expression (like assignment).
In order to allow local class declarations as part of a block, we introduced <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTLocalClassStatement.html#"><code>ASTLocalClassStatement</code></a>
which is a statement that carries a type declaration. Now blocks are just a list of statements.
This allows us to have two distinct hierarchies for expressions and statements.</li>
<li>Related issue: <a href="https://github.com/pmd/pmd/pull/2164">[java] Improve statement grammar (#2164)</a></li>
</ul>
<details>
<summary>ExpressionStatement, LocalClassStatement Examples</summary>
<table>
<tr><th>Code</th><th>Old AST (PMD 6)</th><th>New AST (PMD 7)</th></tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="n">i</span><span class="o">++;</span>
<span class="kd">class</span> <span class="nc">LocalClass</span> <span class="o">{}</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">Block</span>
<span class="err">├─</span> <span class="nx">BlockStatement</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Statement</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">StatementExpression</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">PostfixExpression</span> <span class="dl">"</span><span class="s2">++</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">i</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">BlockStatement</span>
<span class="err">└─</span> <span class="nx">ClassOrInterfaceDeclaration</span><span class="p">[</span> <span class="p">@</span><span class="nd">Local</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span> <span class="dl">"</span><span class="s2">LocalClass</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ClassOrInterfaceBody</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">Block</span>
<span class="err">├─</span> <span class="nx">ExpressionStatement</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">UnaryExpression</span> <span class="dl">"</span><span class="s2">++</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">VariableAccess</span> <span class="dl">"</span><span class="s2">i</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">LocalClassStatement</span>
<span class="err">└─</span> <span class="nx">ClassDeclaration</span> <span class="dl">"</span><span class="s2">LocalClass</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">ModifierList</span>
<span class="err">└─</span> <span class="nx">ClassBody</span></code></pre></figure>
</td></tr>
</table>
</details>
<h5 id="improve-try-with-resources-grammar">Improve try-with-resources grammar</h5>
<ul>
<li>What: The AST representation of a try-with-resources statement has been simplified.
It uses now <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTLocalVariableDeclaration.html#"><code>ASTLocalVariableDeclaration</code></a> unless it is a concise try-with-resources.</li>
<li>Why: Simpler integration try-with-resources into symboltable and type resolution.</li>
<li>Related issue: <a href="https://github.com/pmd/pmd/pull/1897">[java] Improve try-with-resources grammar (#1897)</a></li>
</ul>
<details>
<summary>Try-With-Resources Examples</summary>
<table>
<tr><th>Code</th><th>Old AST (PMD 6)</th><th>New AST (PMD 7)</th></tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="k">try</span> <span class="o">(</span><span class="nc">InputStream</span> <span class="n">in</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">FileInputStream</span><span class="o">();</span> <span class="nc">OutputStream</span> <span class="n">out</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">FileOutputStream</span><span class="o">();)</span> <span class="o">{</span> <span class="o">}</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">TryStatement</span>
<span class="err">└─</span> <span class="nx">ResourceSpecification</span>
<span class="err">└─</span> <span class="nx">Resources</span>
<span class="err">├─</span> <span class="nx">Resource</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">Type</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">ReferenceType</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">ClassOrInterfaceType</span> <span class="dl">"</span><span class="s2">InputStream</span><span class="dl">"</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">VariableDeclaratorId</span> <span class="dl">"</span><span class="s2">in</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Expression</span>
<span class="err"></span> <span class="err">└─</span> <span class="p">...</span>
<span class="err">└─</span> <span class="nx">Resource</span>
<span class="err">├─</span> <span class="nx">Type</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ReferenceType</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ClassOrInterfaceType</span> <span class="dl">"</span><span class="s2">OutputStream</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">VariableDeclaratorId</span> <span class="dl">"</span><span class="s2">out</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">Expression</span>
<span class="err">└─</span> <span class="p">...</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">TryStatement</span>
<span class="err">└─</span> <span class="nx">ResourceList</span><span class="p">[</span> <span class="p">@</span><span class="nd">TrailingSemiColon</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span> <span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="err">├─</span> <span class="nx">Resource</span><span class="p">[</span> <span class="p">@</span><span class="nd">ConciseResource</span> <span class="o">=</span> <span class="kc">false</span><span class="p">()</span> <span class="p">]</span> <span class="dl">"</span><span class="s2">in</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">LocalVariableDeclaration</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">ModifierList</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">InputStream</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">VariableDeclarator</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">VariableId</span> <span class="dl">"</span><span class="s2">in</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ConstructorCall</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">FileInputStream</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ArgumentList</span> <span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="err">└─</span> <span class="nx">Resource</span><span class="p">[</span> <span class="p">@</span><span class="nd">ConciseResource</span> <span class="o">=</span> <span class="kc">false</span><span class="p">()</span> <span class="p">]</span> <span class="dl">"</span><span class="s2">out</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">LocalVariableDeclaration</span>
<span class="err">├─</span> <span class="nx">ModifierList</span>
<span class="err">├─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">OutputStream</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">VariableDeclarator</span>
<span class="err">├─</span> <span class="nx">VariableId</span> <span class="dl">"</span><span class="s2">out</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ConstructorCall</span>
<span class="err">├─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">FileOutputStream</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ArgumentList</span> <span class="p">(</span><span class="mi">0</span><span class="p">)</span></code></pre></figure>
</td></tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nc">InputStream</span> <span class="n">in</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">FileInputStream</span><span class="o">();</span>
<span class="k">try</span> <span class="o">(</span><span class="n">in</span><span class="o">)</span> <span class="o">{}</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">TryStatement</span>
<span class="err">└─</span> <span class="nx">ResourceSpecification</span>
<span class="err">└─</span> <span class="nx">Resources</span>
<span class="err">└─</span> <span class="nx">Resource</span> <span class="dl">"</span><span class="s2">in</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">in</span><span class="dl">"</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">TryStatement</span>
<span class="err">└─</span> <span class="nx">ResourceList</span><span class="p">[</span> <span class="p">@</span><span class="nd">TrailingSemiColon</span> <span class="o">=</span> <span class="kc">false</span><span class="p">()</span> <span class="p">]</span> <span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="err">└─</span> <span class="nx">Resource</span><span class="p">[</span> <span class="p">@</span><span class="nd">ConciseResource</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span> <span class="dl">"</span><span class="s2">in</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">VariableAccess</span> <span class="dl">"</span><span class="s2">in</span><span class="dl">"</span></code></pre></figure>
</td></tr>
</table>
</details>
<h4 id="expressions">Expressions</h4>
<ul>
<li>
<p><a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTExpression.html#"><code>ASTExpression</code></a> and <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTPrimaryExpression.html#"><code>ASTPrimaryExpression</code></a> have
been turned into interfaces. These added no information to the AST and increased
its depth unnecessarily. All expressions implement the first interface. Both of
those nodes can no more be found in ASTs.</p>
</li>
<li>
<p><strong>Migrating</strong>:</p>
<ul>
<li>Basically, <code class="language-plaintext highlighter-rouge">Expression/X</code> or <code class="language-plaintext highlighter-rouge">Expression/PrimaryExpression/X</code>, just becomes <code class="language-plaintext highlighter-rouge">X</code></li>
<li>There is currently no way to match abstract or interface types with XPath, so <code class="language-plaintext highlighter-rouge">Expression</code> or <code class="language-plaintext highlighter-rouge">PrimaryExpression</code>
name tests wont match anything anymore. However, the axis step *[@Expression=true()] matches any expression.</li>
</ul>
</li>
</ul>
<h5 id="new-nodes-for-different-literals-types">New nodes for different literals types</h5>
<ul>
<li>What:
<ul>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTLiteral.html#"><code>ASTLiteral</code></a> has been turned into an interface.</li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTNumericLiteral.html#"><code>ASTNumericLiteral</code></a>, <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTCharLiteral.html#"><code>ASTCharLiteral</code></a>, <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTStringLiteral.html#"><code>ASTStringLiteral</code></a>,
and <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTClassLiteral.html#"><code>ASTClassLiteral</code></a> are new nodes that implement that interface.</li>
<li>ASTLiteral implements <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTPrimaryExpression.html#"><code>ASTPrimaryExpression</code></a></li>
</ul>
</li>
<li>Why: The fact that <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTNullLiteral.html#"><code>ASTNullLiteral</code></a>
and <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTBooleanLiteral.html#"><code>ASTBooleanLiteral</code></a> were nested within it but other literals types were all directly represented
by it was inconsistent, and ultimately that level of nesting was unnecessary.</li>
<li>Related issue: <a href="https://github.com/pmd/pmd/pull/1759">[java] New expression and type grammar (#1759)</a></li>
<li><strong>Migrating</strong>:
<ul>
<li>Remove all <code class="language-plaintext highlighter-rouge">/Literal/</code> segments from your XPath expressions</li>
<li>If you tested several types of literals, you can e.g. do it like <code class="language-plaintext highlighter-rouge">/*[self::StringLiteral or self::CharLiteral]/</code></li>
<li>As usual, use the designer to explore the new AST structure</li>
</ul>
</li>
</ul>
<details>
<summary>Literals Examples</summary>
<table>
<tr><th>Code</th><th>Old AST (PMD 6)</th><th>New AST (PMD 7)</th></tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kt">char</span> <span class="n">c</span> <span class="o">=</span> <span class="sc">'c'</span><span class="o">;</span>
<span class="kt">boolean</span> <span class="n">b</span> <span class="o">=</span> <span class="kc">true</span><span class="o">;</span>
<span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="o">;</span>
<span class="kt">double</span> <span class="n">d</span> <span class="o">=</span> <span class="mf">1.0</span><span class="o">;</span>
<span class="nc">String</span> <span class="n">s</span> <span class="o">=</span> <span class="s">"s"</span><span class="o">;</span>
<span class="nc">Object</span> <span class="n">n</span> <span class="o">=</span> <span class="kc">null</span><span class="o">;</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">Literal</span><span class="p">[</span> <span class="p">@</span><span class="nd">CharLiteral</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span> <span class="dl">"</span><span class="s2">'c'</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">Literal</span>
<span class="err">└─</span> <span class="nx">BooleanLiteral</span><span class="p">[</span> <span class="p">@</span><span class="nd">True</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">Literal</span><span class="p">[</span> <span class="p">@</span><span class="nd">IntLiteral</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span> <span class="dl">"</span><span class="s2">1</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">Literal</span><span class="p">[</span> <span class="p">@</span><span class="nd">DoubleLiteral</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span> <span class="dl">"</span><span class="s2">1.0</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">Literal</span><span class="p">[</span> <span class="p">@</span><span class="nd">StringLiteral</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span> <span class="dl">"</span><span class="se">\"</span><span class="s2">s</span><span class="se">\"</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">Literal</span>
<span class="err">└─</span> <span class="nx">NullLiteral</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">CharLiteral</span> <span class="dl">"</span><span class="s2">'c'</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">BooleanLiteral</span><span class="p">[</span> <span class="p">@</span><span class="nd">True</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">NumericLiteral</span><span class="p">[</span> <span class="p">@</span><span class="nd">IntLiteral</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span> <span class="dl">"</span><span class="s2">1</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">NumericLiteral</span><span class="p">[</span> <span class="p">@</span><span class="nd">DoubleLiteral</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span> <span class="dl">"</span><span class="s2">1.0</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">StringLiteral</span> <span class="dl">"</span><span class="se">\"</span><span class="s2">s</span><span class="se">\"</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">NullLiteral</span></code></pre></figure>
</td></tr></table>
</details>
<h5 id="method-calls-constructor-calls-array-allocations">Method calls, constructor calls, array allocations</h5>
<ul>
<li>What: Extra nodes dedicated for method and constructor calls and array allocations
<ul>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTConstructorCall.html#"><code>ASTConstructorCall</code></a></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTMethodCall.html#"><code>ASTMethodCall</code></a></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTArrayAllocation.html#"><code>ASTArrayAllocation</code></a></li>
</ul>
</li>
<li>Why: It was extremely difficult to identify method calls in PMD 6 - these consisted of multiple nodes with
primary prefix, suffix and expressions. This was too low level to be easy to be used.</li>
<li>Related issue: <a href="https://github.com/pmd/pmd/pull/1759">[java] New expression and type grammar (#1759)</a></li>
</ul>
<details>
<summary>Method calls, constructor calls, array allocations Examples</summary>
<table>
<tr><th>Code</th><th>Old AST (PMD 6)</th><th>New AST (PMD 7)</th></tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="n">o</span><span class="o">.</span><span class="na">myMethod</span><span class="o">(</span><span class="s">"a"</span><span class="o">);</span>
<span class="k">new</span> <span class="nf">Object</span><span class="o">(</span><span class="s">"b"</span><span class="o">);</span>
<span class="k">new</span> <span class="kt">int</span><span class="o">[</span><span class="mi">10</span><span class="o">];</span>
<span class="k">new</span> <span class="kt">int</span><span class="o">[]</span> <span class="o">{</span> <span class="mi">1</span><span class="o">,</span> <span class="mi">2</span><span class="o">,</span> <span class="mi">3</span> <span class="o">};</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">├─</span> <span class="nx">PrimaryPrefix</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">o.myMethod</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">PrimarySuffix</span>
<span class="err">└─</span> <span class="nx">Arguments</span>
<span class="err">└─</span> <span class="nx">ArgumentList</span> <span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="err">└─</span> <span class="nx">Expression</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err">└─</span> <span class="nx">Literal</span> <span class="dl">"</span><span class="se">\"</span><span class="s2">a</span><span class="se">\"</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err">└─</span> <span class="nx">AllocationExpression</span>
<span class="err">├─</span> <span class="nx">ClassOrInterfaceType</span> <span class="dl">"</span><span class="s2">Object</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">Arguments</span>
<span class="err">└─</span> <span class="nx">ArgumentList</span>
<span class="err">└─</span> <span class="nx">Expression</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err">└─</span> <span class="nx">Literal</span> <span class="dl">"</span><span class="se">\"</span><span class="s2">b</span><span class="se">\"</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err">└─</span> <span class="nx">AllocationExpression</span>
<span class="err">├─</span> <span class="nx">PrimitiveType</span> <span class="dl">"</span><span class="s2">int</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ArrayDimsAndInits</span>
<span class="err">└─</span> <span class="nx">Expression</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err">└─</span> <span class="nx">Literal</span> <span class="dl">"</span><span class="s2">10</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err">└─</span> <span class="nx">AllocationExpression</span>
<span class="err">├─</span> <span class="nx">PrimitiveType</span> <span class="dl">"</span><span class="s2">int</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ArrayDimsAndInits</span>
<span class="err">└─</span> <span class="nx">ArrayInitializer</span>
<span class="err">├─</span> <span class="nx">VariableInitializer</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Expression</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Literal</span> <span class="dl">"</span><span class="s2">1</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">VariableInitializer</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Expression</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Literal</span> <span class="dl">"</span><span class="s2">2</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">VariableInitializer</span>
<span class="err">└─</span> <span class="nx">Expression</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err">└─</span> <span class="nx">Literal</span> <span class="dl">"</span><span class="s2">3</span><span class="dl">"</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">MethodCall</span> <span class="dl">"</span><span class="s2">myMethod</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">VariableAccess</span> <span class="dl">"</span><span class="s2">o</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ArgumentList</span> <span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="err">└─</span> <span class="nx">StringLiteral</span> <span class="dl">"</span><span class="se">\"</span><span class="s2">a</span><span class="se">\"</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ConstructorCall</span>
<span class="err">├─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">Object</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ArgumentList</span> <span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="err">└─</span> <span class="nx">StringLiteral</span> <span class="dl">"</span><span class="se">\"</span><span class="s2">b</span><span class="se">\"</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ArrayAllocation</span><span class="p">[</span> <span class="p">@</span><span class="nd">ArrayDepth</span> <span class="o">=</span> <span class="mi">1</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">ArrayType</span>
<span class="err">├─</span> <span class="nx">PrimitiveType</span> <span class="dl">"</span><span class="s2">int</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ArrayDimensions</span> <span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="err">└─</span> <span class="nx">ArrayDimExpr</span>
<span class="err">└─</span> <span class="nx">NumericLiteral</span> <span class="dl">"</span><span class="s2">10</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ArrayAllocation</span><span class="p">[</span> <span class="p">@</span><span class="nd">ArrayDepth</span> <span class="o">=</span> <span class="mi">1</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">ArrayType</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">PrimitiveType</span> <span class="dl">"</span><span class="s2">int</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ArrayDimensions</span> <span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ArrayTypeDim</span>
<span class="err">└─</span> <span class="nx">ArrayInitializer</span><span class="p">[</span> <span class="p">@</span><span class="nd">Length</span> <span class="o">=</span> <span class="mi">3</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">NumericLiteral</span> <span class="dl">"</span><span class="s2">1</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">NumericLiteral</span> <span class="dl">"</span><span class="s2">2</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">NumericLiteral</span> <span class="dl">"</span><span class="s2">3</span><span class="dl">"</span></code></pre></figure>
</td></tr></table>
</details>
<h5 id="method-call-chains-are-left-recursive">Method call chains are left-recursive</h5>
<ul>
<li>What: The nodes <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.2.0/net/sourceforge/pmd/lang/java/ast/ASTPrimaryPrefix.html#"><code>ASTPrimaryPrefix</code></a> and <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.2.0/net/sourceforge/pmd/lang/java/ast/ASTPrimarySuffix.html#"><code>ASTPrimarySuffix</code></a> are removed from the
grammar. Subtrees for primary expressions appear to be left-recursive now.</li>
<li>Why: Allows to reuse abstractions like method calls without introducing a new artificial node (like method chain).</li>
<li>Related issue: <a href="https://github.com/pmd/pmd/pull/1759">[java] New expression and type grammar (#1759)</a></li>
</ul>
<details>
<summary>Method call chain Examples</summary>
<table>
<tr><th>Code</th><th>Old AST (PMD 6)</th><th>New AST (PMD 7)</th></tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="k">new</span> <span class="nc">Foo</span><span class="o">().</span><span class="na">bar</span><span class="o">.</span><span class="na">foo</span><span class="o">(</span><span class="mi">1</span><span class="o">);</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">StatementExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">├─</span> <span class="nx">PrimaryPrefix</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">AllocationExpression</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">ClassOrInterfaceType</span> <span class="dl">"</span><span class="s2">Foo</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Arguments</span> <span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="err">├─</span> <span class="nx">PrimarySuffix</span> <span class="dl">"</span><span class="s2">bar</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">PrimarySuffix</span> <span class="dl">"</span><span class="s2">foo</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">PrimarySuffix</span><span class="p">[</span> <span class="p">@</span><span class="nd">Arguments</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">Arguments</span> <span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="err">└─</span> <span class="nx">ArgumentList</span>
<span class="err">└─</span> <span class="nx">Expression</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err">└─</span> <span class="nx">Literal</span> <span class="dl">"</span><span class="s2">1</span><span class="dl">"</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">ExpressionStatement</span>
<span class="err">└─</span> <span class="nx">MethodCall</span> <span class="dl">"</span><span class="s2">foo</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">FieldAccess</span> <span class="dl">"</span><span class="s2">bar</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ConstructorCall</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">Foo</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ArgumentList</span> <span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="err">└─</span> <span class="nx">ArgumentList</span> <span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="err">└─</span> <span class="nx">NumericLiteral</span> <span class="dl">"</span><span class="s2">1</span><span class="dl">"</span></code></pre></figure>
</td></tr></table>
</details>
<p>Instead of being flat, the subexpressions are now nested within one another.
The nesting follows the naturally recursive structure of expressions:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">new</span> <span class="nc">Foo</span><span class="o">().</span><span class="na">bar</span><span class="o">.</span><span class="na">foo</span><span class="o">(</span><span class="mi">1</span><span class="o">)</span>
<span class="err">└───────┘</span> <span class="err"></span> <span class="err"></span> <span class="nc">ConstructorCall</span>
<span class="err">└───────────┘</span> <span class="err"></span> <span class="nc">FieldAccess</span>
<span class="err">└──────────────────┘</span> <span class="nc">MethodCall</span>
</code></pre></div></div>
<p>This makes the AST more regular and easier to navigate. Each node contains
the other nodes that are relevant to it (e.g. arguments) instead of them
being spread out over several siblings. The API of all nodes has been
enriched with high-level accessors to query the AST in a semantic way,
without bothering with the placement details.</p>
<p>The amount of changes in the grammar that this change entails is enormous,
but hopefully firing up the designer to inspect the new structure should
give you the information you need quickly.</p>
<p>Note: this also affect binary expressions like <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTInfixExpression.html#"><code>ASTInfixExpression</code></a>.
E.g. <code class="language-plaintext highlighter-rouge">a+b+c</code> is not parsed as</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>AdditiveExpression
+ (a)
+ (b)
+ (c)
</code></pre></div></div>
<p>But it is now (note: AdditiveExpression is now InfixExpression)</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>InfixExpression
+ InfixExpression
+ (a)
+ (b)
+ (c)
</code></pre></div></div>
<h5 id="field-access-array-access-variable-access">Field access, array access, variable access</h5>
<ul>
<li>What: New nodes dedicated to accessing field, variables and referencing arrays.
Also provide info about the access type, like whether a variable is read or written.
<ul>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTFieldAccess.html#"><code>ASTFieldAccess</code></a></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTVariableAccess.html#"><code>ASTVariableAccess</code></a></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTArrayAccess.html#"><code>ASTArrayAccess</code></a></li>
</ul>
</li>
<li>Why: Like MethodCalls, this was a missing abstraction in the AST that has been added now.</li>
<li>Related issue: <a href="https://github.com/pmd/pmd/pull/1759">[java] New expression and type grammar (#1759)</a></li>
</ul>
<details>
<summary>Field access, array access, variable access Examples</summary>
<table>
<tr><th>Code</th><th>Old AST (PMD 6)</th><th>New AST (PMD 7)</th></tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="n">field</span> <span class="o">=</span> <span class="mi">1</span><span class="o">;</span>
<span class="n">localVar</span> <span class="o">=</span> <span class="mi">1</span><span class="o">;</span>
<span class="n">array</span><span class="o">[</span><span class="mi">0</span><span class="o">]</span> <span class="o">=</span> <span class="mi">1</span><span class="o">;</span>
<span class="nc">Foo</span><span class="o">.</span><span class="na">staticField</span> <span class="o">=</span> <span class="n">localVar</span><span class="o">;</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">BlockStatement</span>
<span class="err">└─</span> <span class="nx">Statement</span>
<span class="err">└─</span> <span class="nx">StatementExpression</span>
<span class="err">├─</span> <span class="nx">PrimaryExpression</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">field</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">AssignmentOperator</span> <span class="dl">"</span><span class="s2">=</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">Expression</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err">└─</span> <span class="nx">Literal</span> <span class="dl">"</span><span class="s2">1</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">BlockStatement</span>
<span class="err">└─</span> <span class="nx">Statement</span>
<span class="err">└─</span> <span class="nx">StatementExpression</span>
<span class="err">├─</span> <span class="nx">PrimaryExpression</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">localVar</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">AssignmentOperator</span> <span class="dl">"</span><span class="s2">=</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">Expression</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err">└─</span> <span class="nx">Literal</span> <span class="dl">"</span><span class="s2">1</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">BlockStatement</span>
<span class="err">└─</span> <span class="nx">Statement</span>
<span class="err">└─</span> <span class="nx">StatementExpression</span>
<span class="err">├─</span> <span class="nx">PrimaryExpression</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">PrimaryPrefix</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">array</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">PrimarySuffix</span><span class="p">[</span> <span class="p">@</span><span class="nd">ArrayDereference</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Expression</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Literal</span> <span class="dl">"</span><span class="s2">0</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">AssignmentOperator</span> <span class="dl">"</span><span class="s2">=</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">Expression</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err">└─</span> <span class="nx">Literal</span> <span class="dl">"</span><span class="s2">1</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">BlockStatement</span>
<span class="err">└─</span> <span class="nx">Statement</span>
<span class="err">└─</span> <span class="nx">StatementExpression</span>
<span class="err">├─</span> <span class="nx">PrimaryExpression</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">Foo.staticField</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">AssignmentOperator</span> <span class="dl">"</span><span class="s2">=</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">Expression</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">localVar</span><span class="dl">"</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">ExpressionStatement</span>
<span class="err">└─</span> <span class="nx">AssignmentExpression</span> <span class="dl">"</span><span class="s2">=</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">VariableAccess</span> <span class="dl">"</span><span class="s2">field</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">NumericLiteral</span> <span class="dl">"</span><span class="s2">1</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ExpressionStatement</span>
<span class="err">└─</span> <span class="nx">AssignmentExpression</span> <span class="dl">"</span><span class="s2">=</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">VariableAccess</span> <span class="dl">"</span><span class="s2">localVar</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">NumericLiteral</span> <span class="dl">"</span><span class="s2">1</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ExpressionStatement</span>
<span class="err">└─</span> <span class="nx">AssignmentExpression</span> <span class="dl">"</span><span class="s2">=</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">ArrayAccess</span><span class="p">[</span> <span class="p">@</span><span class="nd">AccessType</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">WRITE</span><span class="dl">"</span> <span class="p">]</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">VariableAccess</span> <span class="dl">"</span><span class="s2">array</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">NumericLiteral</span> <span class="dl">"</span><span class="s2">0</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">NumericLiteral</span> <span class="dl">"</span><span class="s2">1</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ExpressionStatement</span>
<span class="err">└─</span> <span class="nx">AssignmentExpression</span> <span class="dl">"</span><span class="s2">=</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">FieldAccess</span><span class="p">[</span> <span class="p">@</span><span class="nd">AccessType</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">WRITE</span><span class="dl">"</span> <span class="p">]</span> <span class="dl">"</span><span class="s2">staticField</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">TypeExpression</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">Foo</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">VariableAccess</span><span class="p">[</span> <span class="p">@</span><span class="nd">AccessType</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">READ</span><span class="dl">"</span> <span class="p">]</span> <span class="dl">"</span><span class="s2">localVar</span><span class="dl">"</span></code></pre></figure>
<ul>
<li>As seen above, an unqualified field access currently shows up as a VariableAccess. This may be fixed
future versions of PMD.</li>
</ul>
</td></tr></table>
</details>
<h5 id="explicit-nodes-for-thissuper-expressions">Explicit nodes for this/super expressions</h5>
<ul>
<li>What: <code class="language-plaintext highlighter-rouge">this</code> and <code class="language-plaintext highlighter-rouge">super</code> are now explicit nodes instead of PrimaryPrefix.
<ul>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTThisExpression.html#"><code>ASTThisExpression</code></a></li>
<li><a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTSuperExpression.html#"><code>ASTSuperExpression</code></a></li>
</ul>
</li>
<li>Why: That way these nodes can qualify other nodes like FieldAccess.</li>
<li>Related issue: <a href="https://github.com/pmd/pmd/pull/1759">[java] New expression and type grammar (#1759)</a></li>
</ul>
<details>
<summary>this/super expressions Examples</summary>
<table>
<tr><th>Code</th><th>Old AST (PMD 6)</th><th>New AST (PMD 7)</th></tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="k">this</span><span class="o">.</span><span class="na">field</span> <span class="o">=</span> <span class="mi">1</span><span class="o">;</span>
<span class="kd">super</span><span class="o">.</span><span class="na">field</span> <span class="o">=</span> <span class="mi">1</span><span class="o">;</span>
<span class="k">this</span><span class="o">.</span><span class="na">method</span><span class="o">();</span>
<span class="kd">super</span><span class="o">.</span><span class="na">method</span><span class="o">();</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">BlockStatement</span>
<span class="err">└─</span> <span class="nx">Statement</span>
<span class="err">└─</span> <span class="nx">StatementExpression</span>
<span class="err">├─</span> <span class="nx">PrimaryExpression</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">PrimaryPrefix</span><span class="p">[</span> <span class="p">@</span><span class="nd">ThisModifier</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">PrimarySuffix</span> <span class="dl">"</span><span class="s2">field</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">AssignmentOperator</span> <span class="dl">"</span><span class="s2">=</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">Expression</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err">└─</span> <span class="nx">Literal</span> <span class="dl">"</span><span class="s2">1</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">BlockStatement</span>
<span class="err">└─</span> <span class="nx">Statement</span>
<span class="err">└─</span> <span class="nx">StatementExpression</span>
<span class="err">├─</span> <span class="nx">PrimaryExpression</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">PrimaryPrefix</span><span class="p">[</span> <span class="p">@</span><span class="nd">SuperModifier</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">PrimarySuffix</span> <span class="dl">"</span><span class="s2">field</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">AssignmentOperator</span> <span class="dl">"</span><span class="s2">=</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">Expression</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err">└─</span> <span class="nx">Literal</span> <span class="dl">"</span><span class="s2">1</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">BlockStatement</span>
<span class="err">└─</span> <span class="nx">Statement</span>
<span class="err">└─</span> <span class="nx">StatementExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">├─</span> <span class="nx">PrimaryPrefix</span><span class="p">[</span> <span class="p">@</span><span class="nd">ThisModifier</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">PrimarySuffix</span> <span class="dl">"</span><span class="s2">method</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">PrimarySuffix</span><span class="p">[</span> <span class="p">@</span><span class="nd">Arguments</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">Arguments</span> <span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="err">└─</span> <span class="nx">BlockStatement</span>
<span class="err">└─</span> <span class="nx">Statement</span>
<span class="err">└─</span> <span class="nx">StatementExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">├─</span> <span class="nx">PrimaryPrefix</span><span class="p">[</span> <span class="p">@</span><span class="nd">SuperModifier</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">PrimarySuffix</span> <span class="dl">"</span><span class="s2">method</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">PrimarySuffix</span><span class="p">[</span> <span class="p">@</span><span class="nd">Arguments</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">Arguments</span> <span class="p">(</span><span class="mi">0</span><span class="p">)</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">ExpressionStatement</span>
<span class="err">└─</span> <span class="nx">AssignmentExpression</span> <span class="dl">"</span><span class="s2">=</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">FieldAccess</span><span class="p">[</span> <span class="p">@</span><span class="nd">AccessType</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">WRITE</span><span class="dl">"</span> <span class="p">]</span> <span class="dl">"</span><span class="s2">field</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ThisExpression</span>
<span class="err">└─</span> <span class="nx">NumericLiteral</span> <span class="dl">"</span><span class="s2">1</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ExpressionStatement</span>
<span class="err">└─</span> <span class="nx">AssignmentExpression</span> <span class="dl">"</span><span class="s2">=</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">FieldAccess</span><span class="p">[</span> <span class="p">@</span><span class="nd">AcessType</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">WRITE</span><span class="dl">"</span> <span class="p">]</span> <span class="dl">"</span><span class="s2">field</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">SuperExpression</span>
<span class="err">└─</span> <span class="nx">NumericLiteral</span> <span class="dl">"</span><span class="s2">1</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ExpressionStatement</span>
<span class="err">└─</span> <span class="nx">MethodCall</span> <span class="dl">"</span><span class="s2">method</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">ThisExpression</span>
<span class="err">└─</span> <span class="nx">ArgumentList</span> <span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="err">└─</span> <span class="nx">ExpressionStatement</span>
<span class="err">└─</span> <span class="nx">MethodCall</span> <span class="dl">"</span><span class="s2">method</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">SuperExpression</span>
<span class="err">└─</span> <span class="nx">ArgumentList</span> <span class="p">(</span><span class="mi">0</span><span class="p">)</span></code></pre></figure>
</td></tr></table>
</details>
<h5 id="type-expressions">Type expressions</h5>
<ul>
<li>What: The node <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTTypeExpression.html#"><code>ASTTypeExpression</code></a> wraps a <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTType.html#"><code>ASTType</code></a> node (such as
<a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTClassType.html#"><code>ASTClassType</code></a>) and is used to qualify a method call or field access or method reference.</li>
<li>Why: Simplify the qualifier of method calls, treat instanceof as infix expression.</li>
<li>Related issue: <a href="https://github.com/pmd/pmd/pull/2039">[java] Grammar type expr (#2039)</a></li>
</ul>
<details>
<summary>Type expressions Examples</summary>
<table>
<tr><th>Code</th><th>Old AST (PMD 6)</th><th>New AST (PMD 7)</th></tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nc">Foo</span><span class="o">.</span><span class="na">staticMethod</span><span class="o">();</span>
<span class="k">if</span> <span class="o">(</span><span class="n">x</span> <span class="k">instanceof</span> <span class="nc">Foo</span><span class="o">)</span> <span class="o">{}</span>
<span class="kt">var</span> <span class="n">x</span> <span class="o">=</span> <span class="nl">Foo:</span><span class="o">:</span><span class="n">method</span><span class="o">;</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">BlockStatement</span>
<span class="err">└─</span> <span class="nx">Statement</span>
<span class="err">└─</span> <span class="nx">StatementExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">├─</span> <span class="nx">PrimaryPrefix</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">Foo.staticMethod</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">PrimarySuffix</span><span class="p">[</span> <span class="p">@</span><span class="nd">Arguments</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">Arguments</span> <span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="err">└─</span> <span class="nx">BlockStatement</span>
<span class="err">└─</span> <span class="nx">Statement</span>
<span class="err">└─</span> <span class="nx">IfStatement</span>
<span class="err">├─</span> <span class="nx">Expression</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">InstanceOfExpression</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">PrimaryExpression</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">x</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Type</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ReferenceType</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ClassOrInterfaceType</span> <span class="dl">"</span><span class="s2">Foo</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">Statement</span>
<span class="err">└─</span> <span class="nx">Block</span>
<span class="err">└─</span> <span class="nx">BlockStatement</span>
<span class="err">└─</span> <span class="nx">LocalVariableDeclaration</span>
<span class="err">└─</span> <span class="nx">VariableDeclarator</span>
<span class="err">├─</span> <span class="nx">VariableDeclaratorId</span> <span class="dl">"</span><span class="s2">x</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">VariableInitializer</span>
<span class="err">└─</span> <span class="nx">Expression</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">├─</span> <span class="nx">PrimaryPrefix</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">Foo</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">PrimarySuffix</span>
<span class="err">└─</span> <span class="nx">MemberSelector</span>
<span class="err">└─</span> <span class="nx">MethodReference</span> <span class="dl">"</span><span class="s2">method</span><span class="dl">"</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">ExpressionStatement</span>
<span class="err">└─</span> <span class="nx">MethodCall</span> <span class="dl">"</span><span class="s2">staticMethod</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">TypeExpression</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">Foo</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ArgumentList</span> <span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="err">└─</span> <span class="nx">IfStatement</span>
<span class="err">├─</span> <span class="nx">InfixExpression</span> <span class="dl">"</span><span class="s2">instanceof</span><span class="dl">"</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">VariableAccess</span><span class="p">[</span> <span class="p">@</span><span class="nd">AccessType</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">READ</span><span class="dl">"</span> <span class="p">]</span> <span class="dl">"</span><span class="s2">x</span><span class="dl">"</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">TypeExpression</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">Foo</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">Block</span>
<span class="err">└─</span> <span class="nx">LocalVariableDeclaration</span>
<span class="err">├─</span> <span class="nx">ModifierList</span>
<span class="err">└─</span> <span class="nx">VariableDeclarator</span>
<span class="err">├─</span> <span class="nx">VariableId</span> <span class="dl">"</span><span class="s2">x</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">MethodReference</span> <span class="dl">"</span><span class="s2">method</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">TypeExpression</span>
<span class="err">└─</span> <span class="nx">ClassType</span> <span class="dl">"</span><span class="s2">Foo</span><span class="dl">"</span></code></pre></figure>
</td></tr></table>
</details>
<h5 id="merge-unary-expressions">Merge unary expressions</h5>
<ul>
<li>What: Merge AST nodes for postfix and prefix expressions into the single <a href="https://docs.pmd-code.org/apidocs/pmd-java/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTUnaryExpression.html#"><code>ASTUnaryExpression</code></a> node.
The merged nodes are:
<ul>
<li>PreIncrementExpression</li>
<li>PreDecrementExpression</li>
<li>UnaryExpression</li>
<li>UnaryExpressionNotPlusMinus</li>
</ul>
</li>
<li>Why: Those nodes were asymmetric, and inconsistently nested within UnaryExpression. By definition, theyre all unary,
so that using a single node is appropriate.</li>
<li>Related issues:
<ul>
<li><a href="https://github.com/pmd/pmd/pull/1890">[java] Merge different increment/decrement expressions (#1890)</a></li>
<li><a href="https://github.com/pmd/pmd/pull/2155">[java] Merge prefix/postfix expressions into one node (#2155)</a></li>
</ul>
</li>
</ul>
<details>
<summary>Unary Expressions Examples</summary>
<table>
<tr><th>Code</th><th>Old AST (PMD 6)</th><th>New AST (PMD 7)</th></tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="o">++</span><span class="n">a</span><span class="o">;</span>
<span class="o">--</span><span class="n">b</span><span class="o">;</span>
<span class="n">c</span><span class="o">++;</span>
<span class="n">d</span><span class="o">--;</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">StatementExpression</span>
<span class="err">└─</span> <span class="nx">PreIncrementExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">a</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">StatementExpression</span>
<span class="err">└─</span> <span class="nx">PreDecrementExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">b</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">StatementExpression</span>
<span class="err">└─</span> <span class="nx">PostfixExpression</span> <span class="dl">"</span><span class="s2">++</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">c</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">StatementExpression</span>
<span class="err">└─</span> <span class="nx">PostfixExpression</span> <span class="dl">"</span><span class="s2">--</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">d</span><span class="dl">"</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">ExpressionStatement</span>
<span class="err">└─</span> <span class="nx">UnaryExpression</span><span class="p">[</span> <span class="p">@</span><span class="nd">Prefix</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">][</span> <span class="p">@</span><span class="nd">Operator</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">++</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">VariableAccess</span><span class="p">[</span> <span class="p">@</span><span class="nd">AccessType</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">WRITE</span><span class="dl">"</span> <span class="p">]</span> <span class="dl">"</span><span class="s2">a</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ExpressionStatement</span>
<span class="err">└─</span> <span class="nx">UnaryExpression</span><span class="p">[</span> <span class="p">@</span><span class="nd">Prefix</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">][</span> <span class="p">@</span><span class="nd">Operator</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">--</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">VariableAccess</span><span class="p">[</span> <span class="p">@</span><span class="nd">AccessType</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">WRITE</span><span class="dl">"</span> <span class="p">]</span> <span class="dl">"</span><span class="s2">b</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ExpressionStatement</span>
<span class="err">└─</span> <span class="nx">UnaryExpression</span><span class="p">[</span> <span class="p">@</span><span class="nd">Prefix</span> <span class="o">=</span> <span class="kc">false</span><span class="p">()</span> <span class="p">][</span> <span class="p">@</span><span class="nd">Operator</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">++</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">VariableAccess</span><span class="p">[</span> <span class="p">@</span><span class="nd">AccessType</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">WRITE</span><span class="dl">"</span> <span class="p">]</span> <span class="dl">"</span><span class="s2">c</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">ExpressionStatement</span>
<span class="err">└─</span> <span class="nx">UnaryExpression</span><span class="p">[</span> <span class="p">@</span><span class="nd">Prefix</span> <span class="o">=</span> <span class="kc">false</span><span class="p">()</span> <span class="p">][</span> <span class="p">@</span><span class="nd">Operator</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">--</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">└─</span> <span class="nx">VariableAccess</span><span class="p">[</span> <span class="p">@</span><span class="nd">AccessType</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">WRITE</span><span class="dl">"</span> <span class="p">]</span> <span class="dl">"</span><span class="s2">d</span><span class="dl">"</span></code></pre></figure>
</td></tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="n">x</span> <span class="o">=</span> <span class="o">~</span><span class="n">a</span><span class="o">;</span>
<span class="n">x</span> <span class="o">=</span> <span class="o">+</span><span class="n">a</span><span class="o">;</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">UnaryExpressionNotPlusMinus</span> <span class="dl">"</span><span class="s2">~</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">a</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">UnaryExpression</span> <span class="dl">"</span><span class="s2">+</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">a</span><span class="dl">"</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">UnaryExpression</span><span class="p">[</span> <span class="p">@</span><span class="nd">Prefix</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span> <span class="dl">"</span><span class="s2">~</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">VariableAccess</span> <span class="dl">"</span><span class="s2">a</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">UnaryExpression</span><span class="p">[</span> <span class="p">@</span><span class="nd">Prefix</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">]</span> <span class="dl">"</span><span class="s2">+</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">VariableAccess</span> <span class="dl">"</span><span class="s2">a</span><span class="dl">"</span></code></pre></figure>
</td></tr>
</table>
</details>
<h5 id="binary-operators-are-left-recursive">Binary operators are left-recursive</h5>
<ul>
<li>What: For each operator, there were separate AST nodes (like AdditiveExpression, AndExpression, …).
These are now unified into a <code class="language-plaintext highlighter-rouge">InfixExpression</code>, which gives access to the operator via <code class="language-plaintext highlighter-rouge">getOperator()</code>
and to the operands (<code class="language-plaintext highlighter-rouge">getLhs()</code>, <code class="language-plaintext highlighter-rouge">getRhs()</code>). Additionally, the resulting AST is not flat anymore,
but a more structured tree.</li>
<li>Why: Having different AST node types doesnt add information, that the operator doesnt already provide.
The new structure as a result, that the expressions are now parsed left recursive, makes the AST more JLS-like.
This makes it easier for the type mapping algorithms. It also provides the information, which operands are
used with which operator. This information was lost if more than 2 operands where used and the tree was
flattened with PMD 6.</li>
<li>Related issue: <a href="https://github.com/pmd/pmd/pull/1979">[java] Make binary operators left-recursive (#1979)</a></li>
</ul>
<details>
<summary>Binary operators Examples</summary>
<table>
<tr><th>Code</th><th>Old AST (PMD 6)</th><th>New AST (PMD 7)</th></tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span> <span class="o">*</span> <span class="mi">2</span> <span class="o">*</span> <span class="mi">3</span> <span class="o">%</span> <span class="mi">4</span><span class="o">;</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">Expression</span>
<span class="err">└─</span> <span class="nx">MultiplicativeExpression</span> <span class="dl">"</span><span class="s2">%</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">PrimaryExpression</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Literal</span> <span class="dl">"</span><span class="s2">1</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">PrimaryExpression</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Literal</span> <span class="dl">"</span><span class="s2">2</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">PrimaryExpression</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Literal</span> <span class="dl">"</span><span class="s2">3</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err">└─</span> <span class="nx">Literal</span> <span class="dl">"</span><span class="s2">4</span><span class="dl">"</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">InfixExpression</span><span class="p">[</span> <span class="p">@</span><span class="nd">Operator</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">%</span><span class="dl">'</span> <span class="p">]</span>
<span class="err">├─</span> <span class="nx">InfixExpression</span><span class="p">[@</span><span class="nd">Operator</span><span class="o">=</span><span class="dl">'</span><span class="s1">*</span><span class="dl">'</span><span class="p">]</span>
<span class="err"></span> <span class="err">├─</span> <span class="nx">InfixExpression</span><span class="p">[@</span><span class="nd">Operator</span><span class="o">=</span><span class="dl">'</span><span class="s1">*</span><span class="dl">'</span><span class="p">]</span>
<span class="err"></span> <span class="err"></span> <span class="err">├─</span> <span class="nx">NumericLiteral</span><span class="p">[@</span><span class="nd">ValueAsInt</span><span class="o">=</span><span class="mi">1</span><span class="p">]</span>
<span class="err"></span> <span class="err"></span> <span class="err">└─</span> <span class="nx">NumericLiteral</span><span class="p">[@</span><span class="nd">ValueAsInt</span><span class="o">=</span><span class="mi">2</span><span class="p">]</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">NumericLiteral</span><span class="p">[@</span><span class="nd">ValueAsInt</span><span class="o">=</span><span class="mi">3</span><span class="p">]</span>
<span class="err">└─</span> <span class="nx">NumericLiteral</span><span class="p">[@</span><span class="nd">ValueAsInt</span><span class="o">=</span><span class="mi">4</span><span class="p">]</span></code></pre></figure>
</td></tr>
</table>
</details>
<h5 id="parenthesized-expressions">Parenthesized expressions</h5>
<ul>
<li>What: Parentheses are not modelled in the AST anymore, but can be checked with the attributes <code class="language-plaintext highlighter-rouge">@Parenthesized</code>
and <code class="language-plaintext highlighter-rouge">@ParenthesisDepth</code></li>
<li>Why: This keeps the tree flat while still preserving the information. The tree is the same in case of unnecessary
parenthesis, which makes it harder to fool rules that look at the structure of the tree.</li>
<li>Related issue: <a href="https://github.com/pmd/pmd/pull/1872">[java] Remove ParenthesizedExpr (#1872)</a></li>
</ul>
<details>
<summary>Parenthesized expressions Examples</summary>
<table>
<tr><th>Code</th><th>Old AST (PMD 6)</th><th>New AST (PMD 7)</th></tr>
<tr><td>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="n">a</span> <span class="o">=</span> <span class="o">(((</span><span class="mi">1</span><span class="o">)));</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">StatementExpression</span>
<span class="err">├─</span> <span class="nx">PrimaryExpression</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err"></span> <span class="err">└─</span> <span class="nx">Name</span> <span class="dl">"</span><span class="s2">a</span><span class="dl">"</span>
<span class="err">├─</span> <span class="nx">AssignmentOperator</span> <span class="dl">"</span><span class="s2">=</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">Expression</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err">└─</span> <span class="nx">Expression</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err">└─</span> <span class="nx">Expression</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err">└─</span> <span class="nx">Expression</span>
<span class="err">└─</span> <span class="nx">PrimaryExpression</span>
<span class="err">└─</span> <span class="nx">PrimaryPrefix</span>
<span class="err">└─</span> <span class="nx">Literal</span> <span class="dl">"</span><span class="s2">1</span><span class="dl">"</span></code></pre></figure>
</td><td>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="err">└─</span> <span class="nx">ExpressionStatement</span>
<span class="err">└─</span> <span class="nx">AssignmentExpression</span>
<span class="err">├─</span> <span class="nx">VariableAccess</span> <span class="dl">"</span><span class="s2">a</span><span class="dl">"</span>
<span class="err">└─</span> <span class="nx">NumericLiteral</span><span class="p">[</span> <span class="p">@</span><span class="nd">Parenthesized</span> <span class="o">=</span> <span class="kc">true</span><span class="p">()</span> <span class="p">][</span> <span class="p">@</span><span class="nd">ParenthesisDepth</span> <span class="o">=</span> <span class="mi">3</span> <span class="p">]</span> <span class="dl">"</span><span class="s2">1</span><span class="dl">"</span></code></pre></figure>
</td></tr></table>
</details>
<h3 id="apex-ast">Apex AST</h3>
<p>PMD 7.0.0 switched the underlying parser for Apex code from Jorje to <a href="https://github.com/google/summit-ast">Summit AST</a>,
which is based on an open source grammar for Apex: <a href="https://github.com/nawforce/apex-parser">apex-parser</a>.</p>
<p>The produced AST is mostly compatible, there are some unavoidable changes however:</p>
<ul>
<li>Node <code class="language-plaintext highlighter-rouge">Method</code> (<a href="https://docs.pmd-code.org/apidocs/pmd-apex/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/apex/ast/ASTMethod.html#"><code>ASTMethod</code></a>)
<ul>
<li>No attribute <code class="language-plaintext highlighter-rouge">@Synthetic</code> anymore. Unlike Jorje, Summit AST doesnt generate synthetic methods anymore, so
this attribute would have been always false and is of no use. Therefore it has been removed completely.</li>
<li>There will be no methods anymore with the name <code class="language-plaintext highlighter-rouge">&lt;clinit&gt;</code>, <code class="language-plaintext highlighter-rouge">&lt;init&gt;</code>.</li>
</ul>
</li>
<li>There is no node <code class="language-plaintext highlighter-rouge">BridgeMethodCreator</code> anymore. This was an artificially generated node by Jorje. Since the
new parser doesnt generate synthetic methods anymore, this node is not needed anymore.</li>
<li>There is in general no attribute <code class="language-plaintext highlighter-rouge">@Namespace</code> anymore. The attribute has been removed, as it was never fully
implemented. It always returned an empty string.</li>
<li>Node <code class="language-plaintext highlighter-rouge">ReferenceExpression</code> (<a href="https://docs.pmd-code.org/apidocs/pmd-apex/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/apex/ast/ASTReferenceExpression.html#"><code>ASTReferenceExpression</code></a>)
<ul>
<li>No attribute <code class="language-plaintext highlighter-rouge">@Context</code> anymore. It was not used and always returned <code class="language-plaintext highlighter-rouge">null</code>.</li>
</ul>
</li>
</ul>
<h3 id="language-versions">Language versions</h3>
<ul>
<li>Since all languages now have defined language versions, you could now write rules that apply only for specific
versions (using <code class="language-plaintext highlighter-rouge">minimumLanguageVersion</code> and <code class="language-plaintext highlighter-rouge">maximumLanguageVersion</code>).</li>
<li>All languages have a default version. If no specific version on the CLI is given using <code class="language-plaintext highlighter-rouge">--use-version</code>, then
this default version will be used. Usually the latest version is the default version.</li>
<li>The available versions for each language can be seen in the help message of the CLI <code class="language-plaintext highlighter-rouge">pmd check --help</code>.</li>
<li>See also <a href="pmd_release_notes_pmd7.html#changed-language-versions">Changed: Language versions</a></li>
</ul>
<h3 id="migrating-custom-cpd-language-modules">Migrating custom CPD language modules</h3>
<p>This is only relevant, if you are maintaining a CPD language module for a custom language.</p>
<ul>
<li>Instead of <code class="language-plaintext highlighter-rouge">AbstractLanguage</code> extend now <a href="https://docs.pmd-code.org/apidocs/pmd-core/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/impl/CpdOnlyLanguageModuleBase.html#"><code>CpdOnlyLanguageModuleBase</code></a>.</li>
<li>Instead of <code class="language-plaintext highlighter-rouge">AntlrTokenManager</code> use now <a href="https://docs.pmd-code.org/apidocs/pmd-core/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/TokenManager.html#"><code>TokenManager</code></a></li>
<li>Instead of <code class="language-plaintext highlighter-rouge">AntlrTokenFilter</code> also use now <a href="https://docs.pmd-code.org/apidocs/pmd-core/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/TokenManager.html#"><code>TokenManager</code></a></li>
<li>Instead of <code class="language-plaintext highlighter-rouge">AntlrTokenFilter</code> extend now <a href="https://docs.pmd-code.org/apidocs/pmd-core/7.3.0-SNAPSHOT/net/sourceforge/pmd/cpd/impl/BaseTokenFilter.html#"><code>BaseTokenFilter</code></a></li>
<li>CPD Module discovery change. The service loader wont load anymore <code class="language-plaintext highlighter-rouge">src/main/resources/META-INF/services/net.sourceforge.pmd.cpd.Language</code>
but instead <code class="language-plaintext highlighter-rouge">src/main/resources/META-INF/services/net.sourceforge.pmd.lang.Language</code>. This is the unified
language interface for both PMD and CPD capable languages. See also the subinterfaces
<a href="https://docs.pmd-code.org/apidocs/pmd-core/7.3.0-SNAPSHOT/net/sourceforge/pmd/cpd/CpdCapableLanguage.html#"><code>CpdCapableLanguage</code></a> and <a href="https://docs.pmd-code.org/apidocs/pmd-core/7.3.0-SNAPSHOT/net/sourceforge/pmd/lang/PmdCapableLanguage.html#"><code>PmdCapableLanguage</code></a>.</li>
<li>The documentation <a href="pmd_devdocs_major_adding_new_cpd_language.html">How to add a new CPD language</a> has been updated
to reflect these changes.</li>
</ul>
<h3 id="build-tools">Build Tools</h3>
<div class="alert alert-info" role="alert"><i class="fas fa-info-circle"></i> <b>Note:</b>
When you switch from PMD 6.x to PMD 7 in your build tools, you most likely need to review your
ruleset(s) as well and check for removed rules.
See the use case <a href="#im-using-only-built-in-rules">Im using only built-in rules</a> above.
</div>
<h4 id="ant">Ant</h4>
<ul>
<li>The Ant tasks <a href="https://docs.pmd-code.org/apidocs/pmd-ant/7.3.0-SNAPSHOT/net/sourceforge/pmd/ant/PMDTask.html#"><code>PMDTask</code></a> and <a href="https://docs.pmd-code.org/apidocs/pmd-ant/7.3.0-SNAPSHOT/net/sourceforge/pmd/ant/CPDTask.html#"><code>CPDTask</code></a> have been moved from the module
<code class="language-plaintext highlighter-rouge">pmd-core</code> into the new module <code class="language-plaintext highlighter-rouge">pmd-ant</code>.</li>
<li>You need to add this dependency/jar file onto the class path (<code class="language-plaintext highlighter-rouge">net.sourceforge.pmd:pmd-ant</code>) in order to
import the tasks into your build file.</li>
<li>When using the guide <a href="pmd_userdocs_tools_ant.html">Ant Task Usage</a> then no change is needed, since
the pmd-ant jar file is included in the binary distribution of PMD. It is part of PMDs lib folder.</li>
</ul>
<h4 id="maven">Maven</h4>
<ul>
<li>Since maven-pmd-plugin 3.22.0, PMD 7 is supported directly.</li>
<li>See <a href="https://issues.apache.org/jira/browse/MPMD-379">MPMD-379</a></li>
<li>See <a href="pmd_userdocs_tools_maven.html#using-pmd-7-with-maven-pmd-plugin">Using PMD 7 with maven-pmd-plugin</a></li>
</ul>
<h4 id="gradle">Gradle</h4>
<ul>
<li>Gradle uses internally PMDs Ant task to execute PMD</li>
<li>Gradle 8.6 supports PMD 7 out of the box, but does not yet use PMD 7 by default.</li>
<li>You can set <code class="language-plaintext highlighter-rouge">toolVersion = "7.3.0-SNAPSHOT"</code>.</li>
<li>Only for older gradle versions you need to configure the dependencies manually for now, since
the ant task is in an own dependency with PMD 7:
<div class="language-groovy highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">pmd</span> <span class="s1">'net.sourceforge.pmd:pmd-ant:7.3.0-SNAPSHOT'</span>
<span class="n">pmd</span> <span class="s1">'net.sourceforge.pmd:pmd-java:7.3.0-SNAPSHOT'</span>
</code></pre></div> </div>
</li>
<li>See <a href="https://github.com/gradle/gradle/issues/24502">Support for PMD 7.0</a></li>
</ul>
<h3 id="xml-report-format">XML Report Format</h3>
<p>The <a href="pmd_userdocs_report_formats.html#xml">XML Report format</a> supports rendering <a href="pmd_userdocs_suppressing_warnings.html">suppressed violations</a>.</p>
<p>The content of the attribute <code class="language-plaintext highlighter-rouge">suppressiontype</code> is changed in PMD 7.0.0:</p>
<ul>
<li><code class="language-plaintext highlighter-rouge">nopmd</code> ➡️ <code class="language-plaintext highlighter-rouge">//nopmd</code></li>
<li><code class="language-plaintext highlighter-rouge">annotation</code> ➡️ <code class="language-plaintext highlighter-rouge">@suppresswarnings</code></li>
<li><code class="language-plaintext highlighter-rouge">xpath</code> - new value. Suppressed via property “violationSuppressXPath”.</li>
<li><code class="language-plaintext highlighter-rouge">regex</code> - new value. Suppressed via property “violationSuppressRegex”.</li>
</ul>
<div class="tags">
<b>Tags: </b>
<a href="tag_userdocs.html" class="btn btn-outline-secondary navbar-btn cursorNorm" role="button">userdocs</a>
</div>
</div>
<footer>
<hr />
<div>
This documentation is written in markdown. <br />
If there is something missing or can be improved, edit this page on
github and create a PR:
<a
target="_blank"
href="https://github.com/pmd/pmd/blob/master/docs/pages/pmd/userdocs/migrating_to_pmd7.md"
role="button"
><i class="fab fa-github fa-lg"></i> Edit on GitHub</a
>
</div>
<hr />
<div class="row">
<div class="col-lg-12 footer">
&copy;2024 PMD Open Source Project. All rights
reserved. <br />
<span>Page last updated:</span>
June 2024 (7.3.0)<br /> Site last generated: Jun 28, 2024 <br />
<p>
<img src="images/logo/pmd-logo-70px.png" alt="PMD
logo"/>
</p>
</div>
</div>
</footer>
</div>
<!-- /.row -->
</div>
<!-- /.container -->
</div>
<!-- Sticky TOC column -->
<div class="toc-col">
<div id="toc"></div>
</div>
<!-- /.toc-container-wrapper -->
</div>
</div>
<script type="application/javascript" src="assets/jquery-3.5.1/jquery-3.5.1.min.js"></script>
<script type="application/javascript" src="assets/anchorjs-4.2.2/anchor.min.js"></script>
<script type="application/javascript" src="assets/navgoco-0.2.1/src/jquery.navgoco.min.js"></script>
<script type="application/javascript" src="assets/bootstrap-4.5.2-dist/js/bootstrap.bundle.min.js"></script>
<script type="application/javascript" src="assets/Simple-Jekyll-Search-1.0.8/dest/jekyll-search.js"></script>
<script type="application/javascript" src="assets/jekyll-table-of-contents/toc.js"></script>
<script type="application/javascript" src="js/tabstate.js"></script>
<script type="application/javascript" src="js/customscripts.js"></script>
</body>
</html>