Merge branch 'master' into junit-rule-pmd-test-runner

This commit is contained in:
Andreas Dangel
2017-09-11 22:04:55 +02:00
93 changed files with 3646 additions and 356 deletions

View File

@ -6,8 +6,8 @@ GEM
minitest (~> 5.1)
thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1)
addressable (2.5.1)
public_suffix (~> 2.0, >= 2.0.2)
addressable (2.5.2)
public_suffix (>= 2.0.2, < 4.0)
coffee-script (2.4.1)
coffee-script-source
execjs
@ -16,21 +16,21 @@ GEM
ethon (0.10.1)
ffi (>= 1.3.0)
execjs (2.7.0)
faraday (0.13.0)
faraday (0.13.1)
multipart-post (>= 1.2, < 3)
ffi (1.9.18)
forwardable-extended (2.6.0)
gemoji (3.0.0)
github-pages (151)
github-pages (158)
activesupport (= 4.2.8)
github-pages-health-check (= 1.3.5)
jekyll (= 3.5.1)
jekyll (= 3.5.2)
jekyll-avatar (= 0.4.2)
jekyll-coffeescript (= 1.0.1)
jekyll-default-layout (= 0.1.4)
jekyll-feed (= 0.9.2)
jekyll-gist (= 1.4.1)
jekyll-github-metadata (= 2.6.0)
jekyll-github-metadata (= 2.9.1)
jekyll-mentions (= 1.2.0)
jekyll-optional-front-matter (= 0.2.0)
jekyll-paginate (= 1.1.0)
@ -38,7 +38,7 @@ GEM
jekyll-redirect-from (= 0.12.1)
jekyll-relative-links (= 0.4.1)
jekyll-sass-converter (= 1.5.0)
jekyll-seo-tag (= 2.2.3)
jekyll-seo-tag (= 2.3.0)
jekyll-sitemap (= 1.0.0)
jekyll-swiss (= 0.4.0)
jekyll-theme-architect (= 0.1.0)
@ -50,7 +50,7 @@ GEM
jekyll-theme-midnight (= 0.1.0)
jekyll-theme-minimal (= 0.1.0)
jekyll-theme-modernist (= 0.1.0)
jekyll-theme-primer (= 0.4.0)
jekyll-theme-primer (= 0.5.2)
jekyll-theme-slate (= 0.1.0)
jekyll-theme-tactile (= 0.1.0)
jekyll-theme-time-machine (= 0.1.0)
@ -69,11 +69,11 @@ GEM
octokit (~> 4.0)
public_suffix (~> 2.0)
typhoeus (~> 0.7)
html-pipeline (2.6.0)
html-pipeline (2.7.0)
activesupport (>= 2)
nokogiri (>= 1.4)
i18n (0.8.6)
jekyll (3.5.1)
jekyll (3.5.2)
addressable (~> 2.4)
colorator (~> 1.0)
jekyll-sass-converter (~> 1.0)
@ -94,7 +94,7 @@ GEM
jekyll (~> 3.3)
jekyll-gist (1.4.1)
octokit (~> 4.2)
jekyll-github-metadata (2.6.0)
jekyll-github-metadata (2.9.1)
jekyll (~> 3.1)
octokit (~> 4.0, != 4.4.0)
jekyll-mentions (1.2.0)
@ -112,7 +112,7 @@ GEM
jekyll (~> 3.3)
jekyll-sass-converter (1.5.0)
sass (~> 3.4)
jekyll-seo-tag (2.2.3)
jekyll-seo-tag (2.3.0)
jekyll (~> 3.3)
jekyll-sitemap (1.0.0)
jekyll (~> 3.3)
@ -144,8 +144,9 @@ GEM
jekyll-theme-modernist (0.1.0)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-primer (0.4.0)
jekyll-theme-primer (0.5.2)
jekyll (~> 3.5)
jekyll-github-metadata (~> 2.9)
jekyll-seo-tag (~> 2.2)
jekyll-theme-slate (0.1.0)
jekyll (~> 3.5)
@ -214,4 +215,4 @@ DEPENDENCIES
jekyll
BUNDLED WITH
1.13.6
1.15.1

View File

@ -7,15 +7,16 @@ This site was built using the tomjohnson1492/documentation-theme-jekyll theme
A Jekyll-based theme designed for documentation and help systems. See the link for detailed instructions on setting up and configuring everything. http://idratherbewriting.com/documentation-theme-jekyll/
## Building using Bundler
Build the site to see the instructions for using it. Or just go here: [http://idratherbewriting.com/documentation-theme-jekyll/](http://idratherbewriting.com/documentation-theme-jekyll/)
Run `bundle exec jekyll serve --watch` to fire up Jekyll on local machine
## Using Docker
One time: `docker build --no-cache -t mydocs .`
Now run the site with `docker run --rm=true -v "$PWD:/src" -p 4005:4005 mydocs serve -H 0.0.0.0`
bundle install # once
bundle exec jekyll serve
Go to: http://localhost:4005/
## Building using Docker
docker build --no-cache -t pmd-doc . # once
docker run --rm=true -v "$PWD:/src" -p 4005:4005 pmd-doc serve -H 0.0.0.0
Go to: http://localhost:4005/

View File

@ -2,6 +2,7 @@ repository: pmd/pmd
pmd:
version: 6.0.0
date: to-be-defined
output: web
# this property is useful for conditional filtering of content that is separate from the PDF.

View File

@ -45,9 +45,20 @@ entries:
- title: Suppressing
url: /pmd_userdocs_suppressing.html
output: web, pdf
- title: Tools / Integrations
url: /pmd_userdocs_tools.html
output: web, pdf
subfolders:
- title: Tools / Integrations
output: web, pdf
subfolderitems:
- title: Maven PMD Plugin
output: web, pdf
url: /pmd_userdocs_tools_maven.html
- title: Ant
output: web, pdf
url: /pmd_userdocs_tools_ant.html
- title: Other Tools / Integrations
output: web, pdf
url: /pmd_userdocs_tools.html
- title: FAQ
url: /pmd_userdocs_faq.html
output: web, pdf
@ -123,6 +134,12 @@ entries:
- title: Developer Documentation
output: web, pdf
folderitems:
- title: Developer Resources
url: /pmd_devdocs_development.html
output: web, pdf
- title: Writing Documentation
url: /pmd_devdocs_writing_documentation.html
output: web, pdf
- title: Code Style
url: /pmd_devdocs_codestyle.html
output: web, pdf

View File

@ -6,7 +6,11 @@
{% for folder in entry.folders %}
{% if folder.output contains "web" %}
<li>
{% if folder.url %}
<a href="{{ folder.url | remove: "/" }}">{{ folder.title }}</a>
{% else %}
<a href="#">{{ folder.title }}</a>
{% endif %}
<ul>
{% for folderitem in folder.folderitems %}
{% if folderitem.output contains "web" %}

View File

@ -2,38 +2,97 @@
title: PMD Introduction
keywords: java
tags: [getting_started]
sidebar: pmd_sidebar
permalink: index.html
summary: Welcome to PMD, an extensible cross-language static code analyzer.
toc: false
summary: >
Welcome to PMD, an extensible cross-language static code analyzer.
It finds common programming flaws like unused variables, empty catch blocks, unnecessary object creation,
and so forth. Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code.
last_updated: August 2017
author: Jeff Jensen <jjensen@apache.org>, Andreas Dangel <andreas.dangel@adangel.org>
---
{% include image.html file="pmd-logo-big.png" alt="PMD Logo" %}
# Welcome to PMD
<br>
PMD scans source code in Java and other languages and looks for potential problems like:
**PMD** scans source code in Java and other languages and looks for potential problems like:
* Possible bugs - empty try/catch/finally/switch statements
* Dead code - unused local variables, parameters and private methods
* Suboptimal code - wasteful String/StringBuffer usage
* Overcomplicated expressions - unnecessary if statements, for loops that could be while loops
* Duplicate code - copied/pasted code means copied/pasted bugs
## Download
**CPD**, the copy-paste-detector, finds duplicated code in many languages:
You can [download everything from here](https://github.com/pmd/pmd/releases).
* Duplicate code is often just copied and pasted. This means, the bugs are also copied and pasted. Fixing
them means, fix all duplicated code locations.
You can get an overview of all the rules for e.g. Java at the [rulesets index](pmd_rules_java.html) page.
## Features
PMD is [integrated](pmd_userdocs_tools.html) with JDeveloper, Eclipse, JEdit, JBuilder, BlueJ, CodeGuide, NetBeans/Sun Java Studio Enterprise/Creator, IntelliJ IDEA, TextPad, Maven, Ant, Gel, JCreator, and Emacs.
{::options parse_block_html="true" /}
<div class="row"><div class="col-lg-6">
### PMD
Features:
* Supporting 8 languages
* Many ready-to-use built-in rules.
* Custom rules can be written in Java
* Custom rules can be written using XPath expression that query the AST of the sources
* Many output formats
* Many integrations into IDEs, build tools
Supported Languages:
* [Java](pmd_rules_java.html)
* [JavaScript](pmd_rules_ecmascript.html)
* [Salesforce.com Apex](pmd_rules_apex.html) and [Visualforce](pmd_rules_vf.html)
* [PLSQL](pmd_rules_plsql.html)
* [Apache Velocity](pmd_rules_vm.html)
* [XML](pmd_rules_xml.html) and [Maven POM](pmd_rules_pom.html)
* [XSL](pmd_rules_xsl.html)
</div><div class="col-lg-6">
### CPD
Features:
* Supporting 19 languages
* Simple GUI
* Fast
* Many integrations
Supported Languages:
* Java
* C, C++
* C#
* Groovy
* PHP
* Ruby
* Fortran
* JavaScript
* PLSQL
* Apache Velocity
* Scala
* Objective C
* Matlab
* Python
* Go
* Swift
* Salesforce.com Apex and Visualforce
</div></div>
## Download PMD {{ site.pmd.version }}
Latest Version: {{ site.pmd.version }} ({{ site.pmd.date }})
* [Release Notes](pmd_release_notes.html)
* [Download](https://github.com/pmd/pmd/releases)
## Future Releases
The next version of PMD will be developed in parallel with this release. We will release additional bugfix versions as needed.
A [snapshot](http://pmd.sourceforge.net/snapshot) of the web site for the new version is generated daily by our continuous integration server.
Maven packages are also generated regularly and uploaded to [Sonatypes OSS snapshot repository](https://oss.sonatype.org/content/repositories/snapshots/net/sourceforge/pmd/pmd/).
{% include links.html %}

View File

@ -2,13 +2,12 @@
title: Adding support for metrics to a language
short_title: Implement a metrics framework
tags: [customizing]
summary: "PMD's Java module has an extensive framework for the calculation of metrics, which allows rule developers
to implement and use new code metrics very simply. Most of the functionality of this framework is abstracted in such
summary: "PMD's Java module has an extensive framework for the calculation of metrics, which allows rule developers
to implement and use new code metrics very simply. Most of the functionality of this framework is abstracted in such
a way that any PMD supported language can implement such a framework without too much trouble. Here's how."
last_updated: August 2017
sidebar: pmd_sidebar
permalink: pmd_devdocs_adding_metrics_support_to_language.html
folder: pmd/devdocs
author: Clément Fournier <clement.fournier76@gmail.com>
---
{% include warning.html content="WIP, unstable API" %}
@ -18,100 +17,100 @@ folder: pmd/devdocs
### Overview of the Java framework
The framework has several subsystems, the two most easily identifiable being:
* A **project memoizer** (`ProjectMemoizer`). When a metric is computed, it's stored back in this structure and can be
reused later. This
reduces the overhead on the calculation of e.g. aggregate results (`ResultOption` calculations). The contents of
this data structure are indexed with fully qualified names (`JavaQualifiedName`), which must identify unambiguously
* A **project memoizer** (`ProjectMemoizer`). When a metric is computed, it's stored back in this structure and can be
reused later. This
reduces the overhead on the calculation of e.g. aggregate results (`ResultOption` calculations). The contents of
this data structure are indexed with fully qualified names (`JavaQualifiedName`), which must identify unambiguously
classes and methods.
* The **façade**. The static end-user façade (`JavaMetrics`) is backed by an instance of a `JavaMetricsFaçade`. This
allows us to abstract the functionality of the façade into `pmd-core` for other frameworks to use. The façade
instance contains a project memoizer for the analysed project, and a metrics computer
(`JavaMetricsComputer`). It's this last object which really computes the metric and stores back its result in the
* The **façade**. The static end-user façade (`JavaMetrics`) is backed by an instance of a `JavaMetricsFaçade`. This
allows us to abstract the functionality of the façade into `pmd-core` for other frameworks to use. The façade
instance contains a project memoizer for the analysed project, and a metrics computer
(`JavaMetricsComputer`). It's this last object which really computes the metric and stores back its result in the
project mirror, while the façade only handles parameters.
Metrics (`Metric<N>`) plug in to this static system and only provide behaviour that's executed by the metrics computer.
Internally, metric keys (`MetricKey<N>`) are parameterized with their version (`MetricVersion`) to index memoisation
maps (see `ParameterizedMetricKey<N>`). This allows us to memoise several versions of the same metric without conflict.
Metrics (`Metric<N>`) plug in to this static system and only provide behaviour that's executed by the metrics computer.
Internally, metric keys (`MetricKey<N>`) are parameterized with their version (`MetricVersion`) to index memoisation
maps (see `ParameterizedMetricKey<N>`). This allows us to memoise several versions of the same metric without conflict.
{% include important.html content="The following will be moved when multifile analysis and metrics are separated" %}
<!-- We should probably create a dedicated page about the architecture of multifile analysis/ signature matching and how
to implement that -->
At the very least, a metrics framework has those two components and is just a convenient way to compute and memoize
metrics on a single file. Yet, one of the goals of the metrics framework is to allow for **multi-file analysis**, which
make it possible, for instance, to compute the coupling between two classes. This feature uses two major
At the very least, a metrics framework has those two components and is just a convenient way to compute and memoize
metrics on a single file. Yet, one of the goals of the metrics framework is to allow for **multi-file analysis**, which
make it possible, for instance, to compute the coupling between two classes. This feature uses two major
components:
* A **project mirror**. This data structure that stores info about all classes and operations (and other relevant
* A **project mirror**. This data structure that stores info about all classes and operations (and other relevant
entities, such as fields, packages, etc.) of the analysed project. This is implemented by `PackageStats` in the Java
framework. The role of this structure is to make info about other files available to rules. It's filled by a visitor before rules apply.
The information stored in this data structure that's accessible to metrics is mainly comprised of method and field
signatures (e.g. `JavaOperationSignature`), which describes concisely the characteristics of the method or field
The information stored in this data structure that's accessible to metrics is mainly comprised of method and field
signatures (e.g. `JavaOperationSignature`), which describes concisely the characteristics of the method or field
(roughly, its modifiers).
* Some kind of method and field **usage resolution**, i.e. some way to find the fully qualified name of a method from a
* Some kind of method and field **usage resolution**, i.e. some way to find the fully qualified name of a method from a
method call expression node. This is the trickiest part to implement. In Java it depends on type resolution.
### Abstraction layer
As you may have seen, most of the functionality of the first two components are abstracted into `pmd-core`. This
allows us to implement new metrics frameworks quite quickly. These abstract components are parameterized by the
node types of the class and operation AST nodes. Moreover, it makes the external behaviour of the framework is very
As you may have seen, most of the functionality of the first two components are abstracted into `pmd-core`. This
allows us to implement new metrics frameworks quite quickly. These abstract components are parameterized by the
node types of the class and operation AST nodes. Moreover, it makes the external behaviour of the framework is very
stable across languages, yet each component can easily be customized by adding methods or overriding existing ones.
The signature matching aspect is framed by generic interfaces, but it can't really be abstracted more
The signature matching aspect is framed by generic interfaces, but it can't really be abstracted more
than that. For instance, the project mirror is very language specific. Java's implementation uses the natural structure
provided by the language's package system to structure the project's content. Apex, on the other, has no package
system and thus can't use the same mechanism. That explains why the interfaces framing the project mirror are very
provided by the language's package system to structure the project's content. Apex, on the other, has no package
system and thus can't use the same mechanism. That explains why the interfaces framing the project mirror are very
loose. Their main goal is to provide type safety through generics.
Moreover, usage resolution depends on the availability of type resolution for the given language, which is only implemented in
Java. For these reasons, signature matching is considered an optional feature of the metrics framework. But despite
this limitation, signature matching still provides a elegant way to find information about the class we're in. This
feature requires no usage resolution and can be used to implement sophisticated metrics, that already give access to
Moreover, usage resolution depends on the availability of type resolution for the given language, which is only implemented in
Java. For these reasons, signature matching is considered an optional feature of the metrics framework. But despite
this limitation, signature matching still provides a elegant way to find information about the class we're in. This
feature requires no usage resolution and can be used to implement sophisticated metrics, that already give access to
detection strategies.
## Implementation of a new framework
### 1. Groundwork
* Create a class implementing `QualifiedName`. This implementation must be tailored to the target language so
that it can indentify unambiguously any class and operation in the analysed project. You
* Create a class implementing `QualifiedName`. This implementation must be tailored to the target language so
that it can indentify unambiguously any class and operation in the analysed project. You
must implement `equals`, `hashCode` and `toString`.
[Example](https://github.com/pmd/pmd/blob/52d78d2fa97913cf73814d0307a1c1ae6125a437/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaQualifiedName.java)
* Determine the AST nodes that correspond to class and method declaration in your language. These types are
referred hereafter as `T` and `O`, respectively. Both these types must implement the interface `QualifiableNode`,
* Determine the AST nodes that correspond to class and method declaration in your language. These types are
referred hereafter as `T` and `O`, respectively. Both these types must implement the interface `QualifiableNode`,
which means they must expose a `getQualifiedName` method to give access to their qualified name.
### 2. Implement and wire the project memoizer
* Create a class extending `BasicProjectMemoizer<T, O>`. There's no abstract functionality to implement.
[Example](https://github.com/pmd/pmd/blob/52d78d2fa97913cf73814d0307a1c1ae6125a437/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaProjectMemoizer.java)
* Create an AST visitor that fills the project memoizer with memoizers. For that, you use `BasicProjectMemoizer`'s
`addClassMemoizer` and `addOperationMemoizer` methods with a qualified name.
* Create an AST visitor that fills the project memoizer with memoizers. For that, you use `BasicProjectMemoizer`'s
`addClassMemoizer` and `addOperationMemoizer` methods with a qualified name.
[Example](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaMetricsVisitor.java)
* Create a façade class for your visitor. This class extends a `*ParserVisitorAdapter` class and only overrides the
`initializeWith(Node)` method. It's supposed to make your real visitor accept the node in parameter.
* Create a façade class for your visitor. This class extends a `*ParserVisitorAdapter` class and only overrides the
`initializeWith(Node)` method. It's supposed to make your real visitor accept the node in parameter.
[Example](https://github.com/pmd/pmd/blob/52d78d2fa97913cf73814d0307a1c1ae6125a437/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaMetricsVisitorFacade.java)
* Override the `getMetricsVisitorFacade()` method in your language's handler (e.g. `ApexHandler`). This method gives
back a `VisitorStarter` which initializes your façade with a `Node`.
* Override the `getMetricsVisitorFacade()` method in your language's handler (e.g. `ApexHandler`). This method gives
back a `VisitorStarter` which initializes your façade with a `Node`.
[Example](https://github.com/pmd/pmd/blob/52d78d2fa97913cf73814d0307a1c1ae6125a437/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/AbstractJavaHandler.java#L100-L108)
* Your project memoizer should now get filled when the `metrics` attribute is set to `true` in the rule XML.
### 3. Implement the façade
* Create a class extending `AbstractMetricsComputer<T, O>`. This object will be responsible for calculating metrics
given a memoizer, a node and info about the metric. Typically, this object is stateless so you might as well make it
* Create a class extending `AbstractMetricsComputer<T, O>`. This object will be responsible for calculating metrics
given a memoizer, a node and info about the metric. Typically, this object is stateless so you might as well make it
a singleton.
[Example](https://github.com/pmd/pmd/blob/52d78d2fa97913cf73814d0307a1c1ae6125a437/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaMetricsComputer.java)
* Create a class extending `AbstractMetricsFacade<T, O>`. This class needs a reference to your `ProjectMemoizer` and
your `MetricsComputer`. It backs the real end user façade, and handles user provided parameters before delegating to
* Create a class extending `AbstractMetricsFacade<T, O>`. This class needs a reference to your `ProjectMemoizer` and
your `MetricsComputer`. It backs the real end user façade, and handles user provided parameters before delegating to
your `MetricsComputer`.
[Example](https://github.com/pmd/pmd/blob/52d78d2fa97913cf73814d0307a1c1ae6125a437/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaMetricsFacade.java)
* Create the static façade of your framework. This one has an instance of your `MetricsFaçade` object and delegates
* Create the static façade of your framework. This one has an instance of your `MetricsFaçade` object and delegates
static methods to that instance.
[Example](https://github.com/pmd/pmd/blob/52d78d2fa97913cf73814d0307a1c1ae6125a437/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaMetrics.java)
* Create classes `AbstractOperationMetric` and `AbstractClassMetric`. These must implement `Metric<T>` and
`Metric<O>`, respectively. They typically provide defaults for the `supports` method of each metric.
* Create classes `AbstractOperationMetric` and `AbstractClassMetric`. These must implement `Metric<T>` and
`Metric<O>`, respectively. They typically provide defaults for the `supports` method of each metric.
[Example](https://github.com/pmd/pmd/blob/52d78d2fa97913cf73814d0307a1c1ae6125a437/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/AbstractJavaOperationMetric.java)
* Create enums `ClassMetricKey` and `OperationMetricKey`. These must implement `MetricKey<T>` and `MetricKey<O>`. The
enums list all available metric keys for your language.
@ -122,21 +121,20 @@ detection strategies.
{% include important.html content="The following section will be moved when multifile analysis and metrics are separated" %}
### Optional: Signature matching
You can match the signature of anything: method, field, class, package... It depends on what's useful for you.
Suppose you want to be able to match signatures for nodes of type `N`. What you have to do then is the following:
* Create a class implementing the interface `Signature<N>`. Signatures describe basic information about the node,
which typically includes most of the modifiers they declare (eg visibility, abstract or virtual, etc.).
You can match the signature of anything: method, field, class, package... It depends on what's useful for you.
Suppose you want to be able to match signatures for nodes of type `N`. What you have to do then is the following:
* Create a class implementing the interface `Signature<N>`. Signatures describe basic information about the node,
which typically includes most of the modifiers they declare (eg visibility, abstract or virtual, etc.).
It's up to you to define the right level of detail, depending on the accuracy of the pattern matching required.
* Make type `N` implement `SignedNode<N>`. This makes the node capable of giving its signature. Factory methods to
* Make type `N` implement `SignedNode<N>`. This makes the node capable of giving its signature. Factory methods to
build a `Signature<N>` from a `N` are a good idea.
* Create signature masks. A mask is an object that matches some signatures based on their features. For example, with
the Java framework, you can build a `JavaOperationSigMask` that matches all method signatures with visibility
the Java framework, you can build a `JavaOperationSigMask` that matches all method signatures with visibility
`public`. A sigmask implements `SigMask<S>`, where `S` is the type of signature your mask handles.
* Typically, the project mirror stores the signatures, so you have to implement it in a way that makes it possible to
associate a signature with the qualified name of its node.
* If you want to implement signature matching, create an `AbstractMetric` class, which gives access to a
`SignatureMatcher` to your metrics. Typically, your implementation of `ProjectMirror` implements a
associate a signature with the qualified name of its node.
* If you want to implement signature matching, create an `AbstractMetric` class, which gives access to a
`SignatureMatcher` to your metrics. Typically, your implementation of `ProjectMirror` implements a
custom `SignatureMatcher` interface, and your façade can give back its instance of the project mirror.

View File

@ -4,9 +4,8 @@ short_title: Add a New CPD Language
tags: [customizing]
summary: How to Add a New CPD Language
last_updated: July 3, 2016
sidebar: pmd_sidebar
permalink: pmd_devdocs_adding_new_cpd_language.html
folder: pmd/devdocs
author: Romain PELISSE <belaran@gmail.com>
---
# How to Add a New Language to CPD

View File

@ -1,8 +1,7 @@
---
title: Building PMD from source
sidebar: pmd_sidebar
permalink: pmd_devdocs_building.html
folder: pmd/devdocs
author: Tom Copeland, Xavier Le Vourch <xlv@users.sourceforge.net>
---
# Compiling PMD

View File

@ -0,0 +1,36 @@
---
title: Developer Resources
permalink: pmd_devdocs_development.html
last_updated: August 2017
---
The next version of PMD will be developed in parallel with this release. We will release additional bugfix versions as needed.
## Source Code
The complete source code can be found on github:
* [github.com/pmd/pmd](https://github.com/pmd/pmd) - main PMD repository. Includes all the code to support all languages, including this documentation.
* [github.com/pmd/pmd.github.io](https://github.com/pmd/pmd.github.io) - Contains the landing page [https://pmd.github.io](https://pmd.github.io)
* [github.com/pmd/build-tools](https://github.com/pmd/build-tools) - Contains the checkstyle rules we use
* [github.com/pmd/pmd-eclipse-plugin](https://github.com/pmd/pmd-eclipse-plugin) - The PMD eclipse plugin
* [github.com/pmd](https://github.com/pmd) - PMD Organization at github. There are a couple of more repositories
## Continuous Integration
We use [Travis CI](https://travis-ci.org/pmd) as our ci service. The main repo and the eclipse plugin are built for
every push. Each pull request is built as well.
The maven snapshot artifacts are deployed at [Sonatypes OSS snapshot repository](https://oss.sonatype.org/content/repositories/snapshots/net/sourceforge/pmd/pmd/).
Ready-to-use binary packages are uploaded to sourceforge at <https://sourceforge.net/projects/pmd/files/pmd/>.
## Documentation and Webpages
A [snapshot](http://pmd.sourceforge.net/snapshot) of the web site for the new version is generated travis-ci as well.
## Contributing
First off, thanks for taking the time to contribute!
Please have a look at [CONTRIBUTING.md](https://github.com/pmd/pmd/blob/master/CONTRIBUTING.md) and
[BUILDING.md](https://github.com/pmd/pmd/blob/master/BUILDING.md).

View File

@ -3,9 +3,8 @@ title: PMD How it Works
tags: [customizing]
summary: How PMD Works
last_updated: July 3, 2016
sidebar: pmd_sidebar
permalink: pmd_devdocs_how_pmd_works.html
folder: pmd/devdocs
author: Tom Copeland
---
# How it works

View File

@ -4,9 +4,8 @@ short_title: Info for Developers
tags: [customizing]
summary: Info for PMD Developers
last_updated: July 3, 2016
sidebar: pmd_sidebar
permalink: pmd_devdocs_info_for_developers.html
folder: pmd/devdocs
author: Hooper Bloob <hooperbloob@users.sourceforge.net>, Romain Pelisse <rpelisse@users.sourceforge.net>
---
# Information for PMD Developers

View File

@ -3,9 +3,8 @@ title: PMD Making Rulesets
tags: [customizing]
summary: Making Custom Rulesets for PMD
last_updated: July 3, 2016
sidebar: pmd_sidebar
permalink: pmd_devdocs_making_rulesets.html
folder: pmd/devdocs
author: Tom Copeland <tomcopeland@users.sourceforge.net>
---
# How to make a new rule set

View File

@ -1,22 +1,29 @@
---
title: Using code metrics in custom rules
tags: [customizing]
summary: "PMD was recently enhanced with the ability to compute code metrics on Java and Apex source (the so-called
Metrics Framework). This framework provides developers with a straightforward interface to use code metrics in their
summary: "PMD was recently enhanced with the ability to compute code metrics on Java and Apex source (the so-called
Metrics Framework). This framework provides developers with a straightforward interface to use code metrics in their
rules, and to extend the framework with their own custom metrics."
last_updated: July 20, 2017
permalink: pmd_devdocs_metrics_howto.html
author: Clément Fournier <clement.fournier76@gmail.com>
---
# Using code metrics in custom rules
## Using the metrics framework
{%include note.html content="The following explains how to use the Java metrics framework. The Apex framework
{%include note.html content="Using the metrics framework is for now restricted to Java rules (with plans to support
XPath rules later)." %}
To use the metrics framework in a custom rule, the first thing to do would be to **enable metrics by adding the
`metrics="true"` attribute** to your rule's XML element.
{%include note.html content="The following explains how to use the Java metrics framework. The Apex framework
differs only by the name of its classes." %}
In PMD's Metrics framework, a metric is an operation that can be carried out on nodes of a certain type and produces
a numeric result. In the Java framework, metrics can be computed on operation declaration nodes (constructor and
method declaration), and type declaration nodes (class, interface, enum, and annotation declarations). A metric
In PMD's Metrics framework, a metric is an operation that can be carried out on nodes of a certain type and produces
a numeric result. In the Java framework, metrics can be computed on operation declaration nodes (constructor and
method declaration), and type declaration nodes (class, interface, enum, and annotation declarations). A metric
object in the framework can only handle either types or operations, but not both.
PMD ships with a library of already implemented metrics. These metrics are referenced by `MetricKey` objects,
@ -27,9 +34,6 @@ each enum.
## For XPath rules
To use the metrics framework in a custom rule, the first thing to do would be to enable metrics by adding the
`metrics="true"` attribute to your rule's XML element.
XPath rules can compute metrics using the `metric` function. This function takes a single **string argument**,
which is the name of the metric key as defined in `JavaClassMetricKey` or `JavaOperationMetricKey`. The metric
will be **computed on the context node**.
@ -56,12 +60,13 @@ or `ConstructorDeclaration`.
First, similarly to XPath rules, you should add the `metrics="true"` attribute to your rule's XML element.
The static façade class `JavaMetrics` is the single entry point to compute metrics in the Java framework.
This class provides the method `get` and its overloads. The following sections describes the interface of this class.
### Basic usage
The simplest overloads of `JavaMetrics.get` take two parameters: **a `MetricKey` and a node of the corresponding type.**
Say you want to write a rule to report methods that have a high cyclomatic complexity. In your rule's visitor, you
The simplest overloads of `JavaMetrics.get` take two parameters: **a `MetricKey` and a node of the corresponding type.**
Say you want to write a rule to report methods that have a high cyclomatic complexity. In your rule's visitor, you
can get the value of Cyclo for a method node like so:
```java
public Object visit(ASTMethodDeclaration method, Object data) {
@ -74,18 +79,18 @@ public Object visit(ASTMethodDeclaration method, Object data) {
```
The same goes for class metrics: you select one among `JavaClassMetricKey`'s constants and pass it along with the node
to `JavaMetrics.get`.
{%include tip.html
to `JavaMetrics.get`.
{%include tip.html
content="A specific base rule class (`AbstractJavaMetricsRule`) exists
to e.g. check constructors and method nodes completely alike. This comes
in handy for metrics, as they usually don't make the distinction" %}
### Capability checking
Metrics are not necessarily computable on any node of the type they handle. For example, Cyclo cannot be computed on
Metrics are not necessarily computable on any node of the type they handle. For example, Cyclo cannot be computed on
abstract methods. Metric keys provides a `supports(Node)` boolean method to find out if the metric can be computed on
the specified node. **If the metric cannot be computed on the given node, `JavaMetrics.get` will return `Double.NaN` .**
the specified node. **If the metric cannot be computed on the given node, `JavaMetrics.get` will return `Double.NaN` .**
If you're concerned about that, you can condition your call on whether the node is supported or not:
```java
public Object visit(ASTMethodDeclaration method, Object data) {
@ -101,16 +106,16 @@ public Object visit(ASTMethodDeclaration method, Object data) {
### Metric options
Some metrics define options that can be used to slightly modify the computation. You'll typically see these options
gathered inside an enum in the implementation class of the metric, for example `CycloMetric.CycloOptions`. They're
Some metrics define options that can be used to slightly modify the computation. You'll typically see these options
gathered inside an enum in the implementation class of the metric, for example `CycloMetric.CycloOptions`. They're
also documented on the [index of metrics](pmd_java_metrics_index.html).
To use options with a metric, you must first bundle them into a `MetricOptions` object. `MetricOptions` provides the
utility method `ofOptions` to get a `MetricOptions` bundle from a collection or with varargs parameters. You can then
To use options with a metric, you must first bundle them into a `MetricOptions` object. `MetricOptions` provides the
utility method `ofOptions` to get a `MetricOptions` bundle from a collection or with varargs parameters. You can then
pass this bundle as a parameter to `JavaMetrics.get`:
```java
public Object visit(ASTMethodDeclaration method, Object data) {
int cyclo = (int) JavaMetrics.get(JavaOperationMetricKey.CYCLO, method,
int cyclo = (int) JavaMetrics.get(JavaOperationMetricKey.CYCLO, method,
MetricOptions.ofOptions(CycloOptions.IGNORE_BOOLEAN_PATHS));
if (cyclo > 10) {
// add violation
@ -119,18 +124,18 @@ public Object visit(ASTMethodDeclaration method, Object data) {
}
```
The version of `MetricOptions.ofOptions` using a collection is useful when you're building a `MetricOptions` from eg
the value of an `EnumeratedMultiProperty`, which gives users control of the options they use. See
The version of `MetricOptions.ofOptions` using a collection is useful when you're building a `MetricOptions` from eg
the value of an `EnumeratedMultiProperty`, which gives users control of the options they use. See
[CyclomaticComplexityRule]( https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/rule/CyclomaticComplexityRule.java)
for an example usage.
### Result options
The Metrics API also gives you the possibility to aggregate the result of an operation metric on all operations of a
The Metrics API also gives you the possibility to aggregate the result of an operation metric on all operations of a
class very simply. You can for example get the highest value of the metric over a class that way:
```java
public Object visit(ASTClassOrInterfaceDeclaration clazz, Object data) {
int highest = (int) JavaMetrics.get(JavaOperationMetricKey.CYCLO, clazz,
int highest = (int) JavaMetrics.get(JavaOperationMetricKey.CYCLO, clazz,
ResultOption.HIGHEST);
if (highest > 10) {
// add violation
@ -139,8 +144,8 @@ public Object visit(ASTClassOrInterfaceDeclaration clazz, Object data) {
}
```
Notice that **we use an operation metric and a class node**. The `ResultOption` parameter controls what result will be
computed: you can choose among `HIGHEST`, `SUM` and `AVERAGE`. You can use metric options together with a result
Notice that **we use an operation metric and a class node**. The `ResultOption` parameter controls what result will be
computed: you can choose among `HIGHEST`, `SUM` and `AVERAGE`. You can use metric options together with a result
option too.
### Complete use case
@ -297,4 +302,3 @@ Language | Java | Apex |
-----------|------|------|
Operation metrics| supports constructors and non abstract methods| supports any non abstract method except `<init>`, `<clinit>`, and `clone`
Type declaration|supports classes and enums|supports classes

View File

@ -1,6 +1,173 @@
---
title: Pull Requests
sidebar: pmd_sidebar
title: Pull-Request Merge
permalink: pmd_devdocs_pull_requests.html
folder: pmd/devdocs
last_updated: August 2017
author: Andreas Dangel <andreas.dangel@adangel.org>
---
## Contributing via pull requests
First off, thanks for taking the time to contribute!
* Please create your pull request against the `master` branch. We will rebase/merge it to the maintenance
branches, if necessary. Just fork the [pmd repo](https://github.com/pmd/pmd/) and
create a [pull request](https://github.com/pmd/pmd/pulls).
* We are using [checkstyle](http://checkstyle.sourceforge.net/) to enforce a common code style.
The check is integrated into the default build - so, make sure, you can [build PMD](pmd_devdocs_building.html)
without errors.
See [code style](pmd_devdocs_codestyle.html) for more info.
## Merging pull requests
### Example 1: Merging PR #123 into master
1. Review the pull request
* Compilation and checkstyle is verified already by travis build: PRs are automatically checked.
* If it is a bug fix, a new unit test, that reproduces the bug, is mandatory. Without such a test, we might accidentally reintroduce the bug again.
* Add the appropriate labels on the github issue: If the PR fixes a bug, the label "a:bug" should be used.
* Make sure, the PR is added to the appropriate milestone. If the PR fixes a bug, make sure, that the bug issue is added to the same milestone.
2. The actual merge commands:
We assume, that the PR has been created from the master branch. If this is not the case,
then we'll either need to rebase or ask for rebasing before merging.
```
git checkout master && git pull origin master # make sure, you have the latest code
git fetch origin pull/123/head:pr-123 && git checkout pr-123 # creates a new temporary branch
```
3. Update the [release notes](https://github.com/pmd/pmd/blob/master/docs/pages/release_notes.md):
* Are there any API changes, that need to be documented? (Section "API Changes")
* Are there any significant changes to existing rules, that should be mentioned?
(Section "Modified Rules" / "New Rules" / "Removed Rules")
* If the PR fixes a bug, make sure, it is listed under the section "Fixed Issues".
* In any case, add the PR to the section "External Contributions"
* Commit these changes with the message:
git add docs/pages/release_notes.md
git commit -m "Update release notes, refs #123"
{% include note.html content="If the PR fixes a bug, verify, that we have a commit with the message
\"Fixes #issue-number\". If this doesn't exist, you can add it to the commit message when
updating the release notes: `Update release notes, refs #123, fixes #issue-number`.
This will automatically close the github issue." %}
4. Now merge the pull request into the master branch:
```
git checkout master
git merge --no-ff pr-123
```
{%include note.html content="If there are merge conflicts, you'll need to deal with them here." %}
5. Run the complete build: `./mvnw clean verify`
{% include note.html content="This will execute all the unit tests and the checkstyle tests. It ensures,
that the complete project can be build and is functioning on top of the current master." %}
6. If the build was successful, you are ready to push:
```
git push origin master
```
Since the temporary branch is now not needed anymore, you can delete it:
`git branch -d pr-123`.
### Example 2: Merging PR #124 into a maintenance branch
We ask, to create every pull request against master, to make it easier to contribute.
But if a pull request is intended to fix a bug in an older version of PMD, then we need to backport this pull request.
#### Creating a maintenance branch
For older versions, we use maintenance branches, like `pmd/5.8.x`. If there is no maintenance branch for
the specific version, then we'll have to create it first. Let's say, we want a maintenance branch for
PMD version 5.8.0, so that we can create a bugfix release 5.8.1.
1. We'll simply create a new branch off of the release tag:
```
git branch pmd/5.8.x pmd_releases/5.8.0 && git checkout pmd/5.8.x
```
2. Now we'll need to adjust the version, since it's currently the same as the release version.
We'll change the version to the next patch version: "5.8.1-SNAPSHOT".
```
./mvnw versions:set -DnewVersion=5.8.1-SNAPSHOT
git add pom.xml \*/pom.xml
git commit -m "prepare next version 5.8.1-SNAPSHOT"
```
#### Merging the PR
1. As above: Review the PR
2. Fetch the PR and rebase it onto the maintenance branch:
```
git fetch origin pull/124/head:pr-124 && git checkout pr-124 # creates a new temporary branch
git rebase master --onto pmd/5.8.x
./mvnw clean verify # make sure, everything works after the rebase
```
{%include note.html content="You might need to fix conflicts / backport the commits for the older
PMD version." %}
3. Update the release notes. See above for details.
4. Now merge the pull request into the maintenance branch:
```
git checkout pmd/5.8.x
git merge --no-ff pr-124
```
5. Just to be sure, run the complete build again: `./mvnw clean verify`.
6. If the build was successful, you are ready to push:
```
git push origin pmd/5.8.x
```
7. Since we have rebased the pull request, it won't appear as merged on github.
You need to manually close the pull request. Leave a comment, that it has been
rebased onto the maintenance branch.
#### Merging into master
Now the PR has been merged into the maintenance branch, but it is missing in any later version of PMD.
Therefore, we merge first into the next minor version maintenance branch (if existing):
git checkout pmd/5.9.x
git merge pmd/5.8.x
After that, we merge the changes into the master branch:
git checkout master
git merge pmd/5.9.x
{%include note.html content="This ensures, that every change on the maintenance branch eventually ends
up in the master branch and therefore in any future version of PMD.<br>
The downside is however, that there are inevitable merge conflicts for the maven `pom.xml` files, since
every branch changed the version number differently.<br>
We could avoid this by merging only the temporary branch \"pr-124\" into each maintenance branch and
eventually into master, with the risk of missing single commits in a maintenance branch, that have been
done outside the temporary branch." %}
#### Merging vs. Cherry-Picking
We are not using cherry-picking, so that each fix is represented by a single commit.
Cherry-picking would duplicate the commit and you can't see in the log, on which branches the fix has been
integrated (e.g. gitk and github show the branches, from which the specific commit is reachable).
The downside is a more complex history - the maintenance branches and master branch are "connected" and not separate.

View File

@ -1,8 +1,7 @@
---
title: Releasing
sidebar: pmd_sidebar
permalink: pmd_devdocs_releasing.html
folder: pmd/devdocs
author: Romain Pelisse <rpelisse@users.sourceforge.net>, Andreas Dangel <adangel@users.sourceforge.net>
---
This page describes the current status of the release process.
@ -172,7 +171,7 @@ Maybe there are some milestones on sourceforge, too: <https://sourceforge.net/p/
### Merging
If the release was done on a maintenance branch, such as `pmd/5.4.x`, then this branch should be
merge into the next "higher" branches, such as `pmd/5.5.x` and `master`.
merged into the next "higher" branches, such as `pmd/5.5.x` and `master`.
This ensures, that all fixes done on the maintenance branch, finally end up in the other branches.
In theory, the fixes should already be there, but you never now.
@ -180,7 +179,7 @@ In theory, the fixes should already be there, but you never now.
### Multiple releases
If releases from multiple branches are being done, the order matters. You should start from the "oldes" branch,
If releases from multiple branches are being done, the order matters. You should start from the "oldest" branch,
e.g. `pmd/5.4.x`, release from there. Then merge (see above) into the next branch, e.g. `pmd/5.5.x` and release
from there. Then merge into the `master` branch and release from there. This way, the last release done, becomes
automatically the latest release on <https://pmd.github.io/latest/> and on sourceforge.

View File

@ -1,8 +1,9 @@
---
title: Roadmap
sidebar: pmd_sidebar
permalink: pmd_devdocs_roadmap.html
folder: pmd/devdocs
author: >
Tom Copeland <tom@infoether.com>, Ryan Gustavson, Romain Pelisse <belaran@gmail.com>,
Juan Martín Sotuyo Dodero <juansotuyo@gmail.com>, Andreas Dangel <adangel@users.sourceforge.net>
---

View File

@ -3,9 +3,8 @@ title: PMD Rule Guidelines
tags: [customizing]
summary: Rule Guidelines
last_updated: July 3, 2016
sidebar: pmd_sidebar
permalink: pmd_devdocs_rule_guidelines.html
folder: pmd/devdocs
author: Xavier Le Vourch, Ryan Gustafson, Romain Pelisse
---
# Rule Guidelines

View File

@ -0,0 +1,143 @@
---
title: Writing Documentation
last_update: August 2017
permalink: pmd_devdocs_writing_documentation.html
keywords: documentation, jekyll, markdown
author: Andreas Dangel <andreas.dangel@adangel.org>
---
PMD's documentation uses [Jekyll](https://jekyllrb.com/) with
the [I'd rather be writing Jekyll Theme](http://idratherbewriting.com/documentation-theme-jekyll/index.html).
Here are some quick tips.
## Format
The pages are in general in [Github Flavored Markdown](https://kramdown.gettalong.org/parser/gfm.html).
## Structure
All documentation is stored in the folder `docs/`. This is the folder, that github and the travis-ci scripts
use to render the site.
New pages are stored in the different subfolders under `pages`. The folder structure resembles the sidebar structure.
Since all pages use a simple *permalink*, in the rendered html pages, all pages are flattened in one directory.
This makes it easy to view the documentation also offline.
## Building
There are two ways, to execute jekyll:
1. Using [bundler](http://bundler.io/). This will install all the needed ruby packages locally and execute jekyll:
# this is required only once, to download and install the dependencies
bundle install
# this builds the documentation under _site
bundle exec jekyll build
# this runs a local webserver as http://localhost:4005
bundle exec jekyll serve
2. Using [docker](https://www.docker.com/). This will create a local docker image, into which all needed ruby
packages and jekyll is installed.
# this is required only once to create a local docker image named "pmd-doc"
docker build --no-cache -t pmd-doc .
# this builds the documentation under _site
docker run --rm=true -v "$PWD:/src" pmd-doc build -H 0.0.0.0
# this runs a local webserver as http://localhost:4005
docker run --rm=true -v "$PWD:/src" -p 4005:4005 pmd-doc serve -H 0.0.0.0
The built site is stored locally in the (git ignored) directory `_site`. You can
point your browser to `_site/index.html` to see the pmd documentation.
Alternatively, you can start the local webserver, that will serve the documentation.
Just go to http://localhost:4005.
If a page is modified, the documentation will automatically be rendered again and
all you need to do, is refreshing the page in your browser.
See also the script [pmd-jekyll.sh](https://gist.github.com/oowekyala/ee6f8801138861072c59ce683bdf737b).
It starts the jekyll server in the background and doesn't block the current shell.
## The sidebar
The sidebar is stored as a YAML document under `_data/sidebars/pmd_sidebar.yml`.
Make sure to add an entry there, whenever you create a new page.
## The frontmatter
Each page in jekyll begins with a YAML section at the beginning. This section
is separated by 3 dashes (`---`). Example:
---
title: Writing Documentation
last_update: August 2017
permalink: pmd_devdocs_writing_documentation.html
---
Some Text
# Some header
There are a couple of possible fields. Most important and always
required are **title** and **permalink**.
By default, a page **toc** (table of contents) is automatically generated.
You can prevent this with "toc: false".
You can add **keywords**, that will be used for the on-site search: "keywords: documentation, jekyll, markdown"
It's useful to maintain a **last_update** field. This will be added at the bottom of the
page.
A **summary** can also be provided. It will be added in a box before the content.
For a more exhaustive list, see [Pages - Frontmatter](http://idratherbewriting.com/documentation-theme-jekyll/mydoc_pages.html#frontmatter).
## Alerts and Callouts
See [Alerts](http://idratherbewriting.com/documentation-theme-jekyll/mydoc_alerts.html).
For example, a info-box can be created like this:
{%raw%}{% include note.html content="This is a note." %}{%endraw%}
It renders as:
{% include note.html content="This is a note." %}
Other available types are:
* note.html
* tip.html
* warning.html
* important.html
A callout is created like this:
{%raw%}{% include callout.html content="This is a callout of type default.<br/><br/>There are the following types available: danger, default, primary, success, info, and warning." type="default" %}{%endraw%}
It renders as:
{% include callout.html content="This is a callout of type default.<br/><br/>There are the following types available: danger, default, primary, success, info, and warning." type="default" %}
## Code samples with syntax highlighting
This is as easy as:
``` java
public class Foo {
public void bar() { System.out.println("x"); }
}
```
This looks as follows:
``` java
public class Foo {
public void bar() { System.out.println("x"); }
}
```

View File

@ -3,9 +3,8 @@ title: PMD Writing a Custom Rule
tags: [customizing]
summary: Writing a Custom Rule for PMD
last_updated: July 3, 2016
sidebar: pmd_sidebar
permalink: pmd_devdocs_writing_pmd_rules.html
folder: pmd/devdocs
author: Tom Copeland <tomcopeland@users.sourceforge.net>
---
# How to write a PMD rule

View File

@ -1,11 +1,10 @@
---
title: PMD Writing XPath Rules
title: Writing XPath Rules
tags: [customizing]
summary: "Writing XPath rules for PMD"
last_updated: July 3, 2016
sidebar: pmd_sidebar
permalink: pmd_devdocs_writing_xpath_rules.html
folder: pmd/devdocs
author: Miguel Griffa <mikkey@users.sourceforge.net>
---
# XPath Rule tutorial
@ -151,4 +150,50 @@ The following expression does the magic we need:
We recommend at this point that you experiment with Designer putting the final modifier to the Factory and verifying that the results produced are those expected.
## Creating a new rule definition
To actually use your new XPath rule, it needs to be in a ruleset. You can create a new custom ruleset which just
contains your new XPath rule. You can use the following template. Just make sure, to replace the `xpath` property,
the example code and give your rule a useful name and message.
``` xml
<?xml version="1.0"?>
<ruleset name="Custom Rules"
xmlns="http://pmd.sourceforge.net/ruleset/3.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/3.0.0 http://pmd.sourceforge.net/ruleset_3_0_0.xsd">
<description>
Custom rules
</description>
<rule name="My Rule"
language="java"
message="violation message"
class="net.sourceforge.pmd.lang.rule.XPathRule">
<description>
Rule Description
</description>
<priority>3</priority>
<properties>
<property name="xpath">
<value><![CDATA[
--- here comes your XPath expression
]]></value>
</property>
</properties>
<example>
<![CDATA[
public class ExampleCode {
public void foo() {
}
}
]]>
</example>
</rule>
</ruleset>
```
Finally, for many more details on writing XPath rules, pick up [PMD Applied](http://pmdapplied.com/)!

View File

@ -1,8 +1,7 @@
---
title: JSP Support
sidebar: pmd_sidebar
permalink: pmd_languages_jsp.html
folder: pmd/languages
author: Pieter Vanraemdonck
---
## What is currently supported and what is not

View File

@ -40,6 +40,11 @@ public class Foo {
|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier|
|cc_block_highlighting|false|Code Climate Block Highlighting|
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/apex/apexunit.xml/ApexUnitTestClassShouldHaveAsserts" />
```
## ApexUnitTestShouldNotUseSeeAllDataTrue
**Since:** PMD 5.5.1
@ -72,3 +77,8 @@ public class Foo {
|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier|
|cc_block_highlighting|false|Code Climate Block Highlighting|
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/apex/apexunit.xml/ApexUnitTestShouldNotUseSeeAllDataTrue" />
```

View File

@ -42,6 +42,11 @@ for (int i = 0; i < 42; i++) { // preferred approach
|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier|
|cc_block_highlighting|false|Code Climate Block Highlighting|
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/apex/braces.xml/ForLoopsMustUseBraces" />
```
## IfElseStmtsMustUseBraces
**Since:** PMD 5.6.0
@ -79,6 +84,11 @@ else
|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier|
|cc_block_highlighting|false|Code Climate Block Highlighting|
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/apex/braces.xml/IfElseStmtsMustUseBraces" />
```
## IfStmtsMustUseBraces
**Since:** PMD 5.6.0
@ -112,6 +122,11 @@ if (foo) { // preferred approach
|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier|
|cc_block_highlighting|false|Code Climate Block Highlighting|
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/apex/braces.xml/IfStmtsMustUseBraces" />
```
## WhileLoopsMustUseBraces
**Since:** PMD 5.6.0
@ -145,3 +160,8 @@ while (true) { // preferred approach
|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier|
|cc_block_highlighting|false|Code Climate Block Highlighting|
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/apex/braces.xml/WhileLoopsMustUseBraces" />
```

View File

@ -42,6 +42,11 @@ public class Foo {
|cc_block_highlighting|false|Code Climate Block Highlighting|
|problemDepth|3|The if statement depth reporting threshold|
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/apex/complexity.xml/AvoidDeeplyNestedIfStmts" />
```
## ExcessiveClassLength
**Since:** PMD 5.5.0
@ -84,6 +89,11 @@ public class Foo {
|cc_block_highlighting|false|Code Climate Block Highlighting|
|sigma||Sigma value|
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/apex/complexity.xml/ExcessiveClassLength" />
```
## ExcessiveParameterList
**Since:** PMD 5.5.0
@ -119,6 +129,11 @@ public void addPerson(Date birthdate, BodyMeasurements measurements, int ssn) {
|cc_block_highlighting|false|Code Climate Block Highlighting|
|sigma||Sigma value|
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/apex/complexity.xml/ExcessiveParameterList" />
```
## ExcessivePublicCount
**Since:** PMD 5.5.0
@ -159,6 +174,11 @@ public class Foo {
|cc_block_highlighting|false|Code Climate Block Highlighting|
|sigma||Sigma value|
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/apex/complexity.xml/ExcessivePublicCount" />
```
## NcssConstructorCount
**Since:** PMD 5.5.0
@ -198,6 +218,11 @@ public class Foo extends Bar {
|cc_block_highlighting|false|Code Climate Block Highlighting|
|sigma||Sigma value|
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/apex/complexity.xml/NcssConstructorCount" />
```
## NcssMethodCount
**Since:** PMD 5.5.0
@ -236,6 +261,11 @@ public class Foo extends Bar {
|cc_block_highlighting|false|Code Climate Block Highlighting|
|sigma||Sigma value|
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/apex/complexity.xml/NcssMethodCount" />
```
## NcssTypeCount
**Since:** PMD 5.5.0
@ -276,6 +306,11 @@ public class Foo extends Bar {
|cc_block_highlighting|false|Code Climate Block Highlighting|
|sigma||Sigma value|
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/apex/complexity.xml/NcssTypeCount" />
```
## StdCyclomaticComplexity
**Since:** PMD 5.5.0
@ -341,6 +376,11 @@ public class Foo {
|cc_block_highlighting|false|Code Climate Block Highlighting|
|reportLevel|10|Cyclomatic Complexity reporting threshold|
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/apex/complexity.xml/StdCyclomaticComplexity" />
```
## TooManyFields
**Since:** PMD 5.5.0
@ -381,3 +421,8 @@ public class Person {
|cc_block_highlighting|false|Code Climate Block Highlighting|
|maxfields|15|Max allowable fields|
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/apex/complexity.xml/TooManyFields" />
```

View File

@ -39,6 +39,11 @@ public class Something {
|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier|
|cc_block_highlighting|false|Code Climate Block Highlighting|
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/apex/performance.xml/AvoidDmlStatementsInLoops" />
```
## AvoidSoqlInLoops
**Since:** PMD 5.5.0
@ -69,3 +74,8 @@ public class Something {
|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier|
|cc_block_highlighting|false|Code Climate Block Highlighting|
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/apex/performance.xml/AvoidSoqlInLoops" />
```

View File

@ -37,6 +37,11 @@ public without sharing class Foo {
|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier|
|cc_block_highlighting|false|Code Climate Block Highlighting|
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/apex/security.xml/ApexBadCrypto" />
```
## ApexCRUDViolation
**Since:** PMD 5.5.3
@ -76,6 +81,11 @@ public class Foo {
|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier|
|cc_block_highlighting|false|Code Climate Block Highlighting|
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/apex/security.xml/ApexCRUDViolation" />
```
## ApexCSRF
**Since:** PMD 5.5.3
@ -109,6 +119,11 @@ public class Foo {
|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier|
|cc_block_highlighting|false|Code Climate Block Highlighting|
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/apex/security.xml/ApexCSRF" />
```
## ApexDangerousMethods
**Since:** PMD 5.5.3
@ -144,6 +159,11 @@ public class Foo {
|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier|
|cc_block_highlighting|false|Code Climate Block Highlighting|
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/apex/security.xml/ApexDangerousMethods" />
```
## ApexInsecureEndpoint
**Since:** PMD 5.5.3
@ -174,6 +194,11 @@ public without sharing class Foo {
|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier|
|cc_block_highlighting|false|Code Climate Block Highlighting|
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/apex/security.xml/ApexInsecureEndpoint" />
```
## ApexOpenRedirect
**Since:** PMD 5.5.3
@ -204,6 +229,11 @@ public without sharing class Foo {
|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier|
|cc_block_highlighting|false|Code Climate Block Highlighting|
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/apex/security.xml/ApexOpenRedirect" />
```
## ApexSharingViolations
**Since:** PMD 5.5.3
@ -231,6 +261,11 @@ public without sharing class Foo {
|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier|
|cc_block_highlighting|false|Code Climate Block Highlighting|
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/apex/security.xml/ApexSharingViolations" />
```
## ApexSOQLInjection
**Since:** PMD 5.5.3
@ -259,6 +294,11 @@ public class Foo {
|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier|
|cc_block_highlighting|false|Code Climate Block Highlighting|
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/apex/security.xml/ApexSOQLInjection" />
```
## ApexSuggestUsingNamedCred
**Since:** PMD 5.5.3
@ -301,6 +341,11 @@ public class Foo {
|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier|
|cc_block_highlighting|false|Code Climate Block Highlighting|
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/apex/security.xml/ApexSuggestUsingNamedCred" />
```
## ApexXSSFromEscapeFalse
**Since:** PMD 5.5.3
@ -329,6 +374,11 @@ public without sharing class Foo {
|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier|
|cc_block_highlighting|false|Code Climate Block Highlighting|
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/apex/security.xml/ApexXSSFromEscapeFalse" />
```
## ApexXSSFromURLParam
**Since:** PMD 5.5.3
@ -357,3 +407,8 @@ public without sharing class Foo {
|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier|
|cc_block_highlighting|false|Code Climate Block Highlighting|
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/apex/security.xml/ApexXSSFromURLParam" />
```

View File

@ -36,6 +36,11 @@ global class Unchangeable {
|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier|
|cc_block_highlighting|false|Code Climate Block Highlighting|
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/apex/style.xml/AvoidGlobalModifier" />
```
## AvoidLogicInTrigger
**Since:** PMD 5.5.0
@ -75,6 +80,11 @@ trigger Accounts on Account (before insert, before update, before delete, after
|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier|
|cc_block_highlighting|false|Code Climate Block Highlighting|
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/apex/style.xml/AvoidLogicInTrigger" />
```
## ClassNamingConventions
**Since:** PMD 5.5.0
@ -99,6 +109,11 @@ public class Foo {}
|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier|
|cc_block_highlighting|false|Code Climate Block Highlighting|
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/apex/style.xml/ClassNamingConventions" />
```
## MethodNamingConventions
**Since:** PMD 5.5.0
@ -126,6 +141,11 @@ public class Foo {
|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier|
|cc_block_highlighting|false|Code Climate Block Highlighting|
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/apex/style.xml/MethodNamingConventions" />
```
## MethodWithSameNameAsEnclosingClass
**Since:** PMD 5.5.0
@ -155,6 +175,11 @@ public class MyClass {
|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier|
|cc_block_highlighting|false|Code Climate Block Highlighting|
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/apex/style.xml/MethodWithSameNameAsEnclosingClass" />
```
## VariableNamingConventions
**Since:** PMD 5.5.0
@ -196,3 +221,8 @@ public class Foo {
|cc_block_highlighting|false|Code Climate Block Highlighting|
|checkMembers|true|Check member variables|
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/apex/style.xml/VariableNamingConventions" />
```

View File

@ -55,6 +55,11 @@ function getX() {
|allowTernaryResults|false|Allow assignment within the result expressions of a ternary operator|
|allowIncrementDecrement|false|Allow increment or decrement operators within the conditional expression of an if, for, or while statement|
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/ecmascript/basic.xml/AssignmentInOperand" />
```
## AvoidTrailingComma
**Since:** PMD 5.1
@ -88,6 +93,11 @@ function(arg) {
|allowObjectLiteral|false|Allow a trailing comma within an object literal|
|allowArrayLiteral|false|Allow a trailing comma within an array literal|
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/ecmascript/basic.xml/AvoidTrailingComma" />
```
## ConsistentReturn
**Since:** PMD 5.0
@ -128,6 +138,11 @@ function bar() {
|recordingLocalJsDocComments|true|Specifies that JsDoc comments are produced in the AST.|
|recordingComments|true|Specifies that comments are produced in the AST.|
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/ecmascript/basic.xml/ConsistentReturn" />
```
## EqualComparison
**Since:** PMD 5.0
@ -167,6 +182,11 @@ if (someVar != 3) {
}
```
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/ecmascript/basic.xml/EqualComparison" />
```
## GlobalVariable
**Since:** PMD 5.0
@ -192,6 +212,11 @@ function(arg) {
}
```
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/ecmascript/basic.xml/GlobalVariable" />
```
## InnaccurateNumericLiteral
**Since:** PMD 5.0
@ -221,6 +246,11 @@ var y = 1.1234567890123; // Ok
var z = 1.12345678901234567; // Not good
```
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/ecmascript/basic.xml/InnaccurateNumericLiteral" />
```
## ScopeForInVariable
**Since:** PMD 5.0
@ -269,6 +299,11 @@ function bar() {
}
```
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/ecmascript/basic.xml/ScopeForInVariable" />
```
## UnreachableCode
**Since:** PMD 5.0
@ -303,6 +338,11 @@ function bar() {
}
```
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/ecmascript/basic.xml/UnreachableCode" />
```
## UseBaseWithParseInt
**Since:** PMD 5.0.1
@ -331,3 +371,8 @@ parseInt("010"); // unclear, could be interpreted as 10 or 7 (with a base of
parseInt("10", 10); // good
```
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/ecmascript/basic.xml/UseBaseWithParseInt" />
```

View File

@ -34,6 +34,11 @@ for (var i = 0; i < 42; i++)
foo();
```
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/ecmascript/braces.xml/ForLoopsMustUseBraces" />
```
## IfElseStmtsMustUseBraces
**Since:** PMD 5.0
@ -65,6 +70,11 @@ else
y++;
```
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/ecmascript/braces.xml/IfElseStmtsMustUseBraces" />
```
## IfStmtsMustUseBraces
**Since:** PMD 5.0
@ -90,6 +100,11 @@ if (foo)
x++;
```
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/ecmascript/braces.xml/IfStmtsMustUseBraces" />
```
## WhileLoopsMustUseBraces
**Since:** PMD 5.0
@ -115,3 +130,8 @@ while (true)
x++;
```
**Use this rule by referencing it:**
``` xml
<rule ref="rulesets/ecmascript/braces.xml/WhileLoopsMustUseBraces" />
```

Some files were not shown because too many files have changed in this diff Show More