Merge remote-tracking branch 'upstream/master'

This commit is contained in:
kenji21
2018-04-03 08:49:12 +02:00
688 changed files with 17481 additions and 7038 deletions

View File

@ -1,6 +1,9 @@
Please, prefix the report title with the language it applies to within brackets, such as *[java]* or *[apex]*. If not specific to a language, you can use *[core]*
Please, prefix the report title with the language it applies to within brackets, such as [java] or [apex].
If not specific to a language, you can use [core].
**Rule Set:**
**Affects PMD Version:**
**Rule:**
**Description:**

View File

@ -46,7 +46,7 @@ deploy:
file_glob: true
file:
- pmd-dist/target/pmd-*.zip
- target/pmd-doc-*.zip
- docs/pmd-doc-*.zip
skip_cleanup: true
on:
tags: true
@ -58,6 +58,7 @@ notifications:
email:
recipients:
- andreas.dangel@adangel.org
- pmd-commits@lists.sourceforge.net
on_success: always
on_failure: always
cache:

View File

@ -14,7 +14,7 @@ fi
#
# for java9: enable all modules.
# coveralls plugin seems to need java.xml.bind module
#
echo "MAVEN_OPTS='-Xms1g -Xmx1g --add-modules java.se.ee'" > ${HOME}/.mavenrc
./mvnw clean test jacoco:report coveralls:report -Pcoveralls -B -V
./mvnw clean install -DskipTests=true -Dmaven.javadoc.skip=true -B -V
./mvnw test jacoco:report coveralls:report -Pcoveralls -B -V

View File

@ -25,8 +25,7 @@ function push_docs() {
VERSION=$(./mvnw -q -Dexec.executable="echo" -Dexec.args='${project.version}' --non-recursive org.codehaus.mojo:exec-maven-plugin:1.5.0:exec | tail -1)
echo "Building PMD ${VERSION} on branch ${TRAVIS_BRANCH}"
# TODO : Once we release PMD 6.0.0 and have a compatible PMD plugin, enable PMD once again
MVN_BUILD_FLAGS="-B -V -Dpmd.skip=true"
MVN_BUILD_FLAGS="-B -V"
if travis_isPullRequest; then

View File

@ -14,7 +14,6 @@ fi
#
# for java9: enable all modules.
# sonar plugin seems to need java.xml.bind module
#
echo "MAVEN_OPTS='-Xms1g -Xmx1g --add-modules java.se.ee'" > ${HOME}/.mavenrc
# Run the build, truncate output due to Travis log limits

View File

@ -46,9 +46,9 @@ fi
fi
if [ "${BUILD}" = "site" ]; then
if [ "${BUILD}" = "doc" ]; then
echo "Adding the site to pmd.github.io..."
echo "Adding the new doc to pmd.github.io..."
# clone pmd.github.io. Note: This uses the ssh key setup earlier
# In order to speed things up, we use a sparse checkout - no need to checkout all directories here
mkdir pmd.github.io
@ -61,7 +61,7 @@ mkdir pmd.github.io
git remote add origin git@github.com:pmd/pmd.github.io.git
echo "latest/" > .git/info/sparse-checkout
git pull --depth=1 origin master
rsync -a ../target/pmd-doc-${RELEASE_VERSION}/ pmd-${RELEASE_VERSION}/
rsync -a ../docs/pmd-doc-${RELEASE_VERSION}/ pmd-${RELEASE_VERSION}/
git add pmd-${RELEASE_VERSION}
git commit -q -m "Added pmd-${RELEASE_VERSION}"
git rm -qr latest

View File

@ -29,10 +29,11 @@ When filing a bug report, please provide as much information as possible, so tha
## Documentation
There is some documentation available under <https://pmd.github.io>. Feel free to create a bug report if
documentation is missing, incomplete or outdated.
There is some documentation available under <https://pmd.github.io/pmd>. Feel free to create a bug report if
documentation is missing, incomplete or outdated. See [Bug reports](#bug-reports).
The documentation is generated as a maven site, the source is available at: <https://github.com/pmd/pmd/tree/master/src/site>
The documentation is generated as a Jekyll site, the source is available at: <https://github.com/pmd/pmd/tree/master/docs>. You can find build instructions there.
For more on contributing documentation check <https://pmd.github.io/pmd/pmd_devdocs_writing_documentation.html>
## Questions

View File

@ -1,5 +1,6 @@
# PMD
[![Join the chat at https://gitter.im/pmd/pmd](https://badges.gitter.im/pmd/pmd.svg)](https://gitter.im/pmd/pmd?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Build Status](https://travis-ci.org/pmd/pmd.svg?branch=master)](https://travis-ci.org/pmd/pmd)
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/net.sourceforge.pmd/pmd/badge.svg)](https://maven-badges.herokuapp.com/maven-central/net.sourceforge.pmd/pmd)
[![Coverage Status](https://coveralls.io/repos/github/pmd/pmd/badge.svg)](https://coveralls.io/github/pmd/pmd)

View File

@ -24,7 +24,7 @@ echo "Releasing PMD"
echo "-------------------------------------------"
# see also https://gist.github.com/pdunnavant/4743895
CURRENT_VERSION=$(./mvnw -q -Dexec.executable="echo" -Dexec.args='${project.version}' --non-recursive org.codehaus.mojo:exec-maven-plugin:1.5.0:exec|tail -1)
CURRENT_VERSION=$(./mvnw -q -Dexec.executable="echo" -Dexec.args='${project.version}' --non-recursive org.codehaus.mojo:exec-maven-plugin:1.5.0:exec)
RELEASE_VERSION=${CURRENT_VERSION%-SNAPSHOT}
MAJOR=$(echo $RELEASE_VERSION | cut -d . -f 1)
MINOR=$(echo $RELEASE_VERSION | cut -d . -f 2)
@ -40,6 +40,12 @@ fi
DEVELOPMENT_VERSION="$MAJOR.$NEXT_MINOR.$NEXT_PATCH"
DEVELOPMENT_VERSION="${DEVELOPMENT_VERSION}-SNAPSHOT"
# allow to override the next version, e.g. via "NEXT_VERSION=7.0.0 ./do-release.sh"
if [ "$NEXT_VERSION" != "" ]; then
DEVELOPMENT_VERSION="${NEXT_VERSION}-SNAPSHOT"
fi
# http://stackoverflow.com/questions/1593051/how-to-programmatically-determine-the-current-checked-out-git-branch
CURRENT_BRANCH=$(git symbolic-ref -q HEAD)
CURRENT_BRANCH=${CURRENT_BRANCH##refs/heads/}
@ -64,10 +70,14 @@ echo "* Update version/release info in **docs/pages/release_notes.md**."
echo
echo " ## $(date -u +%d-%B-%Y) - ${RELEASE_VERSION}"
echo
echo "* Update date info in **docs/_config.yml**."
echo
echo "* Ensure all the new rules are listed in a the proper file:"
echo " pmd-core/src/main/resources/rulesets/releases/${RELEASE_VERSION}.xml file."
echo
echo "* Update **../pmd.github.io/index.html** to mention the new release"
echo "* Update **../pmd.github.io/_config.yml** to mention the new release"
echo
echo "* Add **../pmd.github.io/_posts/$(date -u +%d-%m-%Y)-PMD-${RELEASE_VERSION}.md"
echo
echo "Press enter to continue..."
read
@ -76,6 +86,7 @@ git commit -a -m "Prepare pmd release ${RELEASE_VERSION}"
(
echo "Committing current changes (pmd.github.io)"
cd ../pmd.github.io
git add _posts/$(date -u +%Y-%m-%d)-PMD-${RELEASE_VERSION}.md
git commit -a -m "Prepare pmd release ${RELEASE_VERSION}"
git push
)
@ -96,24 +107,26 @@ echo
cat <<EOF
PMD ${RELEASE_VERSION} released
* minor version with lots of bug fixes
* Release Notes: https://pmd.github.io/pmd-${RELEASE_VERSION}/pmd_release_notes.html
* Downloads: https://github.com/pmd/pmd/releases/tag/pmd_releases%2F${RELEASE_VERSION}
* Fixed Bugs: https://sourceforge.net/p/pmd/bugs/milestone/PMD-${RELEASE_VERSION}/
* Documentation: https://pmd.github.io/pmd-${RELEASE_VERSION}/
And Copy-Paste the release notes
EOF
echo
echo "Press enter to continue..."
read
echo
echo "Check the milestone on sourceforge:"
echo "<https://sourceforge.net/p/pmd/bugs/milestones>"
echo "Check the milestone on github:"
echo "<https://github.com/pmd/pmd/milestones>"
echo " --> move any open issues to the next milestone, close the current milestone"
echo " --> Maybe there are some milestones on sourceforge, too: <https://sourceforge.net/p/pmd/bugs/milestones>."
echo
echo
echo
echo "Prepare Next development version:"
echo "* Move version/release info from **docs/pages/release_notes.md** to **docs/pages/release_notes_old.md**."
echo "* Update version/date info in **docs/_config.yml**."
echo "* Update version/release info in **docs/pages/release_notes.md**."
echo
cat <<EOF
@ -159,7 +172,12 @@ echo
echo "Send out an announcement mail to the mailing list:"
echo "To: PMD Developers List <pmd-devel@lists.sourceforge.net>"
echo "Subject: [ANNOUNCE] PMD ${RELEASE_VERSION} Released"
echo "Body: !!Copy Changelog!!"
echo
echo " * Downloads: https://github.com/pmd/pmd/releases/tag/pmd_releases%2F${RELEASE_VERSION}"
echo " * Documentation: https://pmd.github.io/pmd-${RELEASE_VERSION}/"
echo
echo " And Copy-Paste the release notes"
echo
echo
echo
echo "------------------------------------------"

View File

@ -1,4 +1,4 @@
FROM ruby:2.1
FROM ruby:2.4.2
MAINTAINER mrafayaleem@gmail.com
RUN apt-get clean \

View File

@ -1,7 +1,7 @@
GEM
remote: https://rubygems.org/
specs:
activesupport (4.2.8)
activesupport (4.2.9)
i18n (~> 0.7)
minitest (~> 5.1)
thread_safe (~> 0.3, >= 0.3.4)
@ -11,9 +11,12 @@ GEM
coffee-script (2.4.1)
coffee-script-source
execjs
coffee-script-source (1.12.2)
coffee-script-source (1.11.1)
colorator (1.1.0)
ethon (0.10.1)
commonmarker (0.17.7.1)
ruby-enum (~> 0.5)
concurrent-ruby (1.0.5)
ethon (0.11.0)
ffi (>= 1.3.0)
execjs (2.7.0)
faraday (0.13.1)
@ -21,25 +24,27 @@ GEM
ffi (1.9.18)
forwardable-extended (2.6.0)
gemoji (3.0.0)
github-pages (158)
activesupport (= 4.2.8)
github-pages (172)
activesupport (= 4.2.9)
github-pages-health-check (= 1.3.5)
jekyll (= 3.5.2)
jekyll-avatar (= 0.4.2)
jekyll-coffeescript (= 1.0.1)
jekyll (= 3.6.2)
jekyll-avatar (= 0.5.0)
jekyll-coffeescript (= 1.0.2)
jekyll-commonmark-ghpages (= 0.1.3)
jekyll-default-layout (= 0.1.4)
jekyll-feed (= 0.9.2)
jekyll-gist (= 1.4.1)
jekyll-github-metadata (= 2.9.1)
jekyll-github-metadata (= 2.9.3)
jekyll-mentions (= 1.2.0)
jekyll-optional-front-matter (= 0.2.0)
jekyll-optional-front-matter (= 0.3.0)
jekyll-paginate (= 1.1.0)
jekyll-readme-index (= 0.1.0)
jekyll-readme-index (= 0.2.0)
jekyll-redirect-from (= 0.12.1)
jekyll-relative-links (= 0.4.1)
jekyll-relative-links (= 0.5.2)
jekyll-remote-theme (= 0.2.3)
jekyll-sass-converter (= 1.5.0)
jekyll-seo-tag (= 2.3.0)
jekyll-sitemap (= 1.0.0)
jekyll-sitemap (= 1.1.1)
jekyll-swiss (= 0.4.0)
jekyll-theme-architect (= 0.1.0)
jekyll-theme-cayman (= 0.1.0)
@ -54,14 +59,14 @@ GEM
jekyll-theme-slate (= 0.1.0)
jekyll-theme-tactile (= 0.1.0)
jekyll-theme-time-machine (= 0.1.0)
jekyll-titles-from-headings (= 0.4.0)
jemoji (= 0.8.0)
kramdown (= 1.13.2)
jekyll-titles-from-headings (= 0.5.0)
jemoji (= 0.8.1)
kramdown (= 1.14.0)
liquid (= 4.0.0)
listen (= 3.0.6)
mercenary (~> 0.3)
minima (= 2.1.1)
rouge (= 1.11.1)
rouge (= 2.2.1)
terminal-table (~> 1.4)
github-pages-health-check (1.3.5)
addressable (~> 2.3)
@ -69,52 +74,65 @@ GEM
octokit (~> 4.0)
public_suffix (~> 2.0)
typhoeus (~> 0.7)
html-pipeline (2.7.0)
html-pipeline (2.7.1)
activesupport (>= 2)
nokogiri (>= 1.4)
i18n (0.8.6)
jekyll (3.5.2)
i18n (0.9.1)
concurrent-ruby (~> 1.0)
jekyll (3.6.2)
addressable (~> 2.4)
colorator (~> 1.0)
jekyll-sass-converter (~> 1.0)
jekyll-watch (~> 1.1)
kramdown (~> 1.3)
kramdown (~> 1.14)
liquid (~> 4.0)
mercenary (~> 0.3.3)
pathutil (~> 0.9)
rouge (~> 1.7)
rouge (>= 1.7, < 3)
safe_yaml (~> 1.0)
jekyll-avatar (0.4.2)
jekyll-avatar (0.5.0)
jekyll (~> 3.0)
jekyll-coffeescript (1.0.1)
jekyll-coffeescript (1.0.2)
coffee-script (~> 2.2)
coffee-script-source (~> 1.11.1)
jekyll-commonmark (1.1.0)
commonmarker (~> 0.14)
jekyll (>= 3.0, < 4.0)
jekyll-commonmark-ghpages (0.1.3)
commonmarker (~> 0.17.6)
jekyll-commonmark (~> 1)
rouge (~> 2)
jekyll-default-layout (0.1.4)
jekyll (~> 3.0)
jekyll-feed (0.9.2)
jekyll (~> 3.3)
jekyll-gist (1.4.1)
octokit (~> 4.2)
jekyll-github-metadata (2.9.1)
jekyll-github-metadata (2.9.3)
jekyll (~> 3.1)
octokit (~> 4.0, != 4.4.0)
jekyll-mentions (1.2.0)
activesupport (~> 4.0)
html-pipeline (~> 2.3)
jekyll (~> 3.0)
jekyll-optional-front-matter (0.2.0)
jekyll-optional-front-matter (0.3.0)
jekyll (~> 3.0)
jekyll-paginate (1.1.0)
jekyll-readme-index (0.1.0)
jekyll-readme-index (0.2.0)
jekyll (~> 3.0)
jekyll-redirect-from (0.12.1)
jekyll (~> 3.3)
jekyll-relative-links (0.4.1)
jekyll-relative-links (0.5.2)
jekyll (~> 3.3)
jekyll-remote-theme (0.2.3)
jekyll (~> 3.5)
rubyzip (>= 1.2.1, < 3.0)
typhoeus (>= 0.7, < 2.0)
jekyll-sass-converter (1.5.0)
sass (~> 3.4)
jekyll-seo-tag (2.3.0)
jekyll (~> 3.3)
jekyll-sitemap (1.0.0)
jekyll-sitemap (1.1.1)
jekyll (~> 3.3)
jekyll-swiss (0.4.0)
jekyll-theme-architect (0.1.0)
@ -157,40 +175,43 @@ GEM
jekyll-theme-time-machine (0.1.0)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-titles-from-headings (0.4.0)
jekyll-titles-from-headings (0.5.0)
jekyll (~> 3.3)
jekyll-watch (1.5.0)
listen (~> 3.0, < 3.1)
jemoji (0.8.0)
activesupport (~> 4.0)
jekyll-watch (1.5.1)
listen (~> 3.0)
jemoji (0.8.1)
activesupport (~> 4.0, >= 4.2.9)
gemoji (~> 3.0)
html-pipeline (~> 2.2)
jekyll (>= 3.0)
kramdown (1.13.2)
kramdown (1.14.0)
liquid (4.0.0)
listen (3.0.6)
rb-fsevent (>= 0.9.3)
rb-inotify (>= 0.9.7)
mercenary (0.3.6)
mini_portile2 (2.2.0)
mini_portile2 (2.3.0)
minima (2.1.1)
jekyll (~> 3.3)
minitest (5.10.3)
multipart-post (2.0.0)
net-dns (0.8.0)
nokogiri (1.8.0)
mini_portile2 (~> 2.2.0)
nokogiri (1.8.1)
mini_portile2 (~> 2.3.0)
octokit (4.7.0)
sawyer (~> 0.8.0, >= 0.5.3)
pathutil (0.14.0)
pathutil (0.16.1)
forwardable-extended (~> 2.6)
public_suffix (2.0.5)
rb-fsevent (0.10.2)
rb-inotify (0.9.10)
ffi (>= 0.5.0, < 2)
rouge (1.11.1)
rouge (2.2.1)
ruby-enum (0.7.1)
i18n
rubyzip (1.2.1)
safe_yaml (1.0.4)
sass (3.5.1)
sass (3.5.3)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4)
@ -203,7 +224,7 @@ GEM
thread_safe (0.3.6)
typhoeus (0.8.0)
ethon (>= 0.8.0)
tzinfo (1.2.3)
tzinfo (1.2.4)
thread_safe (~> 0.1)
unicode-display_width (1.3.0)
@ -215,4 +236,4 @@ DEPENDENCIES
jekyll
BUNDLED WITH
1.15.1
1.16.0

View File

@ -1,8 +1,8 @@
repository: pmd/pmd
pmd:
version: 6.0.0
date: to-be-defined
version: 6.3.0
date: 2018-04-29
output: web
# this property is useful for conditional filtering of content that is separate from the PDF.

File diff suppressed because it is too large Load Diff

View File

@ -47,6 +47,7 @@ Features:
Supported Languages:
* [Java](pmd_rules_java.html)
* [JSP](pmd_rules_jsp.html)
* [JavaScript](pmd_rules_ecmascript.html)
* [Salesforce.com Apex](pmd_rules_apex.html) and [Visualforce](pmd_rules_vf.html)
* [PLSQL](pmd_rules_plsql.html)

View File

@ -1,6 +1,6 @@
---
title: Getting Help
permalink: pmd_userdocs_help.html
permalink: pmd_about_help.html
author: Andreas Dangel <andreas.dangel@adangel.org>
last_updated: September 2017
---

View File

@ -1,10 +0,0 @@
---
title: Architecture
sidebar: pmd_sidebar
permalink: pmd_devdocs_architecture.html
folder: pmd/devdocs
---
PMD high-level building blocks
TODO

View File

@ -4,6 +4,9 @@ permalink: pmd_devdocs_building.html
author: Tom Copeland, Xavier Le Vourch <xlv@users.sourceforge.net>
---
<!-- Gives visibility -->
{%include note.html content="TODO add IDE specific indications" %}
# Compiling PMD
* JDK 9 or higher

View File

@ -1,10 +0,0 @@
---
title: Code Style
sidebar: pmd_sidebar
permalink: pmd_devdocs_codestyle.html
folder: pmd/devdocs
---
TODO
* Checkstyle

View File

@ -1,15 +1,13 @@
---
title: PMD How to Add a New CPD Language
short_title: Add a New CPD Language
title: How to add a new CPD language
short_title: Add a new CPD language
tags: [customizing]
summary: How to Add a New CPD Language
summary: How to add a new CPD language
last_updated: July 3, 2016
permalink: pmd_devdocs_adding_new_cpd_language.html
permalink: pmd_devdocs_major_adding_new_cpd_language.html
author: Romain PELISSE <belaran@gmail.com>
---
# How to Add a New Language to CPD
If you wish CPD to parse a unsupported language, you can easily develop a new parser for CPD. All you need to is implements the following interface:
* net.sourceforge.pmd.cpd.Language

View File

@ -1,15 +1,14 @@
---
title: PMD Adding a New Language
short_title: Adding a New Language
title: Adding PMD support for a new language
short_title: Adding a new language
tags: [customizing]
summary: Adding a New Language to PMD
summary: "How to add a new language to PMD."
last_updated: July 3, 2016
sidebar: pmd_sidebar
permalink: pmd_devdocs_adding_new_language.html
permalink: pmd_devdocs_major_adding_new_language.html
folder: pmd/devdocs
---
# How to Add a New Language to PMD
## 1. Start with a new sub-module.
* See pmd-java or pmd-vm for examples.

View File

@ -5,12 +5,11 @@ 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
a way that any PMD supported language can implement such a framework without too much trouble. Here's how."
last_updated: August 2017
permalink: pmd_devdocs_adding_metrics_support_to_language.html
last_updated: December 2017
permalink: pmd_devdocs_major_adding_new_metrics_framework.html
author: Clément Fournier <clement.fournier76@gmail.com>
---
{% include warning.html content="WIP, unstable API" %}
## Internal architecture of the metrics framework
@ -33,43 +32,24 @@ Metrics (`Metric<N>`) plug in to this static system and only provide behaviour t
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
components:
* 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.
metrics on a single file. The expressive power of metrics can be improved by implementing *signature matching* capabilities,
which allows a metric to count signatures matching a specific pattern (a mask) over a whole class. This was originally
designed to work across files, given a working usage resolution. However, making that work with incremental analysis is
harder than it looks, and has been rescheduled to another project.
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
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
node types of the class and operation AST nodes. Moreover, it makes the external behaviour of the framework 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
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
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
detection strategies.
than that. The info given in the signatures is usually very language specific, as it includes info about e.g.
visibility modifiers. So more work is required to implement that, but it can already be used to implement
sophisticated metrics, that already give access to detection strategies.
## Implementation of a new framework
@ -78,48 +58,34 @@ detection strategies.
* 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)
[Example](https://github.com/pmd/pmd/blob/master/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`,
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.
[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.
[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`.
[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
### 2. 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
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 `BasicProjectMemoizer<T, O>`. There's no abstract functionality to implement.
[Example](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaProjectMemoizer.java)
[Example](https://github.com/pmd/pmd/blob/master/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
your `MetricsComputer`.
[Example](https://github.com/pmd/pmd/blob/52d78d2fa97913cf73814d0307a1c1ae6125a437/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaMetricsFacade.java)
[Example](https://github.com/pmd/pmd/blob/master/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
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)
[Example](https://github.com/pmd/pmd/blob/master/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.
[Example](https://github.com/pmd/pmd/blob/52d78d2fa97913cf73814d0307a1c1ae6125a437/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/AbstractJavaOperationMetric.java)
[Example](https://github.com/pmd/pmd/blob/master/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.
[Example](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaOperationMetricKey.java)
* Create metrics by extending your base classes, reference them in your enums, and you can start using them with your
façade!
{% 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.
@ -133,8 +99,6 @@ 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
`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
custom `SignatureMatcher` interface, and your façade can give back its instance of the project mirror.
* Create utility methods in your abstract class metric class to count signatures matching a specific mask.
[Example](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/AbstractJavaClassMetric.java#L50)

View File

@ -6,7 +6,9 @@ author: >
Juan Martín Sotuyo Dodero <juansotuyo@gmail.com>, Andreas Dangel <adangel@users.sourceforge.net>
---
TODO:
* Update
* Future direction
* projects, plans
* Google Summer of Code

View File

@ -1,6 +0,0 @@
---
title: Setting up your IDE
sidebar: pmd_sidebar
permalink: pmd_devdocs_setting_up_ide.html
folder: pmd/devdocs
---

View File

@ -1,5 +1,5 @@
---
title: Writing Documentation
title: Writing documentation
last_update: August 2017
permalink: pmd_devdocs_writing_documentation.html
keywords: documentation, jekyll, markdown
@ -17,13 +17,48 @@ The pages are in general in [Github Flavored Markdown](https://kramdown.gettalon
## 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.
The documentation sources can be found in two places based on how they are generated:
- the ones that are manually written (like the one you are reading);
- and the ones that are generated automatically from the category files. All the rule documentation
pages are generated that way.
New pages are stored in the different subfolders under `pages`. The folder structure resembles the sidebar structure.
### Handwritten documentation
All handwritten documentation is stored in the subfolders under `docs/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.
### Rule documentation
The categories for a language `%lang%` are located in
`pmd-%lang%/src/main/resources/category/%lang% `. So for Java the categories
can be found under [pmd-java/src/main/resources/category/java](https://github.com/pmd/pmd/tree/master/pmd-java/src/main/resources/category/java).
The XML category files in this directory are transformed during build into markdown pages
describing the rules they contain. These pages are placed under `docs/` like the handwritten
documentation, and are then rendered with Jekyll like the rest of them. The rule documentation
generator is the separate submodule `pmd-doc`.
Modifying the documentation of a rule should thus not be done on the markdown page,
but directly on the XML `rule` tag corresponding to the rule, in the relevant
category file.
The XML documentation of rules can contain GitHub flavoured markdown.
Just wrap the markdown inside CDATA section in the xml. CDATA sections preserve
all formatting inside the delimiters, and allow to write code samples without
escaping special xml characters. For example:
```
<rule ...>
<description>
<![CDATA[
Full description, can contain markup
And paragraphs
]]>
</description>
...
</rule>
```
## Building
There are two ways, to execute jekyll:

View File

@ -1,27 +1,11 @@
---
title: Pull-Request Merge
permalink: pmd_devdocs_pull_requests.html
title: Merging pull requests
permalink: pmd_projectdocs_committers_merging_pull_requests.html
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
## Example 1: Merging PR #123 into master
1. Review the pull request
@ -81,12 +65,12 @@ First off, thanks for taking the time to contribute!
`git branch -d pr-123`.
### Example 2: Merging PR #124 into a maintenance branch
## 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
### 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
@ -107,7 +91,7 @@ PMD version 5.8.0, so that we can create a bugfix release 5.8.1.
git commit -m "prepare next version 5.8.1-SNAPSHOT"
```
#### Merging the PR
### Merging the PR
1. As above: Review the PR
@ -143,7 +127,7 @@ PMD version 5.8.0, so that we can create a bugfix release 5.8.1.
You need to manually close the pull request. Leave a comment, that it has been
rebased onto the maintenance branch.
#### Merging into master
### 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):
@ -164,7 +148,7 @@ We could avoid this by merging only the temporary branch \"pr-124\" into each ma
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
### 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

View File

@ -1,6 +1,6 @@
---
title: Releasing
permalink: pmd_devdocs_releasing.html
permalink: pmd_projectdocs_committers_releasing.html
author: Romain Pelisse <rpelisse@users.sourceforge.net>, Andreas Dangel <adangel@users.sourceforge.net>
---
@ -17,19 +17,28 @@ through the release process.
Make sure code is up to date and everything is committed and pushed with git:
$ mvn clean
$ ./mvnw clean
$ git pull
$ git status
### The Release Notes
### The Release Notes and docs
At a very minimum, the current date must be noted in the release notes. Also, the version
At a very minimum, the current date must be noted in the release notes and the download section. Also, the version
must be adjusted. E.g. by removing "-SNAPSHOT".
You can find the release notes here: `docs/pages/release_notes.md`.
The date for the download section is to be entered in `docs/_config.yml`, e.g.
```
pmd:
version: 6.0.0
date: 2017-12-15
```
The release notes usual mention any new rules that have been added since the last release.
Please double check the file `pmd-core/src/main/resources/rulesets/releases/<version>.xml`, so
that all new rules are listed.
@ -43,12 +52,19 @@ Check in all (version) changes to branch master or any other branch, from which
### The Homepage
The github repo `pmd.github.io` hosts the homepage for [https://pmd.github.io](https://pmd.github.io).
The `index.html` page needes to be updated to display the new release. The new release is mentioned
* on the start page
* in the announcements
* and in the previous releases section
The new version needs to be entered into `_config.yml`, e.g.:
```
pmd:
latestVersion: 6.0.0
latestVersionDate: 15th December 2017
```
Also move the previous version down into the "downloads" section.
Then create a new page for the new release, e.g. `_posts/2017-12-15-PMD-6.0.0.md` and copy
the release notes into this page. This will appear under the news section.
Check in all (version) changes to branch master:
@ -120,6 +136,7 @@ the following template:
### Prepare the new release notes
* Update version in **docs/_config.yml**
* Move version/release info from **docs/pages/release_notes.md** to **docs/pages/release_notes_old.md**.
* Update version/release info in **docs/pages/release_notes.md**. Use the following template:
@ -191,6 +208,6 @@ At some point, it might be time for a new maintenance branch. Such a branch is u
the `master` branch. Here are the steps:
* Create a new branch: `git branch pmd/5.6.x master`
* Update the version in both the new branch and master, e.g. `mvn versions:set -Dversion=5.6.0-SNAPSHOT`
and `mvn versions:set -Dversion=5.7.0-SNAPSHOT`.
* Update the version in both the new branch and master, e.g. `mvn versions:set -DnewVersion=5.6.1-SNAPSHOT`
and `mvn versions:set -DnewVersion=5.7.0-SNAPSHOT`.
* Update the release notes on both the new branch and master

View File

@ -1,6 +1,6 @@
---
title: Credits
permalink: pmd_userdocs_credits.html
permalink: pmd_projectdocs_credits.html
author: Tom Copeland <tom@infoether.org>
---

View File

@ -1,7 +1,7 @@
---
title: FAQ
sidebar: pmd_sidebar
permalink: pmd_userdocs_faq.html
permalink: pmd_projectdocs_faq.html
folder: pmd/userdocs
---

View File

@ -1,6 +1,6 @@
---
title: What does 'PMD' mean?
permalink: pmd_userdocs_meaning.html
permalink: pmd_projectdocs_trivia_meaning.html
author: David Dixon-Peugh
---

View File

@ -1,6 +1,6 @@
---
title: PMD in the press
permalink: pmd_userdocs_news.html
permalink: pmd_projectdocs_trivia_news.html
author: Tom Copeland <tom@infoether.org>
---

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