---
schema_version: "1"
id: 4da8f8cc25f8c59119ef0be0b78295cda1efa618728729651b26eb76f8409cde
title: PMD
collection: developer
version: current
locale: en-us
portal_url: https://docs.salesforce.com/developer/current/en-us/code-analyzer/salesforce-code-analyzer/guides/engine-pmd.md
canonical_url: https://developer.salesforce.com/docs/platform/salesforce-code-analyzer/guide/engine-pmd.html
source_site: developer.salesforce.com
content_type: documentation
content_hash: 5331c9b7f54e1d0a028e4c340fa2f89ab2c8f9003c60c11b70fced66d61e0d4a
products:
  - Salesforce Code Analyzer
---
# PMD

PMD is a source code analyzer that performs static analysis of code written in a number of languages. Its bundled rules detect common flaws in code, such as empty catch blocks or unused variables.

## Available PMD Rules

Code Analyzer supports PMD rules for these languages:

- [Apex](https://pmd.github.io/pmd/pmd_rules_apex.html)
- [HTML](https://pmd.github.io/pmd/pmd_rules_html.html)
- [JavaScript](https://pmd.github.io/pmd/pmd_rules_ecmascript.html)
- [XML](https://pmd.github.io/pmd/pmd_rules_xml.html)
- [Visualforce](https://pmd.github.io/pmd/pmd_rules_visualforce.html)

Run this command to view detailed information about the PMD rules for the languages you've configured; the default languages are `apex` and `visualforce`.

```bash
sf code-analyzer rules --rule-selector pmd --view detail
```

For information on how to modify rule settings, such as their severity or tags, see [Customize Your Configuration](https://developer.salesforce.com/docs/platform/salesforce-code-analyzer/guide/config-custom.md). While the examples show modifying rules for the ESLint and Regex engines, you use the same process to modify PMD rules.

## PMD AppExchange Rules

In addition to the base PMD rules, Code Analyzer provides PMD AppExchange rules that help you prepare your managed packages for security review. See [PMD AppExchange Rules Reference](https://developer.salesforce.com/docs/platform/salesforce-code-analyzer/guide/rules-pmd-appexchange.md) for details, including examples of code snippets that cause security violations.

For full instructions on preparing for the AppExchange security review with Code Analyzer, read [Scan Your Solution with Salesforce Code Analyzer](https://developer.salesforce.com/docs/atlas.en-us.packagingGuide.meta/packagingGuide/security_review_code_analyzer_scan.htm) in the ISVforce Guide.

## Add Custom PMD Rules

PMD allows you to create your own custom rules to check for patterns specific to your codebase, or the coding practices of your team. You can then add these custom rules to the list of PMD rules that Code Analyzer runs.

Follow these steps to add custom PMD rules to Code Analyzer.

1. Create your custom PMD rule by following the instructions in [Extending PMD](https://docs.pmd-code.org/latest/pmd_userdocs_extending_writing_rules_intro.html).

   PMD supports the ability to create custom Java rules classes. It also provides the ability to reuse its XPathRule class by supplying your own XPath expression to match against the DOM view of the AST.

   - If you create a custom Java rule, then you must bundle your Java class into a JAR file. A [ruleset xml file](https://docs.pmd-code.org/latest/pmd_userdocs_making_rulesets.html) must then contain your rule definition and can either be contained within the same JAR file or as a separate XML file separate from the JAR file.
   - If you create an XPath based rule, then you define this rule directly inside of a [ruleset xml file](https://docs.pmd-code.org/latest/pmd_userdocs_making_rulesets.html).

2. Update your `code-analyzer.yml` file and specify the location of the XML ruleset file in the `custom_rulesets` option of the `pmd` engine. You can put this XML file in two types of locations:

   - On disk. Provide either an absolute path or a relative path to the `config_root` option of the `code-analyzer.yml` config file.
   - As a relative resource in your Java classpath, such as bundled in a JAR file.

     For example:

   ```bash
   engines:
     pmd:
       custom_rulesets:
         - rulesets/security/xml_security.xml
         - rulesets/security/html_security.xml
   ```

3. If you have one or more JAR files that contain custom JAVA rules and/or ruleset files, then add the JAR files, or the folder in which they live, to the `java_classpath_entries` option; each file or folder must be either an absolute path or relative to `config_root`.

   For example:

   ```bash
   engines:
     pmd:
       custom_rulesets:
         - rulesets/security/xml_security.xml
         - rulesets/security/html_security.xml
       java_classpath_entries:
         - custom_rules/pmd-my-xml-security-rules.jar
         - custom_rules/pmd-my-html-security-rules.jar
   ```

4. Run the `rules` command to validate that Code Analyzer knows about your rule. As a convenience, Code Analyzer automatically adds the `Custom` tag to all custom rules. Run this command to see all the custom PMD rules; your new rule should be in the list:

   ```bash
   sf code-analyzer rules --rule-selector pmd:Custom
   ```

   The name of your new rule is the same as the `name` attribute of the associated `<rule>` element in the XML ruleset file. Also, to make selection of your ruleset rules easy, we add a tag to each rule that matches the `name` attribute of your ruleset (`<ruleset>` element), minus any spaces.

   For example, in this snippet of a ruleset file, each rule has the tag `MyCustomPMDRules`, and the name of one of the rules is `CheckForBadVariableNames`:

   ```bash
   <ruleset name="My Custom PMD Rules"
    xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 https://pmd.sourceforge.io/ruleset_2_0_0.xsd">

    <rule name="CheckForBadVariableNames"
          language="apex"
   ..
   ```

   To list all the rules in the `My Custom PMD Rules` ruleset file, run this command:

   ```bash
   sf code-analyzer rules --rule-selector pmd:MyCustomPMDRules
   ```

   To view details about the `CheckForBadVariableNames` PMD rule, run this command:

   ```bash
   sf code-analyzer rules --rule-selector pmd:CheckForBadVariableNames --view detail
   ```

5. Run the `run` command to see your custom rule in action:

   ```bash
   sf code-analyzer run --rule-selector pmd:CheckForBadVariableNames --view detail
   ```

### How Custom PMD Rule Priorities Map to Code Analyzer Severity Levels

When you [add a custom PMD rule](https://developer.salesforce.com/docs/platform/salesforce-code-analyzer/guide/engine-pmd.md#add-custom-pmd-rules), its Code Analyzer severity level is derived from its PMD rule priority. This table shows the mapping:

| PMD Rule Priority | Code Analyzer Severity Level |
| ----------------- | ---------------------------- |
| 1 (High)          | 2 (High)                     |
| 2 (Medium_High)   | 3 (Moderate)                 |
| 3 (Medium)        | 3 (Moderate)                 |
| 4 (Medium_Low)    | 4 (Low)                      |
| 5 (Low)           | 4 (Low)                      |

If a default PMD rule isn't included in a custom ruleset file, Code Analyzer assigns a default severity level, which may differ from the mapping shown in the table.

You can customize the severity level of all default and custom rules by adding a `rules` field to your `code-analyzer.yml` file. See [Customize the Configuration](https://developer.salesforce.com/docs/platform/salesforce-code-analyzer/guide/config-custom.md) and the [top-level configuration reference](https://developer.salesforce.com/docs/platform/salesforce-code-analyzer/guide/config-toplevel.md) for details.

## Format of Metadata Component Files in Your Salesforce DX Project

You typically store the source code for a second-generation managed package (managed 2GP) in a Salesforce DX project, which you then usually add to a version control system, such as GitHub. The managed 2GP source consists of metadata component files that define your Salesforce app. These files are stored in one or more package directories in your Salesforce DX project; the default package directory is called `force-app`.

The metadata component files that make up your 2GP package can be in one of these formats:

- [Source format](https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_source_file_format.htm): The default and recommended format when working with Salesforce DX projects. The metadata component files are in XML format and they all have the `.xml` file extension.
- Mdapi format: The format specified by Metadata API. Each metadata component has a different file extension, although the content is still XML. For example, [permission sets](https://developer.salesforce.com/docs/atlas.en-us.api_meta.meta/api_meta/meta_permissionset.htm) are stored in a single file with the extension `.permissionset` and [custom objects](https://developer.salesforce.com/docs/atlas.en-us.api_meta.meta/api_meta/customobject.htm) are in a single file with the extension `.object`.

If you use source format, then you don't need to do any custom configuration because Code Analyzer by default analyzes XML files that have the `.xml` extension. However, if you use mdapi format in your Salesforce DX project, then you must update your `code-analyzer.yml` configuration file so Code Analyzer correctly analyzes these XML files with different extension. Specifically, you must add the file extensions of all your app's metadata types to the `file_extensions:xml` option under the `pmd` engine section.

For example, this `code-analyzer.yml` snippet results in Code Analyzer correctly running the PMD AppExchange rules on custom objects, permission sets, layouts, and flows that are in mdapi format:

```yaml
engine:
  pmd:
    file_extensions:
      apex:
        - .cls
        - .trigger
      html:
        - .html
        - .htm
        - .xhtml
        - .xht
        - .shtml
      javascript:
        - .js
        - .cjs
        - .mjs
      typescript:
        - .ts
      visualforce:
        - .page
        - .component
      xml:
        - .xml
        - .permissionset
        - .object
        - .layout
        - .flow
```

See [Metadata Types](https://developer.salesforce.com/docs/atlas.en-us.api_meta.meta/api_meta/meta_types_list.htm) in the _Metadata API Developer Guide_ for reference information for all metadata types and their file extensions.

## PMD Configuration Reference

You can configure the PMD engine with the settings listed in this table. See [Customize the Configuration](https://developer.salesforce.com/docs/platform/salesforce-code-analyzer/guide/config-custom.md) for details on how to apply the settings.

| Field | Type | Description |
| --- | --- | --- |
| `disable_engine` | boolean | Whether to turn off the 'pmd' engine so that it is not included when running Code Analyzer commands. Default value is `false`. |
| `java_command` | string | Indicates the specific 'java' command associated with the JRE or JDK to use for the 'pmd' engine. May be provided as the name of a command that exists on the path, or an absolute file path location. If unspecified, or specified as null, then an attempt will be made to automatically discover a 'java' command from your environment. Default value is `null`. |
| `file_extensions` | object | Specifies the list of file extensions to associate to each rule language. The rule(s) associated with a given language will run against all the files in your workspace containing one of the specified file extensions. Each file extension can only be associated to one language. If a specific language is not specified, then a set of default file extensions for that language will be used. Default value is `{"apex": [".cls", ".trigger"], "html": [".html", ".htm", ".xhtml", ".xht", ".shtml", ".cmp"], "javascript": [".js", ".cjs", ".mjs"], "typescript": [".ts"], "visualforce": [".page", ".component"], "xml": [".xml"]}`. |
| `java_classpath_entries` | array | List of jar files and/or folders to add the Java classpath when running PMD. Each entry may be given as an absolute path or a relative path to 'config_root'. This field is primarily used to supply custom Java based rule definitions to PMD. See https://pmd.github.io/pmd/pmd_userdocs_extending_writing_java_rules.html Default value is `[]`. |
| `custom_rulesets` | array | List of xml ruleset files containing custom PMD rules to be made available for rule selection. Each ruleset must be an xml file that is either:   <ul><li>on disk (provided as an absolute path or a relative path to 'config_root')</li><li>or a relative resource found on the Java classpath.</li></ul> Not all custom rules can be fully defined within an xml ruleset file. For example, Java based rules may be defined in jar files. In these cases, you will need to also add your additional files to the Java classpath using the 'java_classpath_entries' field. See https://pmd.github.io/pmd/pmd_userdocs_making_rulesets.html to learn more about PMD rulesets. Default value is `[]`. |


## Generate a Source File's AST Structure

When you write custom PMD rules, you need your code's [Abstract Syntax Tree](https://deepsource.com/glossary/ast) (AST), which helps you write exact XPath expressions. Use the new `ast-dump` command to view this structure directly from your command line. Generating the source file's AST structure in XML or JSON format, this command supports files written in Apex, Visualforce, HTML, XML, and JavaScript.

```
sf code-analyzer ast-dump --file ./force-app/main/default/classes/BotHandler.cls --output-file ./xpath/simple.xml

```

## See Also

- [PMD Source Analyzer](https://pmd.github.io/#home)
