64
docs/pages/pmd/userdocs/tools/gradle.md
Normal file
64
docs/pages/pmd/userdocs/tools/gradle.md
Normal file
@ -0,0 +1,64 @@
|
||||
---
|
||||
title: Gradle
|
||||
tags: [userdocs, tools]
|
||||
permalink: pmd_userdocs_tools_gradle.html
|
||||
---
|
||||
|
||||
The [Gradle Build Tool](https://gradle.org/) provides a [PMD Plugin](https://docs.gradle.org/current/userguide/pmd_plugin.html)
|
||||
that can be added to your build configuration. Technically it is based on the [Ant Task](pmd_userdocs_tools_ant.html).
|
||||
|
||||
## Example
|
||||
|
||||
In your `build.gradle` add the following:
|
||||
|
||||
```
|
||||
plugins {
|
||||
id 'pmd'
|
||||
}
|
||||
```
|
||||
|
||||
### Custom ruleset
|
||||
|
||||
Configuration of a custom ruleset looks like this:
|
||||
|
||||
```
|
||||
pmd {
|
||||
ruleSetFiles = files("custom-pmd-ruleset.xml")
|
||||
ruleSets = []
|
||||
}
|
||||
```
|
||||
|
||||
Note: The `ruleSets` array is explicitly set to empty to avoid using the default configuration.
|
||||
|
||||
### Fail the build
|
||||
|
||||
If you want to fail the build for pmd violations, you need to set `ignoreFailures`:
|
||||
|
||||
```
|
||||
pmd {
|
||||
ignoreFailures = false
|
||||
}
|
||||
```
|
||||
|
||||
More configuration options are documented on [PMD Extension](https://docs.gradle.org/current/dsl/org.gradle.api.plugins.quality.PmdExtension.html).
|
||||
|
||||
### Upgrade PMD version
|
||||
|
||||
If you want to use a newer PMD version than the default one provided with gradle, you can do so
|
||||
with the property `toolVersion`:
|
||||
|
||||
```
|
||||
pmd {
|
||||
toolVersion = "6.21.0"
|
||||
}
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
Source code for Gradles PMD Plugin is available here:
|
||||
|
||||
* [gradle/gradle code-quality](https://github.com/gradle/gradle/tree/master/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality)
|
||||
* [Pmd.java](https://github.com/gradle/gradle/blob/master/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/Pmd.java)
|
||||
* [PmdExtension.java](https://github.com/gradle/gradle/blob/master/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/PmdExtension.java)
|
||||
* [PmdPlugin.java](https://github.com/gradle/gradle/blob/master/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/PmdPlugin.java)
|
||||
* The default PMD version used by gradle: [DEFAULT_PMD_VERSION](https://github.com/gradle/gradle/blob/62297596035d0ed59304bf458eb89bb9859bb3e3/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/PmdPlugin.java#L51)
|
283
docs/pages/pmd/userdocs/tools/java-api.md
Normal file
283
docs/pages/pmd/userdocs/tools/java-api.md
Normal file
@ -0,0 +1,283 @@
|
||||
---
|
||||
title: PMD Java API
|
||||
tags: [userdocs, tools]
|
||||
permalink: pmd_userdocs_tools_java_api.html
|
||||
---
|
||||
|
||||
The easiest way to run PMD is to just use a build plugin in your favorite build tool
|
||||
like [Apache Ant](pmd_userdocs_tools_ant.html), [Apache Maven](pmd_userdocs_tools_maven.html) or
|
||||
[Gradle](pmd_userdocs_tools_gradle.html).
|
||||
|
||||
There are also many integrations for IDEs available, see [Tools](pmd_userdocs_tools.html).
|
||||
|
||||
If you have your own build tool or want to integrate PMD in a different way, you can call PMD programmatically,
|
||||
as described here.
|
||||
|
||||
## Dependencies
|
||||
|
||||
You'll need to add the dependency to the language, you want to analyze. For Java, it will be
|
||||
`net.sourceforge.pmd:pmd-java`. If you use Maven, you can add a new (compile time) dependency like this:
|
||||
|
||||
``` xml
|
||||
<dependency>
|
||||
<groupId>net.sourceforge.pmd</groupId>
|
||||
<artifactId>pmd-java</artifactId>
|
||||
<version>${pmdVersion}</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
Note: You'll need to select a specific version. This is done in the example via the property `pmdVersion`.
|
||||
|
||||
This will transitively pull in the artifact `pmd-core` which contains the API.
|
||||
|
||||
## Command line interface
|
||||
|
||||
The easiest way is to call PMD with the same interface as from command line. The main class is
|
||||
`net.sourceforge.pmd.PMD`:
|
||||
|
||||
``` java
|
||||
import net.sourceforge.pmd.PMD;
|
||||
|
||||
public class Example {
|
||||
public static void main(String[] args) {
|
||||
String[] pmdArgs = {
|
||||
"-d", "/home/workspace/src/main/java/code",
|
||||
"-R", "rulesets/java/quickstart.xml",
|
||||
"-f", "xml",
|
||||
"-r", "/home/workspace/pmd-report.xml"
|
||||
};
|
||||
PMD.main(pmdArgs);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
It uses the same options as described in [PMD CLI reference](pmd_userdocs_cli_reference.html).
|
||||
|
||||
## Programmatically, variant 1
|
||||
|
||||
This is very similar:
|
||||
|
||||
``` java
|
||||
import net.sourceforge.pmd.PMD;
|
||||
import net.sourceforge.pmd.PMDConfiguration;
|
||||
|
||||
public class PmdExample {
|
||||
|
||||
public static void main(String[] args) {
|
||||
PMDConfiguration configuration = new PMDConfiguration();
|
||||
configuration.setInputPaths("/home/workspace/src/main/java/code");
|
||||
configuration.setRuleSets("rulesets/java/quickstart.xml");
|
||||
configuration.setReportFormat("xml");
|
||||
configuration.setReportFile("/home/workspace/pmd-report.xml");
|
||||
|
||||
PMD.doPMD(configuration);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Programmatically, variant 2
|
||||
|
||||
This gives you more control over which files are processed, but is also more complicated.
|
||||
You can also provide your own listeners and renderers.
|
||||
|
||||
1. First we create a `PMDConfiguration`. This is currently the only way to specify a ruleset:
|
||||
|
||||
```java
|
||||
PMDConfiguration configuration = new PMDConfiguration();
|
||||
configuration.setMinimumPriority(RulePriority.MEDIUM);
|
||||
configuration.setRuleSets("rulesets/java/quickstart.xml");
|
||||
```
|
||||
|
||||
2. In order to support type resolution, PMD needs to have access to the compiled classes and dependencies
|
||||
as well. This is called "auxclasspath" and is also configured here.
|
||||
Note: you can specify multiple class paths separated by `:` on Unix-systems or `;` under Windows.
|
||||
|
||||
```java
|
||||
configuration.prependClasspath("/home/workspace/target/classes:/home/.m2/repository/my/dependency.jar");
|
||||
```
|
||||
|
||||
3. Then we need a ruleset factory. This is created using the configuration, taking the minimum priority into
|
||||
account:
|
||||
|
||||
```java
|
||||
RuleSetFactory ruleSetFactory = RulesetsFactoryUtils.createFactory(configuration);
|
||||
```
|
||||
|
||||
4. PMD operates on a list of `DataSource`. You can assemble a own list of `FileDataSource`, e.g.
|
||||
|
||||
```java
|
||||
List<DataSource> files = Arrays.asList(new FileDataSource(new File("/path/to/src/MyClass.java")));
|
||||
```
|
||||
|
||||
5. For reporting, you can use a built-in renderer, e.g. `XMLRenderer`. Note, that you must manually initialize
|
||||
the renderer by setting a suitable `Writer` and calling `start()`. After the PMD run, you need to call
|
||||
`end()` and `flush()`. Then your writer should have received all output.
|
||||
|
||||
```java
|
||||
StringWriter rendererOutput = new StringWriter();
|
||||
Renderer xmlRenderer = new XMLRenderer("UTF-8");
|
||||
xmlRenderer.setWriter(rendererOutput);
|
||||
xmlRenderer.start();
|
||||
```
|
||||
|
||||
6. Create a `RuleContext`. This is the context instance, that is available then in the rule implementations.
|
||||
Note: when running in multi-threaded mode (which is the default), the rule context instance is cloned for
|
||||
each thread.
|
||||
|
||||
```java
|
||||
RuleContext ctx = new RuleContext();
|
||||
```
|
||||
|
||||
7. Optionally register a report listener. This allows you to react immediately on found violations. You could also
|
||||
use such a listener to implement your own renderer. The listener must implement the interface
|
||||
`ThreadSafeReportListener` and can be registered via `ctx.getReport().addListener(...)`.
|
||||
|
||||
```java
|
||||
ctx.getReport().addListener(new ThreadSafeReportListener() {
|
||||
public void ruleViolationAdded(RuleViolation ruleViolation) {
|
||||
}
|
||||
public void metricAdded(Metric metric) {
|
||||
}
|
||||
```
|
||||
|
||||
8. Now, all the preparations are done, and PMD can be executed. This is done by calling
|
||||
`PMD.processFiles(...)`. This method call takes the configuration, the ruleset factory, the files
|
||||
to process, the rule context and the list of renderers. Provide an empty list, if you don't want to use
|
||||
any renderer. Note: The auxclasspath needs to be closed explicitly. Otherwise the class or jar files may
|
||||
remain open and file resources are leaked.
|
||||
|
||||
```java
|
||||
try {
|
||||
PMD.processFiles(configuration, ruleSetFactory, files, ctx,
|
||||
Collections.singletonList(renderer));
|
||||
} finally {
|
||||
ClassLoader auxiliaryClassLoader = configuration.getClassLoader();
|
||||
if (auxiliaryClassLoader instanceof ClasspathClassLoader) {
|
||||
((ClasspathClassLoader) auxiliaryClassLoader).close();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
9. After the call, you need to finish the renderer via `end()` and `flush()`.
|
||||
Then you can check the rendered output.
|
||||
|
||||
``` java
|
||||
renderer.end();
|
||||
renderer.flush();
|
||||
System.out.println("Rendered Report:");
|
||||
System.out.println(rendererOutput.toString());
|
||||
```
|
||||
|
||||
Here is a complete example:
|
||||
|
||||
``` java
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.FileVisitResult;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.PathMatcher;
|
||||
import java.nio.file.SimpleFileVisitor;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.pmd.PMD;
|
||||
import net.sourceforge.pmd.PMDConfiguration;
|
||||
import net.sourceforge.pmd.RuleContext;
|
||||
import net.sourceforge.pmd.RulePriority;
|
||||
import net.sourceforge.pmd.RuleSetFactory;
|
||||
import net.sourceforge.pmd.RuleViolation;
|
||||
import net.sourceforge.pmd.RulesetsFactoryUtils;
|
||||
import net.sourceforge.pmd.ThreadSafeReportListener;
|
||||
import net.sourceforge.pmd.renderers.Renderer;
|
||||
import net.sourceforge.pmd.renderers.XMLRenderer;
|
||||
import net.sourceforge.pmd.stat.Metric;
|
||||
import net.sourceforge.pmd.util.ClasspathClassLoader;
|
||||
import net.sourceforge.pmd.util.datasource.DataSource;
|
||||
import net.sourceforge.pmd.util.datasource.FileDataSource;
|
||||
|
||||
public class PmdExample2 {
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
PMDConfiguration configuration = new PMDConfiguration();
|
||||
configuration.setMinimumPriority(RulePriority.MEDIUM);
|
||||
configuration.setRuleSets("rulesets/java/quickstart.xml");
|
||||
configuration.prependClasspath("/home/workspace/target/classes");
|
||||
RuleSetFactory ruleSetFactory = RulesetsFactoryUtils.createFactory(configuration);
|
||||
|
||||
List<DataSource> files = determineFiles("/home/workspace/src/main/java/code");
|
||||
|
||||
Writer rendererOutput = new StringWriter();
|
||||
Renderer renderer = createRenderer(rendererOutput);
|
||||
renderer.start();
|
||||
|
||||
RuleContext ctx = new RuleContext();
|
||||
|
||||
ctx.getReport().addListener(createReportListener()); // alternative way to collect violations
|
||||
|
||||
try {
|
||||
PMD.processFiles(configuration, ruleSetFactory, files, ctx,
|
||||
Collections.singletonList(renderer));
|
||||
} finally {
|
||||
ClassLoader auxiliaryClassLoader = configuration.getClassLoader();
|
||||
if (auxiliaryClassLoader instanceof ClasspathClassLoader) {
|
||||
((ClasspathClassLoader) auxiliaryClassLoader).close();
|
||||
}
|
||||
}
|
||||
|
||||
renderer.end();
|
||||
renderer.flush();
|
||||
System.out.println("Rendered Report:");
|
||||
System.out.println(rendererOutput.toString());
|
||||
}
|
||||
|
||||
private static ThreadSafeReportListener createReportListener() {
|
||||
return new ThreadSafeReportListener() {
|
||||
@Override
|
||||
public void ruleViolationAdded(RuleViolation ruleViolation) {
|
||||
System.out.printf("%-20s:%d %s%n", ruleViolation.getFilename(),
|
||||
ruleViolation.getBeginLine(), ruleViolation.getDescription());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void metricAdded(Metric metric) {
|
||||
// ignored
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static Renderer createRenderer(Writer writer) {
|
||||
XMLRenderer xml = new XMLRenderer("UTF-8");
|
||||
xml.setWriter(writer);
|
||||
return xml;
|
||||
}
|
||||
|
||||
private static List<DataSource> determineFiles(String basePath) throws IOException {
|
||||
Path dirPath = FileSystems.getDefault().getPath(basePath);
|
||||
PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:*.java");
|
||||
|
||||
List<DataSource> files = new ArrayList<>();
|
||||
|
||||
Files.walkFileTree(dirPath, new SimpleFileVisitor<Path>() {
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) throws IOException {
|
||||
if (matcher.matches(path.getFileName())) {
|
||||
System.out.printf("Using %s%n", path);
|
||||
files.add(new FileDataSource(path.toFile()));
|
||||
} else {
|
||||
System.out.printf("Ignoring %s%n", path);
|
||||
}
|
||||
return super.visitFile(path, attrs);
|
||||
}
|
||||
});
|
||||
System.out.printf("Analyzing %d files in %s%n", files.size(), basePath);
|
||||
return files;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Maven PMD Plugin
|
||||
tags: [userdocs, tools]
|
||||
permalink: /pmd_userdocs_tools_maven.html
|
||||
permalink: pmd_userdocs_tools_maven.html
|
||||
last_updated: August 2017
|
||||
author: >
|
||||
Miguel Griffa <mikkey@users.sourceforge.net>,
|
||||
|
Reference in New Issue
Block a user