Table of Contents
Overview
PMD can report the found rule violations in various formats. Some formats can be customized further via properties. Violations might also be suppressed and there might be processing errors or configuration errors. Not all report formats display all information.
The header of the sections below are used to select the format on the command line, as
arguments to the --format
option. When a format accepts properties,
those can be specified with the --property
/ -P
option on the command-line.
--show-suppressed
is set.sarif
“SARIF, the Static Analysis Results Interchange Format, is a standard, JSON-based format for the output of static analysis tools. It has been approved as an OASIS standard” - https://docs.oasis-open.org/sarif/sarif/v2.1.0/sarif-v2.1.0.html.
SARIF schema can be found here: https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json.
PMD holds an initial implementation version of SARIF rendering. This means SARIF allows for more complexity and the current implementation can be extended.
codeclimate
Renderer for Code Climate JSON format.
This format is used when running PMD within Code Climate.
The renderer will stream JSON objects, each object is a own issue (a PMD rule violation). Each issue
is separated by the null character (\0
).
The format is specified here: https://github.com/codeclimate/platform/blob/master/spec/analyzers/SPEC.md.
The code climate format doesn’t support suppressed violations. It also doesn’t report any errors. But it contains the full rule details for each reported rule violation.
Example:
{"type":"issue","check_name":"GuardLogStatement","description":"Logger calls should be surrounded by log level guards.","content":{"body":"## GuardLogStatement\n\nSince: PMD 5.1.0\n\nPriority: Medium High\n\n[Categories](https://github.com/codeclimate/platform/blob/master/spec/analyzers/SPEC.md#categories): Style\n\n[Remediation Points](https://github.com/codeclimate/platform/blob/master/spec/analyzers/SPEC.md#remediation-points): 50000\n\nWhenever using a log level, one should check if the loglevel is actually enabled, or otherwise skip the associate String creation and manipulation.\n\n### Example:\n\n```java\n\n\n // Add this for performance\n if (log.isDebugEnabled() { ...\n log.debug('log something' + ' and ' + 'concat strings');\n\n \n``` \n\n### [PMD properties](https://pmd.github.io/pmd-6.22.0/pmd_userdocs_configuring_rules.html#rule-properties)\n\nName | Value | Description\n--- | --- | ---\nviolationSuppressRegex | | Suppress violations with messages matching a regular expression\nviolationSuppressXPath | | Suppress violations on nodes which match a given relative XPath expression.\nlogLevels | trace,debug,info,warn,error,log,finest,finer,fine,info,warning,severe | LogLevels to guard\nguardsMethods | isTraceEnabled,isDebugEnabled,isInfoEnabled,isWarnEnabled,isErrorEnabled,isLoggable | Method use to guard the log statement\n"},"categories":["Style"],"location":{"path":"/home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/RuleContext.java","lines":{"begin":124,"end":125}},"severity":"normal","remediation_points":50000}
{"type":"issue","check_name":"ForLoopCanBeForeach","description":"This for loop can be replaced by a foreach loop","content":{"body":"## ForLoopCanBeForeach\n\nSince: PMD 6.0.0\n\nPriority: Medium\n\n[Categories](https://github.com/codeclimate/platform/blob/master/spec/analyzers/SPEC.md#categories): Style\n\n[Remediation Points](https://github.com/codeclimate/platform/blob/master/spec/analyzers/SPEC.md#remediation-points): 50000\n\nReports loops that can be safely replaced with the foreach syntax. The rule considers loops over lists, arrays and iterators. A loop is safe to replace if it only uses the index variable to access an element of the list or array, only has one update statement, and loops through *every* element of the list or array left to right.\n\n### Example:\n\n```java\n\n\npublic class MyClass {\n void loop(List<String> l) {\n for (int i = 0; i < l.size(); i++) { // pre Java 1.5\n System.out.println(l.get(i));\n }\n\n for (String s : l) { // post Java 1.5\n System.out.println(s);\n }\n }\n}\n\n \n``` \n\n### [PMD properties](https://pmd.github.io/pmd-6.22.0/pmd_userdocs_configuring_rules.html#rule-properties)\n\nName | Value | Description\n--- | --- | ---\nviolationSuppressRegex | | Suppress violations with messages matching a regular expression\nviolationSuppressXPath | | Suppress violations on nodes which match a given relative XPath expression.\n"},"categories":["Style"],"location":{"path":"/home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/benchmark/Benchmarker.java","lines":{"begin":58,"end":62}},"severity":"normal","remediation_points":50000}
csv
Comma-separated values tabular format.
This format only renders rule violations. Suppressed violations or errors are ignored.
Example:
"Problem","Package","File","Priority","Line","Description","Rule set","Rule"
"1","net.sourceforge.pmd","/home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/RuleContext.java","2","124","Logger calls should be surrounded by log level guards.","Best Practices","GuardLogStatement"
"1","net.sourceforge.pmd.benchmark","/home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/benchmark/Benchmarker.java","3","58","This for loop can be replaced by a foreach loop","Best Practices","ForLoopCanBeForeach"
This format can be configured to display only certain columns. In order to not show the problem counter and package
columns, use these CLI parameters additionally: -property problem=false -property package=false
Properties:
- problem: Include problem column. Default: true.
- package: Include package column. Default: true.
- file: Include file column. Default: true.
- priority: Include priority column. Default: true.
- line: Include line column. Default: true.
- desc: Include description column. Default: true.
- ruleSet: Include Rule set column. Default: true.
- rule: Include Rule column. Default: true.
emacs
GNU Emacs integration.
Example:
/home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/RuleContext.java:124: Logger calls should be surrounded by log level guards.
/home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/benchmark/Benchmarker.java:58: This for loop can be replaced by a foreach loop
html
HTML format.
This renderer provides two properties to render a link to the source where the violations
have been found. The following example has been created with -property linkPrefix=https://github.com/pmd/pmd/blob/master/ -property linePrefix=L -shortnames -d pmd
.
If “linkPrefix” is not set, then “linePrefix” has no effect anyway: just the filename will
be rendered, with no html link. Otherwise if “linePrefix” is not set, then the link will
not contain a line number.
When using Maven JXR Plugin to generate a html view of the project’s sources, then the property “htmlExtension” needs to be set to “true”. This will then replace the normal source file extensions (e.g. “.java”) with “.html”, so that the generated html pages are referenced.
Properties:
- linePrefix: Prefix for line number anchor in the source file.
- linkPrefix: Path to HTML source.
- htmlExtension: Replace file extension with .html for the links (default: false)
ideaj
IntelliJ IDEA integration.
It has two ways of calling:
- For a single file: then all three properties need to be provided
pmd check -d src/Foo.java -R rulesets/java/quickstart.xml -f ideaj -P fileName=src/Foo.java -P sourcePath=/home/pmd/src -P classAndMethodName=Foo
- For a directory: then the fileName property can be omitted
pmd check -d src -R rulesets/java/quickstart.xml -f ideaj -P sourcePath=/home/pmd/src -P classAndMethodName=.method
Example:
Logger calls should be surrounded by log level guards.
at Foo(:124)
This for loop can be replaced by a foreach loop
at Foo(:58)
Properties:
- classAndMethodName: Class and method name, pass
.method
when processing a directory. - sourcePath:
- fileName:
json
JSON format.
This prints a single JSON object containing some header information, and then the violations grouped by file. The root object fields are
formatVersion
: an integer which will be incremented if we change the serialization formatpmdVersion
: the version of PMD that produced the reporttimestamp
: explicitfiles
: an array of objects (see the example)
summaryhtml
Summary HTML format.
This is the html renderer but with an extra section, the summarizes the violations per rule.
Properties:
- linePrefix: Prefix for line number anchor in the source file.
- linkPrefix: Path to HTML source.
- htmlExtension: Replace file extension with .html for the links (default: false)
text (default)
This is the default format.
This format outputs one line per violation. At the end, processing errors, suppressed violations and configuration errors are reported.
Example:
/home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/RuleContext.java:124: GuardLogStatement: Logger calls should be surrounded by log level guards.
/home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/benchmark/Benchmarker.java:58: ForLoopCanBeForeach: This for loop can be replaced by a foreach loop
/home/pmd/source/pmd-core/src/test/resources/net/sourceforge/pmd/cpd/files/file_with_ISO-8859-1_encoding.java - PMDException: Error while parsing /home/pmd/source/pmd-core/src/test/resources/net/sourceforge/pmd/cpd/files/file_with_ISO-8859-1_encoding.java
CloseResource rule violation suppressed by Annotation in /home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java
LoosePackageCoupling - No packages or classes specified
textcolor
Text format, with color support (requires ANSI console support, e.g. xterm, rxvt, etc.).
Example:
* file: ./pmd-core/src/main/java/net/sourceforge/pmd/RuleContext.java src: RuleContext.java:124:125 rule: GuardLogStatement msg: Logger calls should be surrounded by log level guards. code: LOG.warning("The method RuleContext::setSourceCodeFilename(String) has been deprecated and will be removed." * file: ./pmd-core/src/main/java/net/sourceforge/pmd/benchmark/Benchmarker.java src: Benchmarker.java:58:62 rule: ForLoopCanBeForeach msg: This for loop can be replaced by a foreach loop code: for (int i = 0; i < args.length; i++) { Summary: net.sourceforge.pmd.RuleContext : 1 net.sourceforge.pmd.benchmark.Benchmarker : 1 * file: ./pmd-core/src/test/resources/net/sourceforge/pmd/cpd/files/file_with_ISO-8859-1_encoding.java err: PMDException: Error while parsing /home/pmd/source/pmd-core/src/test/resources/net/sourceforge/pmd/cpd/files/file_with_ISO-8859-1_encoding.java net.sourceforge.pmd.PMDException: Error while parsing /home/pmd/source/pmd-core/src/test/resources/net/sourceforge/pmd/cpd/files/file_with_ISO-8859-1_encoding.java at net.sourceforge.pmd.SourceCodeProcessor.processSourceCodeWithoutCache(SourceCodeProcessor.java:110) at net.sourceforge.pmd.SourceCodeProcessor.processSourceCode(SourceCodeProcessor.java:89) at net.sourceforge.pmd.SourceCodeProcessor.processSourceCode(SourceCodeProcessor.java:51) at net.sourceforge.pmd.processor.PmdRunnable.call(PmdRunnable.java:78) at net.sourceforge.pmd.processor.PmdRunnable.call(PmdRunnable.java:24) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630) at java.base/java.lang.Thread.run(Thread.java:832) Caused by: net.sourceforge.pmd.lang.java.ast.ParseException: Encountered " "-" "- "" at line 6, column 30. Was expecting one of: "extends" ... "implements" ... "{" ... "<" ... at net.sourceforge.pmd.lang.java.ast.JavaParser.generateParseException(JavaParser.java:12713) at net.sourceforge.pmd.lang.java.ast.JavaParser.jj_consume_token(JavaParser.java:12597) at net.sourceforge.pmd.lang.java.ast.JavaParser.ClassOrInterfaceBody(JavaParser.java:1554) at net.sourceforge.pmd.lang.java.ast.JavaParser.ClassOrInterfaceDeclaration(JavaParser.java:732) at net.sourceforge.pmd.lang.java.ast.JavaParser.TypeDeclaration(JavaParser.java:639) at net.sourceforge.pmd.lang.java.ast.JavaParser.CompilationUnit(JavaParser.java:373) at net.sourceforge.pmd.lang.java.AbstractJavaParser.parse(AbstractJavaParser.java:62) at net.sourceforge.pmd.SourceCodeProcessor.parse(SourceCodeProcessor.java:121) at net.sourceforge.pmd.SourceCodeProcessor.processSource(SourceCodeProcessor.java:185) at net.sourceforge.pmd.SourceCodeProcessor.processSourceCodeWithoutCache(SourceCodeProcessor.java:107) ... 10 more * rule: LoosePackageCoupling err: No packages or classes specified * errors: 2 * warnings: 2
textpad
TextPad integration.
Example:
/home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/RuleContext.java(124, GuardLogStatement): Logger calls should be surrounded by log level guards.
/home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/benchmark/Benchmarker.java(58, ForLoopCanBeForeach): This for loop can be replaced by a foreach loop
vbhtml
Vladimir Bossicard HTML format.
xml
XML format.
This format is a XML document, that can be validated by a XSD schema. The schema is report_2_0_0.xsd.
Example:
<?xml version="1.0" encoding="UTF-8"?>
<pmd xmlns="http://pmd.sourceforge.net/report/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/report/2.0.0 https://pmd.github.io/schema/report_2_0_0.xsd"
version="6.22.0" timestamp="2020-04-11T19:17:03.207">
<file name="/home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/RuleContext.java">
<violation beginline="124" endline="125" begincolumn="9" endcolumn="111" rule="GuardLogStatement" ruleset="Best Practices" package="net.sourceforge.pmd" class="RuleContext" method="setSourceCodeFilename" externalInfoUrl="https://pmd.github.io/pmd-6.22.0/pmd_rules_java_bestpractices.html#guardlogstatement" priority="2">
Logger calls should be surrounded by log level guards.
</violation>
</file>
<file name="/home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/benchmark/Benchmarker.java">
<violation beginline="58" endline="62" begincolumn="9" endcolumn="9" rule="ForLoopCanBeForeach" ruleset="Best Practices" package="net.sourceforge.pmd.benchmark" class="Benchmarker" method="findBooleanSwitch" externalInfoUrl="https://pmd.github.io/pmd-6.22.0/pmd_rules_java_bestpractices.html#forloopcanbeforeach" priority="3">
This for loop can be replaced by a foreach loop
</violation>
</file>
<error filename="/home/pmd/source/pmd-core/src/test/resources/net/sourceforge/pmd/cpd/files/file_with_ISO-8859-1_encoding.java" msg="PMDException: Error while parsing /home/pmd/source/pmd-core/src/test/resources/net/sourceforge/pmd/cpd/files/file_with_ISO-8859-1_encoding.java">
<![CDATA[net.sourceforge.pmd.PMDException: Error while parsing /home/pmd/source/pmd-core/src/test/resources/net/sourceforge/pmd/cpd/files/file_with_ISO-8859-1_encoding.java
at net.sourceforge.pmd.SourceCodeProcessor.processSourceCodeWithoutCache(SourceCodeProcessor.java:110)
at net.sourceforge.pmd.SourceCodeProcessor.processSourceCode(SourceCodeProcessor.java:89)
at net.sourceforge.pmd.SourceCodeProcessor.processSourceCode(SourceCodeProcessor.java:51)
at net.sourceforge.pmd.processor.PmdRunnable.call(PmdRunnable.java:78)
at net.sourceforge.pmd.processor.PmdRunnable.call(PmdRunnable.java:24)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
at java.base/java.lang.Thread.run(Thread.java:832)
Caused by: net.sourceforge.pmd.lang.java.ast.ParseException: Encountered " "-" "- "" at line 6, column 30.
Was expecting one of:
"extends" ...
"implements" ...
"{" ...
"<" ...
at net.sourceforge.pmd.lang.java.ast.JavaParser.generateParseException(JavaParser.java:12713)
at net.sourceforge.pmd.lang.java.ast.JavaParser.jj_consume_token(JavaParser.java:12597)
at net.sourceforge.pmd.lang.java.ast.JavaParser.ClassOrInterfaceBody(JavaParser.java:1554)
at net.sourceforge.pmd.lang.java.ast.JavaParser.ClassOrInterfaceDeclaration(JavaParser.java:732)
at net.sourceforge.pmd.lang.java.ast.JavaParser.TypeDeclaration(JavaParser.java:639)
at net.sourceforge.pmd.lang.java.ast.JavaParser.CompilationUnit(JavaParser.java:373)
at net.sourceforge.pmd.lang.java.AbstractJavaParser.parse(AbstractJavaParser.java:62)
at net.sourceforge.pmd.SourceCodeProcessor.parse(SourceCodeProcessor.java:121)
at net.sourceforge.pmd.SourceCodeProcessor.processSource(SourceCodeProcessor.java:185)
at net.sourceforge.pmd.SourceCodeProcessor.processSourceCodeWithoutCache(SourceCodeProcessor.java:107)
... 10 more
]]>
</error>
<suppressedviolation filename="/home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java" suppressiontype="@suppresswarnings" msg="Ensure that resources like this OutputStreamWriter object are closed after use" usermsg=""/>
<configerror rule="LoosePackageCoupling" msg="No packages or classes specified"/>
</pmd>
Properties:
- encoding: XML encoding format, defaults to UTF-8.
xslt
XML with a XSL transformation applied.
PMD provides one built-in stylesheet, that is used by default, if no other stylesheet with the property “xsltFilename” is specified. It is called pmd-nicerhtml.xsl and can be used for customization.
There are many other stylesheets available online: https://github.com/pmd/pmd/tree/master/pmd-core/etc/xslt.
Examples:
- Example with pmd-nicerhtml.xsl
- Example with html-report-v2.xslt - includes charts. It requires javascript enabled and uses jQuery, DataTables, and Vega for charting.
Properties:
- encoding: XML encoding format, defaults to UTF-8.
- xsltFilename: The XSLT file name.
yahtml
Yet Another HTML format.
This renderer creates an html file per analyzed source file, hence you need to specify a output directory. The output directory must exist. If not specified, the html files are created in the current directory.
Properties:
- outputDir: Output directory.