pmd/pmd_projectdocs_decisions_adr_3.html

2187 lines
57 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

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="">
<meta name="keywords" content=" ">
<title>ADR 3 - API evolution principles | 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.8.0-SNAPSHOT</li>
<div class="sidebarTitleDate">Release date: 29-November-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><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>
<li><a href="pmd_rules_ecmascript_performance.html">Performance</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/main/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 class="active"><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>
» ADR 3 - API evolution principles
<a
target="_blank"
href="https://github.com/pmd/pmd/blob/main/docs/pages/pmd/projectdocs/decisions/adr-3.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">ADR 3 - API evolution principles</h1>
</div>
<div class="post-content" data-github-edit-url="https://github.com/pmd/pmd/blob/main/docs/pages/pmd/projectdocs/decisions/adr-3.md">
<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>
<!-- https://github.com/joelparkerhenderson/architecture-decision-record/blob/main/templates/decision-record-template-by-michael-nygard/index.md -->
<h2 id="context">Context</h2>
<p>The API of PMD has been growing over the years and needed some cleanup. The goal is, to
have a clear separation between a well-defined API and the implementation, which is internal.
This should help us in future development.</p>
<p>Until PMD 7.0.0, all released public members and types were implicitly considered part
of public PMD API, including inheritance-specific members (protected members, abstract methods).
We have maintained those APIs with the goal to preserve full binary compatibility between minor releases,
only breaking those APIs infrequently, for major releases.</p>
<p>PMD is used and integrated in many different tools such as IDE plugins or build plugins. These plugins
use our public API and rely on it being stable, hence we tried to break it only infrequently.</p>
<p>In order to allow PMD to move forward at a faster pace, this implicit contract will
be invalidated with PMD 7.0.0 and onwards. We now introduce more fine-grained distinctions between
the type of compatibility support we guarantee for our libraries, and ways to make
them explicit to clients of PMD.</p>
<p>The actual API development and marking some part of the API as internal or add new API is an ongoing task,
that will need to be done everytime. We wont just define an API and then are done with it.
The API will change as new features want to be implemented.</p>
<p>This decision document aims to document principles and guidelines that are used for PMD development.</p>
<h2 id="decision">Decision</h2>
<h3 id="semantic-versioning">Semantic Versioning</h3>
<p>PMD and all its modules are versioned together. PMD uses <a href="https://semver.org/spec/v2.0.0.html">Semantic Versioning 2.0.0</a>.
This means, that each PMD version consists of MAJOR.MINOR.PATCH components:</p>
<ul>
<li>MAJOR version is incremented for incompatible API changes</li>
<li>MINOR version is incremented for added functionality in a backwards compatible way</li>
<li>PATCH version is incremented for backward compatible bug fixes</li>
</ul>
<p>Additional labels for release candidates might be used.</p>
<p>Incompatible API changes shouldnt be introduced lightly. See
<a href="https://semver.org/spec/v2.0.0.html#if-even-the-tiniest-backward-incompatible-changes-to-the-public-api-require-a-major-version-bump-wont-i-end-up-at-version-4200-very-rapidly">FAQ: If even the tiniest backward incompatible changes to the public API require a major version bump, wont I end up at version 42.0.0 very rapidly?</a>.</p>
<h3 id="project-structure-and-java-base-packages-names">Project structure and Java base packages names</h3>
<p>PMD is mainly developed in the Java programming language. The build tool is Maven and the PMD build consists
of several maven modules.</p>
<ul>
<li>All packages belonging to a given module should have a common package prefix.</li>
<li>Given a package name, it should be easy to figure out to which module this package belongs. There is a 1:1 mapping
between maven module and package. This rule helps to find the source code for any fully qualified (Java) class name.</li>
<li>Two modules must not define the same packages. That means, it is not allowed that any given package spans more than
one module. Otherwise, the mapping between module and package wouldnt be unambiguous.</li>
<li>The base package for all PMD source code is <code class="language-plaintext highlighter-rouge">net.sourceforge.pmd</code>. There are many different sub packages.</li>
<li>The core module <code class="language-plaintext highlighter-rouge">pmd-core</code> uses directly the base package as the only module. All other modules must use
specific sub packages.</li>
<li>Language modules use the base package <code class="language-plaintext highlighter-rouge">net.sourceforge.pmd.lang.&lt;language id&gt;</code>.
E.g. <code class="language-plaintext highlighter-rouge">pmd-java</code> uses the package <code class="language-plaintext highlighter-rouge">net.sourceforge.pmd.lang.java</code>.</li>
<li>All other modules use the base package <code class="language-plaintext highlighter-rouge">net.sourceforge.pmd.&lt;module&gt;</code>,
E.g. <code class="language-plaintext highlighter-rouge">pmd-cli</code> uses the package <code class="language-plaintext highlighter-rouge">net.sourceforge.pmd.cli</code>.</li>
</ul>
<h3 id="criteria-for-public-api">Criteria for public API</h3>
<p>Public API is</p>
<ul>
<li>API needed to execute PMD analysis
<ul>
<li>Renderers</li>
<li>RuleSet XML Schema</li>
<li>Configuration</li>
<li>Ant Tasks</li>
</ul>
</li>
<li>API needed to implement custom rules
<ul>
<li>AST structure and classes of languages (incl. AST structure for XPath rules)</li>
<li>XPath functions</li>
<li>Language Symbol Table / Metrics / Type Resolution (Not the implementation)</li>
</ul>
</li>
</ul>
<p><strong>Not</strong> public API is</p>
<ul>
<li>Anything in packages <code class="language-plaintext highlighter-rouge">internal</code> and <code class="language-plaintext highlighter-rouge">impl</code></li>
<li>Inheritance-specific members of AST related classes and interfaces. E.g. adding a member to an
interface shouldnt be considered API breaking</li>
<li>Setters in AST classes are private. They are only used in the parser.</li>
</ul>
<h3 id="separation-between-public-api-internal-and-implementation">Separation between public API, internal and implementation</h3>
<p>All packages are considered to be public API by default, with <strong>two exceptions</strong>:</p>
<ul>
<li>
<p>Any package that contains an <code class="language-plaintext highlighter-rouge">internal</code> segment is considered internal. E.g. <code class="language-plaintext highlighter-rouge">net.sourceforge.pmd.internal</code>.
<em>Internal API</em> is meant for use <em>only</em> by the main PMD codebase. Internal types and methods
may be modified in any way, or even removed, at any time without a MAJOR version change.</p>
<p>The <code class="language-plaintext highlighter-rouge">@InternalApi</code> annotation will be used for types that have to live outside of
these packages, e.g. methods of a public type that shouldnt be used outside PMD (again,
these can be removed anytime).</p>
</li>
<li>
<p>Any package that contains an <code class="language-plaintext highlighter-rouge">impl</code> segment is considered internal. E.g. <code class="language-plaintext highlighter-rouge">net.sourceforge.pmd.lang.impl</code>.
These packages contain base classes that are needed for extending PMD (like adding a new language).
These can change at any time without a MAJOR version change.</p>
<p>In a later version, the <code class="language-plaintext highlighter-rouge">impl</code> packages could be promoted as a public API for implementing new
languages for PMD outside the main monorepo. In that sense, e.g. the module <code class="language-plaintext highlighter-rouge">pmd-java</code> is allowed
to depend on <code class="language-plaintext highlighter-rouge">impl</code> packages of <code class="language-plaintext highlighter-rouge">pmd-core</code>, but ideally it doesnt depend on <code class="language-plaintext highlighter-rouge">internal</code> packages of
<code class="language-plaintext highlighter-rouge">pmd-core</code> (or any other module). However, for now, the <code class="language-plaintext highlighter-rouge">impl</code> packages are <strong>explicitly considered
internal</strong> until this decision is revised.</p>
</li>
</ul>
<h3 id="deprecation-and-removing-of-old-apis">Deprecation and removing of old APIs</h3>
<ul>
<li>APIs can be deprecated at any time (even in PATCH versions). Deprecated APIs are marked with the
<code class="language-plaintext highlighter-rouge">@Deprecated</code> annotation.</li>
<li>Deprecations should be listed in the release notes.</li>
<li>Deprecated APIs can only be removed with a MAJOR version change.</li>
</ul>
<h3 id="experimental-apis">Experimental APIs</h3>
<ul>
<li>New features often introduce new APIs. These new APIs can be marked with the annotation <code class="language-plaintext highlighter-rouge">@Experimental</code> at
the class or method level.</li>
<li>APIs marked with the <code class="language-plaintext highlighter-rouge">@Experimental</code> annotation are subject to change and are considered <strong>not stable</strong>.
They can be modified in any way, or even removed, at any time. You should not use or rely
on them in any production code. They are purely to allow broad testing and feedback.</li>
<li>Experimental APIs can be introduced or removed with at least a MINOR version change.
These experimental APIs should be listed in the release notes.</li>
<li>Experimental APIs can be promoted to Public APIs with at least a MINOR version change.</li>
</ul>
<h3 id="guidelines-for-ast-classes">Guidelines for AST classes</h3>
<p>AST classes of the individual language modules are used by custom rule implementations and are considered
Public API in general. Rules only read the AST and do not need to modify it.</p>
<p>In order to minimize the public API surface of AST classes, the following guidelines apply:</p>
<ul>
<li>Concrete AST classes should be final, to avoid custom subclasses.</li>
<li>Concrete AST classes should only have a package private constructor to avoid manual instantiation.
Only the parser of the language (which lives in the same package) should be able to create new instances
of AST classes.</li>
<li>Concrete AST classes should not have public setters. All setters should be package private, so that
only the parser of the language can call the setters during AST construction.</li>
</ul>
<p>Non-concrete AST classes (like base classes or common interfaces) should follow similar guidelines:</p>
<ul>
<li>Only package private constructor</li>
<li>Only package private setters</li>
</ul>
<h3 id="summary-of-the-annotations">Summary of the annotations</h3>
<ul>
<li>
<p><code class="language-plaintext highlighter-rouge">@InternalApi</code> (<code class="language-plaintext highlighter-rouge">net.sourceforge.pmd.annotation.InternalApi</code>)</p>
<p>This annotation is used for API members that are not publicly supported API but have to live in
public packages (outside <code class="language-plaintext highlighter-rouge">internal</code> packages).
Such members may be removed, renamed, moved, or otherwise broken at any time and should not be
relied upon outside the main PMD codebase.</p>
</li>
<li>
<p><code class="language-plaintext highlighter-rouge">@Experimental</code> (<code class="language-plaintext highlighter-rouge">net.sourceforge.pmd.annotation.Experimental</code>)</p>
<p>API members marked with the <code class="language-plaintext highlighter-rouge">@Experimental</code> annotation at the class or method level are subject to change.
It is an indication that the feature is in experimental, unstable state.
The API members can be modified in any way, or even removed, at any time, without warning.
You should not use or rely on them in any production code. They are purely to allow broad testing and feedback.</p>
</li>
<li>
<p><code class="language-plaintext highlighter-rouge">@Deprecated</code> (<code class="language-plaintext highlighter-rouge">java.lang.Deprecated</code>)</p>
<p>API members marked with the <code class="language-plaintext highlighter-rouge">@Deprecated</code> annotation at the class or method level will remain supported
until the next major release, but it is recommended to stop using them. These members might be
removed with the next MAJOR release.</p>
</li>
</ul>
<h2 id="status">Status</h2>
<p>Accepted (Last updated: February 2024)</p>
<h2 id="consequences">Consequences</h2>
<ul>
<li>Clearly defining the API PMD provides will help to further modularize PMD using the
Java <a href="https://openjdk.org/jeps/261">Module System</a>.</li>
<li>Simpler decisions when to increase MAJOR, MINOR of PATCH version.</li>
<li>Refactoring of the implementation is possible without affecting public API.</li>
</ul>
<h2 id="change-history">Change History</h2>
<p>2024-02-01: Changed status to “Accepted”. (<a href="https://github.com/pmd/pmd/pull/4756">#4756</a>)</p>
<p>2023-12-01: Proposed initial version.</p>
<div class="tags">
</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/main/docs/pages/pmd/projectdocs/decisions/adr-3.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>
February 2024<br /> Site last generated: Nov 21, 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>