Merge branch 'master' of https://github.com/pmd/pmd
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@ -11,3 +11,5 @@ bin/
|
||||
*.patch
|
||||
*/src/site/site.xml
|
||||
pmd-core/dependency-reduced-pom.xml
|
||||
.bundle
|
||||
vendor
|
||||
|
@ -29,8 +29,12 @@ before_install:
|
||||
- wget https://github.com/sormuras/bach/raw/master/install-jdk.sh
|
||||
- bash .travis/setup-secrets.sh
|
||||
- bash .travis/configure-maven.sh
|
||||
- rvm install 2.4.1
|
||||
- rvm use 2.4.1
|
||||
# Install OracleJDK 10 - see https://sormuras.github.io/blog/2018-03-20-jdk-matrix.html
|
||||
install: . ./install-jdk.sh -F 10 -L BCL
|
||||
install:
|
||||
- . ./install-jdk.sh -F 10 -L BCL
|
||||
- bundle install --without=release_notes_preprocessing
|
||||
before_script: true
|
||||
script: source .travis/build-$BUILD.sh
|
||||
after_success: true
|
||||
@ -67,6 +71,7 @@ notifications:
|
||||
cache:
|
||||
directories:
|
||||
- "$HOME/.m2"
|
||||
- vendor/bundle
|
||||
|
||||
|
||||
# Secure Keys, that need to be set for snapshot builds
|
||||
@ -79,7 +84,6 @@ cache:
|
||||
# PMD_SF_USER - the sourceforge user, which is used to upload created binaries to sf files section. Note: an ssh key is
|
||||
# required. See "before_install".
|
||||
#
|
||||
#
|
||||
# Secure Keys, that need to be set for releases:
|
||||
#
|
||||
# PMD_SF_APIKEY - used to make the new release the default file in the files section. See https://sourceforge.net/auth/preferences/
|
||||
|
18
.travis/all-java.xml
Normal file
18
.travis/all-java.xml
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<ruleset name="All Java Rules"
|
||||
xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd">
|
||||
<description>Every java rule in PMD which is used for the regression tests with pmdtester</description>
|
||||
|
||||
<rule ref="category/java/bestpractices.xml" />
|
||||
<rule ref="category/java/codestyle.xml" />
|
||||
<rule ref="category/java/design.xml" />
|
||||
<rule ref="category/java/documentation.xml" />
|
||||
<rule ref="category/java/errorprone.xml" />
|
||||
<rule ref="category/java/multithreading.xml" />
|
||||
<rule ref="category/java/performance.xml" />
|
||||
<rule ref="category/java/security.xml" />
|
||||
|
||||
</ruleset>
|
@ -27,8 +27,23 @@ TRAVIS_COMMIT_RANGE=${TRAVIS_COMMIT_RANGE}"
|
||||
fi
|
||||
}
|
||||
|
||||
function upload_baseline() {
|
||||
log_info "Generating and uploading baseline for pmdtester..."
|
||||
cd ..
|
||||
pmdtester -m single -r ./pmd -p ${TRAVIS_BRANCH} -pc ./pmd/.travis/all-java.xml -l ./pmd/.travis/project-list.xml -f
|
||||
cd target/reports
|
||||
BRANCH_FILENAME="${TRAVIS_BRANCH/\//_}"
|
||||
zip -q -r ${BRANCH_FILENAME}-baseline.zip ${BRANCH_FILENAME}/
|
||||
rsync -avh ${BRANCH_FILENAME}-baseline.zip ${PMD_SF_USER}@web.sourceforge.net:/home/frs/project/pmd/pmd-regression-tester/
|
||||
if [ $? -ne 0 ]; then
|
||||
log_error "Error while uploading ${BRANCH_FILENAME}-baseline.zip to sourceforge!"
|
||||
log_error "Please upload manually: https://sourceforge.net/projects/pmd/files/pmd-regression-tester/"
|
||||
else
|
||||
log_success "Successfully uploaded ${BRANCH_FILENAME}-baseline.zip to sourceforge"
|
||||
fi
|
||||
}
|
||||
|
||||
VERSION=$(./mvnw -q -Dexec.executable="echo" -Dexec.args='${project.version}' --non-recursive org.codehaus.mojo:exec-maven-plugin:1.5.0:exec | tail -1)
|
||||
VERSION=$(./mvnw -q -Dexec.executable="echo" -Dexec.args='${project.version}' --non-recursive org.codehaus.mojo:exec-maven-plugin:1.5.0:exec)
|
||||
log_info "Building PMD ${VERSION} on branch ${TRAVIS_BRANCH}"
|
||||
|
||||
MVN_BUILD_FLAGS="-B -V"
|
||||
@ -37,6 +52,11 @@ if travis_isPullRequest; then
|
||||
|
||||
log_info "This is a pull-request build"
|
||||
./mvnw verify $MVN_BUILD_FLAGS
|
||||
(
|
||||
set +e
|
||||
log_info "Running danger"
|
||||
bundle exec danger --verbose
|
||||
)
|
||||
|
||||
elif travis_isPush; then
|
||||
|
||||
@ -77,6 +97,9 @@ elif travis_isPush; then
|
||||
else
|
||||
log_success "Successfully uploaded release_notes.md as ReadMe.md to sourceforge"
|
||||
fi
|
||||
|
||||
upload_baseline
|
||||
|
||||
true
|
||||
)
|
||||
|
||||
|
27
.travis/project-list.xml
Normal file
27
.travis/project-list.xml
Normal file
@ -0,0 +1,27 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<projectlist xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="projectlist_1_0_0.xsd">
|
||||
<description>Standard Projects</description>
|
||||
|
||||
<project>
|
||||
<name>checkstyle</name>
|
||||
<type>git</type>
|
||||
<connection>https://github.com/checkstyle/checkstyle</connection>
|
||||
<tag>checkstyle-8.10</tag>
|
||||
</project>
|
||||
|
||||
<project>
|
||||
<name>spring-framework</name>
|
||||
<type>git</type>
|
||||
<connection>https://github.com/spring-projects/spring-framework</connection>
|
||||
<tag>v5.0.6.RELEASE</tag>
|
||||
</project>
|
||||
|
||||
<!---<project>
|
||||
<name>openjdk10</name>
|
||||
<type>hg</type>
|
||||
<connection>http://hg.openjdk.java.net/jdk10/jdk10/jdk</connection>
|
||||
<webview-url>http://hg.openjdk.java.net/jdk10/jdk10/jdk/file/777356696811</webview-url>
|
||||
</project> -->
|
||||
</projectlist>
|
@ -28,11 +28,16 @@ if [ "${BUILD}" = "deploy" ]; then
|
||||
true
|
||||
)
|
||||
|
||||
# install the gems required for rendering the release notes
|
||||
bundle install --with=release_notes_preprocessing
|
||||
|
||||
# renders, and skips the first 6 lines - the Jekyll front-matter
|
||||
RENDERED_RELEASE_NOTES=$(bundle exec .travis/render_release_notes.rb docs/pages/release_notes.md | tail -n +6)
|
||||
|
||||
# Assumes, the release has already been created by travis github releases provider
|
||||
RELEASE_ID=$(curl -s -H "Authorization: token ${GITHUB_OAUTH_TOKEN}" https://api.github.com/repos/pmd/pmd/releases/tags/pmd_releases/${RELEASE_VERSION}|jq ".id")
|
||||
RELEASE_NAME="PMD ${RELEASE_VERSION} ($(date -u +%d-%B-%Y))"
|
||||
RELEASE_BODY=$(tail -n +6 docs/pages/release_notes.md) # skips the first 6 lines - the heading 'PMD Release Notes'
|
||||
RELEASE_BODY="$RENDERED_RELEASE_NOTES"
|
||||
RELEASE_BODY="${RELEASE_BODY//'\'/\\\\}"
|
||||
RELEASE_BODY="${RELEASE_BODY//$'\r'/}"
|
||||
RELEASE_BODY="${RELEASE_BODY//$'\n'/\\r\\n}"
|
||||
@ -79,6 +84,7 @@ mkdir pmd.github.io
|
||||
git pull --depth=1 origin master
|
||||
log_info "Copying documentation from ../docs/pmd-doc-${RELEASE_VERSION}/ ..."
|
||||
rsync -ah --stats ../docs/pmd-doc-${RELEASE_VERSION}/ pmd-${RELEASE_VERSION}/
|
||||
git status
|
||||
git add pmd-${RELEASE_VERSION}
|
||||
git commit -q -m "Added pmd-${RELEASE_VERSION}"
|
||||
|
||||
@ -87,6 +93,7 @@ mkdir pmd.github.io
|
||||
git add latest
|
||||
git commit -q -m "Copying pmd-${RELEASE_VERSION} to latest"
|
||||
|
||||
log_info "Generating sitemap.xml"
|
||||
../.travis/sitemap_generator.sh > sitemap.xml
|
||||
git add sitemap.xml
|
||||
git commit -q -m "Generated sitemap.xml"
|
||||
@ -103,7 +110,7 @@ mkdir pmd.github.io
|
||||
|
||||
log_info "Uploading the new release to pmd.sourceforge.net which serves as an archive..."
|
||||
|
||||
travis_wait rsync -ah --stats pmd-doc-${VERSION}/ ${PMD_SF_USER}@web.sourceforge.net:/home/project-web/pmd/htdocs/pmd-${RELEASE_VERSION}/
|
||||
travis_wait rsync -ah --stats docs/pmd-doc-${RELEASE_VERSION}/ ${PMD_SF_USER}@web.sourceforge.net:/home/project-web/pmd/htdocs/pmd-${RELEASE_VERSION}/
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
log_error "Uploading documentation to pmd.sourceforge.net failed..."
|
||||
|
42
.travis/render_release_notes.rb
Executable file
42
.travis/render_release_notes.rb
Executable file
@ -0,0 +1,42 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
# Renders the release notes for Github releases,
|
||||
# and prints them to standard output
|
||||
|
||||
# Doesn't trim the header, which is done in shell
|
||||
|
||||
# Args:
|
||||
# ARGV[0] : location of the file to render
|
||||
|
||||
require "liquid"
|
||||
require "safe_yaml"
|
||||
|
||||
# include some custom liquid extensions
|
||||
require_relative "../docs/_plugins/rule_tag"
|
||||
require_relative "../docs/_plugins/custom_filters"
|
||||
|
||||
# explicitly setting safe mode to get rid of the warning
|
||||
SafeYAML::OPTIONS[:default_mode] = :safe
|
||||
|
||||
# START OF THE SCRIPT
|
||||
|
||||
unless ARGV.length == 1 && File.exists?(ARGV[0])
|
||||
print "\e[31m[ERROR] In #{$0}: The first arg must be a valid file name\e[0m"
|
||||
exit 1
|
||||
end
|
||||
|
||||
release_notes_file = ARGV[0]
|
||||
|
||||
liquid_env = {
|
||||
# wrap the config under a "site." namespace because that's how jekyll does it
|
||||
'site' => YAML.load_file("docs/_config.yml"),
|
||||
# This signals the links in {% rule %} tags that they should be rendered as absolute
|
||||
'is_release_notes_processor' => true
|
||||
}
|
||||
|
||||
|
||||
to_render = File.read(release_notes_file)
|
||||
rendered = Liquid::Template.parse(to_render).render(liquid_env)
|
||||
|
||||
|
||||
print(rendered)
|
57
Dangerfile
Normal file
57
Dangerfile
Normal file
@ -0,0 +1,57 @@
|
||||
require 'pmdtester'
|
||||
require 'time'
|
||||
require 'logger'
|
||||
|
||||
@logger = Logger.new(STDOUT)
|
||||
|
||||
def run_pmdtester
|
||||
Dir.chdir('..') do
|
||||
argv = ['-r', './pmd', '-b', "#{ENV['TRAVIS_BRANCH']}", '-p', 'FETCH_HEAD', '-m', 'online', '-a']
|
||||
Process.fork do
|
||||
begin
|
||||
runner = PmdTester::Runner.new(argv)
|
||||
introduce_new_pmd_errors = runner.run
|
||||
warn("The PR may introduce new PMD errors!") if introduce_new_pmd_errors
|
||||
rescue StandardError => e
|
||||
warn("Running pmdtester failed, this message is mainly used to remind the maintainers of PMD.")
|
||||
@logger.error "Running pmdtester failed: #{e.inspect}"
|
||||
exit 1
|
||||
end
|
||||
end
|
||||
Process.wait
|
||||
|
||||
upload_report if $?.success?
|
||||
end
|
||||
end
|
||||
|
||||
def upload_report
|
||||
Dir.chdir('target/reports') do
|
||||
tar_filename = "pr-#{ENV['TRAVIS_PULL_REQUEST']}-diff-report-#{Time.now.strftime("%Y-%m-%dT%H-%M-%SZ")}.tar"
|
||||
unless Dir.exist?('diff/')
|
||||
message("No java rules are changed!", sticky: true)
|
||||
return
|
||||
end
|
||||
|
||||
`tar -cf #{tar_filename} diff/`
|
||||
report_url = `curl -u #{ENV['CHUNK_TOKEN']} -T #{tar_filename} chunk.io`
|
||||
if $?.success?
|
||||
@logger.info "Successfully uploaded #{tar_filename} to chunk.io"
|
||||
|
||||
# set value of sticky to true and the message is kept after new commits are submited to the PR
|
||||
message("Please check the [regression diff report](#{report_url.chomp}/diff/index.html) to make sure that everything is expected", sticky: true)
|
||||
else
|
||||
@logger.error "Error while uploading #{tar_filename} to chunk.io: #{report_url}"
|
||||
warn("Uploading the diff report failed, this message is mainly used to remind the maintainers of PMD.")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Perform regression testing
|
||||
can_merge = github.pr_json['mergeable']
|
||||
if can_merge
|
||||
run_pmdtester
|
||||
else
|
||||
warn("This PR cannot be merged yet.", sticky: false)
|
||||
end
|
||||
|
||||
# vim: syntax=ruby
|
12
Gemfile
Normal file
12
Gemfile
Normal file
@ -0,0 +1,12 @@
|
||||
source 'https://rubygems.org/'
|
||||
|
||||
gem 'pmdtester', '~> 1.0.0.pre.beta3'
|
||||
gem 'danger', '~> 5.6', '>= 5.6'
|
||||
|
||||
# This group is only needed during release (via .travis/release.sh and do-release.sh)
|
||||
group :release_notes_preprocessing do
|
||||
gem 'liquid', '>=4.0.0'
|
||||
gem 'safe_yaml', '>=1.0'
|
||||
end
|
||||
|
||||
# vim: syntax=ruby
|
@ -62,19 +62,20 @@ echo "Press enter to continue..."
|
||||
read
|
||||
|
||||
|
||||
# install bundles needed for rendering release notes
|
||||
bundle install with=release_notes_preprocessing --path vendor/bundle
|
||||
|
||||
|
||||
export RELEASE_VERSION
|
||||
export DEVELOPMENT_VERSION
|
||||
export CURRENT_BRANCH
|
||||
|
||||
RELEASE_RULESET="pmd-core/src/main/resources/rulesets/releases/${RELEASE_VERSION//\./}.xml"
|
||||
|
||||
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 " date: $(date -u +%d-%B-%Y)"
|
||||
echo
|
||||
echo "* Ensure all the new rules are listed in a the proper file:"
|
||||
echo "* Ensure all the new rules are listed in the proper file:"
|
||||
echo " ${RELEASE_RULESET}"
|
||||
echo
|
||||
echo "* Update **../pmd.github.io/_config.yml** to mention the new release"
|
||||
@ -109,18 +110,6 @@ echo
|
||||
echo "Tag has been pushed.... now check travis build: <https://travis-ci.org/pmd/pmd>"
|
||||
echo
|
||||
echo
|
||||
echo "Submit news to SF on <https://sourceforge.net/p/pmd/news/> page. You can use"
|
||||
echo "the following template:"
|
||||
echo
|
||||
cat <<EOF
|
||||
PMD ${RELEASE_VERSION} released
|
||||
|
||||
* Downloads: https://github.com/pmd/pmd/releases/tag/pmd_releases%2F${RELEASE_VERSION}
|
||||
* Documentation: https://pmd.github.io/pmd-${RELEASE_VERSION}/
|
||||
|
||||
And Copy-Paste the release notes
|
||||
EOF
|
||||
echo
|
||||
echo "Press enter to continue..."
|
||||
read
|
||||
|
||||
@ -140,7 +129,7 @@ read
|
||||
|
||||
# update release_notes_old
|
||||
OLD_RELEASE_NOTES=$(tail -n +8 docs/pages/release_notes_old.md)
|
||||
NEW_RELEASE_NOTES=$(tail -n +6 docs/pages/release_notes.md)
|
||||
NEW_RELEASE_NOTES=$(bundle exec .travis/render_release_notes.rb docs/pages/release_notes.md | tail -n +6)
|
||||
echo "$(head -n 7 docs/pages/release_notes_old.md)" > docs/pages/release_notes_old.md
|
||||
echo "$NEW_RELEASE_NOTES" >> docs/pages/release_notes_old.md
|
||||
echo >> docs/pages/release_notes_old.md
|
||||
@ -154,11 +143,11 @@ permalink: pmd_release_notes.html
|
||||
keywords: changelog, release notes
|
||||
---
|
||||
|
||||
## ????? - ${DEVELOPMENT_VERSION}
|
||||
## {{ site.pmd.date }} - {{ site.pmd.version | append_unless: is_release_version, "-SNAPSHOT" }}
|
||||
|
||||
The PMD team is pleased to announce PMD ${DEVELOPMENT_VERSION%-SNAPSHOT}.
|
||||
The PMD team is pleased to announce PMD {{ site.pmd.version }}.
|
||||
|
||||
This is a minor release.
|
||||
This is a {{ site.pmd.release_type }} release.
|
||||
|
||||
### Table Of Contents
|
||||
|
||||
@ -185,15 +174,16 @@ echo
|
||||
echo
|
||||
echo "Verify the new release on github: <https://github.com/pmd/pmd/releases/tag/pmd_releases/${RELEASE_VERSION}>"
|
||||
echo
|
||||
echo "* Submit news to SF on <https://sourceforge.net/p/pmd/news/> page. Use same text as in the email below."
|
||||
echo "* Send out an announcement mail to the mailing list:"
|
||||
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
|
||||
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 "$NEW_RELEASE_NOTES"
|
||||
echo
|
||||
echo
|
||||
echo
|
||||
@ -203,4 +193,3 @@ echo "------------------------------------------"
|
||||
echo
|
||||
|
||||
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
repository: pmd/pmd
|
||||
|
||||
pmd:
|
||||
version: 6.6.0
|
||||
version: 6.7.0
|
||||
date: 2018-??-??
|
||||
release_type: minor
|
||||
|
||||
output: web
|
||||
# this property is useful for conditional filtering of content that is separate from the PDF.
|
||||
|
@ -325,6 +325,9 @@ entries:
|
||||
- title: How PMD works
|
||||
url: /pmd_devdocs_how_pmd_works.html
|
||||
output: web, pdf
|
||||
- title: Pmdtester
|
||||
url: /pmd_devdocs_pmdtester.html
|
||||
output: web, pdf
|
||||
- title: null
|
||||
output: web, pdf
|
||||
subfolders:
|
||||
|
@ -68,6 +68,19 @@ module CustomFilters
|
||||
end
|
||||
end
|
||||
|
||||
# Append the suffix only if the condition argument is truthy
|
||||
def append_if(str, condition, suffix)
|
||||
if condition
|
||||
str + suffix
|
||||
else
|
||||
str
|
||||
end
|
||||
end
|
||||
|
||||
def append_unless(str, condition, suffix)
|
||||
append_if(str, !condition, suffix)
|
||||
end
|
||||
|
||||
def render_markdown(input)
|
||||
if input
|
||||
res = input
|
||||
|
73
docs/_plugins/rule_tag.rb
Normal file
73
docs/_plugins/rule_tag.rb
Normal file
@ -0,0 +1,73 @@
|
||||
|
||||
|
||||
# Tag to reference a rule
|
||||
#
|
||||
# Usage:
|
||||
# {% rule "java/codestyle/LinguisticNaming" %} works from anywhere
|
||||
# If inside the doc page of a ruleset/category, the language and
|
||||
# category segment can be dropped, they're taken to be the same.
|
||||
#
|
||||
# That means rule descriptions can also reference rules e.g. by simply
|
||||
# saying {% rule AvoidFinalLocalVars %} if they're in the same category
|
||||
# This could allow deprecated rule notices to link to the replacement rule
|
||||
|
||||
class RuleTag < Liquid::Tag
|
||||
def initialize(tag_name, rule_ref, tokens)
|
||||
super
|
||||
|
||||
if %r!(?:(?:(\w+)/)?(\w+)/)?(\w+)! =~ rule_ref
|
||||
|
||||
@lang_name = $1
|
||||
@category_name = $2
|
||||
@rule_name = $3
|
||||
|
||||
else
|
||||
fail "Invalid rule reference format"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def render(context)
|
||||
|
||||
|
||||
|
||||
if /pmd_rules_(\w+)_(\w+)\.html/ =~ context["page.permalink"]
|
||||
# If we're in a page describing a ruleset,
|
||||
# omitted language or category are taken to be that of this page
|
||||
@lang_name = @lang_name || $1
|
||||
@category_name = @category_name || $2
|
||||
end
|
||||
|
||||
|
||||
unless @category_name
|
||||
fail "no category for rule reference, and no implicit category name available"
|
||||
end
|
||||
|
||||
unless @lang_name
|
||||
fail "no language for rule reference, and no implicit language name available"
|
||||
end
|
||||
|
||||
|
||||
url_prefix = ""
|
||||
# This is passed from the release notes processing script
|
||||
# When generating links for the release notes, the links should be absolute
|
||||
if context["is_release_notes_processor"]
|
||||
url_prefix = "https://pmd.github.io/pmd-#{context["site.pmd.version"]}/"
|
||||
end
|
||||
|
||||
markup_link(@rule_name, url_prefix + relativelink(@lang_name, @category_name, @rule_name))
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def relativelink(lang, cat, rname)
|
||||
"pmd_rules_#{lang}_#{cat}.html##{rname.downcase}"
|
||||
end
|
||||
|
||||
def markup_link(rname, link)
|
||||
"[`#{rname}`](#{link})"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
Liquid::Template.register_tag('rule', RuleTag)
|
24
docs/pages/pmd/devdocs/pmdtester.md
Normal file
24
docs/pages/pmd/devdocs/pmdtester.md
Normal file
@ -0,0 +1,24 @@
|
||||
---
|
||||
title: Pmdtester
|
||||
tags: [devdocs]
|
||||
permalink: pmd_devdocs_pmdtester.html
|
||||
author: Binguo Bao <djydewang@gmail.com>
|
||||
---
|
||||
|
||||
## Introduction
|
||||
Pmdtester is a regression testing tool that ensures no new problems and unexpected behaviors will be introduced to PMD after fixing an issue.
|
||||
It can also be used to verify, that new rules work as expected.It has been integrated into travis CI and is actually used automatically for PRs.
|
||||
Regression difference reports are commented back to the PR for the reviewer's information e.g. https://github.com/pmd/pmd/pull/1265#issuecomment-408945709
|
||||
|
||||
## Run pmdtester locally
|
||||
**Install pmdtester**
|
||||
|
||||
`gem install pmdtester --pre`
|
||||
|
||||
**Verifying your local changes and generate a diff-report locally**
|
||||
|
||||
`pmdtester -r YOUR_LOCAL_PMD_GIT_REPO_ROOT_DIR -b master -p YOUR_DEVELOPMENT_BRANCH`
|
||||
|
||||
The regression difference report is placed in the `YOUR_WORKING_DIR/target/reports/diff` directory.
|
||||
|
||||
For more documentation on pmdtester, see [README.rdoc](https://github.com/pmd/pmd-regression-tester/blob/master/README.rdoc)
|
@ -25,12 +25,9 @@ Make sure code is up to date and everything is committed and pushed with git:
|
||||
|
||||
### The Release Notes and docs
|
||||
|
||||
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.
|
||||
The date and the version must be updated in `docs/_config.yml`, e.g.
|
||||
|
||||
```
|
||||
pmd:
|
||||
@ -140,6 +137,7 @@ the following template:
|
||||
* 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:
|
||||
|
||||
{%raw%}
|
||||
```
|
||||
---
|
||||
title: PMD Release Notes
|
||||
@ -147,11 +145,11 @@ permalink: pmd_release_notes.html
|
||||
keywords: changelog, release notes
|
||||
---
|
||||
|
||||
## ????? - ${DEVELOPMENT_VERSION}
|
||||
## {{ site.pmd.date }} - {{ site.pmd.version | append_unless: is_release_version, "-SNAPSHOT" }}
|
||||
|
||||
The PMD team is pleased to announce PMD ${DEVELOPMENT_VERSION%-SNAPSHOT}.
|
||||
The PMD team is pleased to announce PMD {{ site.pmd.version }}.
|
||||
|
||||
This is a bug fixing release.
|
||||
This is a {{ site.pmd.release_type }} release.
|
||||
|
||||
### Table Of Contents
|
||||
|
||||
@ -169,6 +167,8 @@ This is a bug fixing release.
|
||||
### External Contributions
|
||||
|
||||
```
|
||||
{%endraw%}
|
||||
|
||||
|
||||
Commit and push
|
||||
|
||||
|
@ -28,7 +28,7 @@ folder: pmd/rules
|
||||
* [JUnit4TestShouldUseBeforeAnnotation](pmd_rules_java_bestpractices.html#junit4testshouldusebeforeannotation): In JUnit 3, the setUp method was used to set up all data entities required in running tests. JUni...
|
||||
* [JUnit4TestShouldUseTestAnnotation](pmd_rules_java_bestpractices.html#junit4testshouldusetestannotation): In JUnit 3, the framework executed all methods which started with the word test as a unit test. I...
|
||||
* [JUnitAssertionsShouldIncludeMessage](pmd_rules_java_bestpractices.html#junitassertionsshouldincludemessage): JUnit assertions should include an informative message - i.e., use the three-argument version of ...
|
||||
* [JUnitTestContainsTooManyAsserts](pmd_rules_java_bestpractices.html#junittestcontainstoomanyasserts): JUnit tests should not contain too many asserts. Many asserts are indicative of a complex test, ...
|
||||
* [JUnitTestContainsTooManyAsserts](pmd_rules_java_bestpractices.html#junittestcontainstoomanyasserts): Unit tests should not contain too many asserts. Many asserts are indicative of a complex test, fo...
|
||||
* [JUnitTestsShouldIncludeAssert](pmd_rules_java_bestpractices.html#junittestsshouldincludeassert): JUnit tests should include at least one assertion. This makes the tests more robust, and using a...
|
||||
* [JUnitUseExpected](pmd_rules_java_bestpractices.html#junituseexpected): In JUnit4, use the @Test(expected) annotation to denote tests that should throw exceptions.
|
||||
* [LooseCoupling](pmd_rules_java_bestpractices.html#loosecoupling): The use of implementation types (i.e., HashSet) as object references limits your ability to use a...
|
||||
@ -79,6 +79,7 @@ folder: pmd/rules
|
||||
* [EmptyMethodInAbstractClassShouldBeAbstract](pmd_rules_java_codestyle.html#emptymethodinabstractclassshouldbeabstract): Empty or auto-generated methods in an abstract class should be tagged as abstract. This helps to ...
|
||||
* [ExtendsObject](pmd_rules_java_codestyle.html#extendsobject): No need to explicitly extend Object.
|
||||
* [FieldDeclarationsShouldBeAtStartOfClass](pmd_rules_java_codestyle.html#fielddeclarationsshouldbeatstartofclass): Fields should be declared at the top of the class, before any method declarations, constructors, ...
|
||||
* [FieldNamingConventions](pmd_rules_java_codestyle.html#fieldnamingconventions): Configurable naming conventions for field declarations. This rule reports variable declarations ...
|
||||
* [ForLoopShouldBeWhileLoop](pmd_rules_java_codestyle.html#forloopshouldbewhileloop): Some for loops can be simplified to while loops, this makes them more concise.
|
||||
* [ForLoopsMustUseBraces](pmd_rules_java_codestyle.html#forloopsmustusebraces): <span style="border-radius: 0.25em; color: #fff; padding: 0.2em 0.6em 0.3em; display: inline; background-color: #d9534f; font-size: 75%;">Deprecated</span> Avoid using 'for' statements without using curly braces. If the code formatting or indentation is...
|
||||
* [FormalParameterNamingConventions](pmd_rules_java_codestyle.html#formalparameternamingconventions): Configurable naming conventions for formal parameters of methods and lambdas. This rul...
|
||||
@ -86,6 +87,7 @@ folder: pmd/rules
|
||||
* [IdenticalCatchBranches](pmd_rules_java_codestyle.html#identicalcatchbranches): Identical 'catch' branches use up vertical space and increase the complexity of code without ...
|
||||
* [IfElseStmtsMustUseBraces](pmd_rules_java_codestyle.html#ifelsestmtsmustusebraces): <span style="border-radius: 0.25em; color: #fff; padding: 0.2em 0.6em 0.3em; display: inline; background-color: #d9534f; font-size: 75%;">Deprecated</span> Avoid using if..else statements without using surrounding braces. If the code formatting or inden...
|
||||
* [IfStmtsMustUseBraces](pmd_rules_java_codestyle.html#ifstmtsmustusebraces): <span style="border-radius: 0.25em; color: #fff; padding: 0.2em 0.6em 0.3em; display: inline; background-color: #d9534f; font-size: 75%;">Deprecated</span> Avoid using if statements without using braces to surround the code block. If the code formatting...
|
||||
* [LinguisticNaming](pmd_rules_java_codestyle.html#linguisticnaming): This rule finds Linguistic Naming Antipatterns. It checks for fields, that are named, as if they ...
|
||||
* [LocalHomeNamingConvention](pmd_rules_java_codestyle.html#localhomenamingconvention): The Local Home interface of a Session EJB should be suffixed by 'LocalHome'.
|
||||
* [LocalInterfaceSessionNamingConvention](pmd_rules_java_codestyle.html#localinterfacesessionnamingconvention): The Local Interface of a Session EJB should be suffixed by 'Local'.
|
||||
* [LocalVariableCouldBeFinal](pmd_rules_java_codestyle.html#localvariablecouldbefinal): A local variable assigned only once can be declared final.
|
||||
|
@ -456,8 +456,8 @@ through the @RunWith(Suite.class) annotation.
|
||||
**This rule is defined by the following XPath expression:**
|
||||
``` xpath
|
||||
//ClassOrInterfaceBodyDeclaration[MethodDeclaration/MethodDeclarator[@Image='suite']]
|
||||
[MethodDeclaration/ResultType/Type/ReferenceType/ClassOrInterfaceType[@Image='Test' or @Image = 'junit.framework.Test']]
|
||||
[not(MethodDeclaration/Block//ClassOrInterfaceType[@Image='JUnit4TestAdapter'])]
|
||||
[MethodDeclaration/ResultType/Type/ReferenceType/ClassOrInterfaceType[pmd-java:typeIs('junit.framework.Test')]]
|
||||
[not(MethodDeclaration/Block//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.JUnit4TestAdapter')])]
|
||||
```
|
||||
|
||||
**Example(s):**
|
||||
@ -488,13 +488,18 @@ public class GoodTest {
|
||||
**Priority:** Medium (3)
|
||||
|
||||
In JUnit 3, the tearDown method was used to clean up all data entities required in running tests.
|
||||
JUnit 4 skips the tearDown method and executes all methods annotated with @After after running each test
|
||||
JUnit 4 skips the tearDown method and executes all methods annotated with @After after running each test.
|
||||
JUnit 5 introduced @AfterEach and @AfterAll annotations to execute methods after each test or after all tests in the class, respectively.
|
||||
|
||||
**This rule is defined by the following XPath expression:**
|
||||
``` xpath
|
||||
//CompilationUnit[not(ImportDeclaration/Name[starts-with(@Image, "org.testng")])]
|
||||
//ClassOrInterfaceBodyDeclaration[MethodDeclaration/MethodDeclarator[@Image='tearDown']]
|
||||
[count(Annotation//Name[@Image='After'])=0]
|
||||
//ClassOrInterfaceBodyDeclaration
|
||||
[MethodDeclaration/MethodDeclarator[@Image='tearDown']]
|
||||
[count(Annotation//Name[
|
||||
pmd-java:typeIs('org.junit.After')
|
||||
or pmd-java:typeIs('org.junit.jupiter.api.AfterEach')
|
||||
or pmd-java:typeIs('org.junit.jupiter.api.AfterAll')
|
||||
or pmd-java:typeIs('org.testng.annotations.AfterMethod')])=0]
|
||||
```
|
||||
|
||||
**Example(s):**
|
||||
@ -524,13 +529,18 @@ public class MyTest2 {
|
||||
**Priority:** Medium (3)
|
||||
|
||||
In JUnit 3, the setUp method was used to set up all data entities required in running tests.
|
||||
JUnit 4 skips the setUp method and executes all methods annotated with @Before before all tests
|
||||
JUnit 4 skips the setUp method and executes all methods annotated with @Before before all tests.
|
||||
JUnit 5 introduced @BeforeEach and @BeforeAll annotations to execute methods before each test or before all tests in the class, respectively.
|
||||
|
||||
**This rule is defined by the following XPath expression:**
|
||||
``` xpath
|
||||
//CompilationUnit[not(ImportDeclaration/Name[starts-with(@Image, "org.testng")])]
|
||||
//ClassOrInterfaceBodyDeclaration[MethodDeclaration/MethodDeclarator[@Image='setUp']]
|
||||
[count(Annotation//Name[@Image='Before'])=0]
|
||||
//ClassOrInterfaceBodyDeclaration
|
||||
[MethodDeclaration/MethodDeclarator[@Image='setUp']]
|
||||
[count(Annotation//Name[
|
||||
pmd-java:typeIs('org.junit.Before')
|
||||
or pmd-java:typeIs('org.junit.jupiter.api.BeforeEach')
|
||||
or pmd-java:typeIs('org.junit.jupiter.api.BeforeAll')
|
||||
or pmd-java:typeIs('org.testng.annotations.BeforeMethod')])=0]
|
||||
```
|
||||
|
||||
**Example(s):**
|
||||
@ -561,6 +571,7 @@ public class MyTest2 {
|
||||
|
||||
In JUnit 3, the framework executed all methods which started with the word test as a unit test.
|
||||
In JUnit 4, only methods annotated with the @Test annotation are executed.
|
||||
In JUnit 5, one of the following annotations should be used for tests: @Test, @RepeatedTest, @TestFactory, @TestTemplate or @ParameterizedTest.
|
||||
|
||||
**This rule is defined by the following XPath expression:**
|
||||
``` xpath
|
||||
@ -569,7 +580,12 @@ In JUnit 4, only methods annotated with the @Test annotation are executed.
|
||||
or ExtendsList/ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')]]
|
||||
|
||||
/ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration[MethodDeclaration[@Public=true()]/MethodDeclarator[starts-with(@Image, 'test')]]
|
||||
[not(Annotation//Name[pmd-java:typeIs('org.junit.Test')])]
|
||||
[not(Annotation//Name[
|
||||
pmd-java:typeIs('org.junit.Test')
|
||||
or pmd-java:typeIs('org.junit.jupiter.api.Test') or pmd-java:typeIs('org.junit.jupiter.api.RepeatedTest')
|
||||
or pmd-java:typeIs('org.junit.jupiter.api.TestFactory') or pmd-java:typeIs('org.junit.jupiter.api.TestTemplate')
|
||||
or pmd-java:typeIs('org.junit.jupiter.params.ParameterizedTest')
|
||||
])]
|
||||
```
|
||||
|
||||
**Example(s):**
|
||||
@ -633,13 +649,24 @@ public class Foo extends TestCase {
|
||||
|
||||
**Priority:** Medium (3)
|
||||
|
||||
JUnit tests should not contain too many asserts. Many asserts are indicative of a complex test, for which
|
||||
it is harder to verify correctness. Consider breaking the test scenario into multiple, shorter test scenarios.
|
||||
Unit tests should not contain too many asserts. Many asserts are indicative of a complex test, for which
|
||||
it is harder to verify correctness. Consider breaking the test scenario into multiple, shorter test scenarios.
|
||||
Customize the maximum number of assertions used by this Rule to suit your needs.
|
||||
|
||||
This rule checks for JUnit4, JUnit5 and TestNG Tests, as well as methods starting with "test".
|
||||
|
||||
**This rule is defined by the following XPath expression:**
|
||||
``` xpath
|
||||
//MethodDeclarator[(@Image[fn:matches(.,'^test')] or ../../Annotation/MarkerAnnotation/Name[@Image='Test']) and count(..//PrimaryPrefix/Name[@Image[fn:matches(.,'^assert')]]) > $maximumAsserts]
|
||||
//MethodDeclarator[@Image[fn:matches(.,'^test')] or ../../Annotation/MarkerAnnotation/Name[
|
||||
pmd-java:typeIs('org.junit.Test')
|
||||
or pmd-java:typeIs('org.junit.jupiter.api.Test')
|
||||
or pmd-java:typeIs('org.junit.jupiter.api.RepeatedTest')
|
||||
or pmd-java:typeIs('org.junit.jupiter.api.TestFactory')
|
||||
or pmd-java:typeIs('org.junit.jupiter.api.TestTemplate')
|
||||
or pmd-java:typeIs('org.junit.jupiter.params.ParameterizedTest')
|
||||
or pmd-java:typeIs('org.testng.annotations.Test')
|
||||
]]
|
||||
[count(..//PrimaryPrefix/Name[@Image[fn:matches(.,'^assert')]]) > $maximumAsserts]
|
||||
```
|
||||
|
||||
**Example(s):**
|
||||
@ -1312,7 +1339,14 @@ This rule detects JUnit assertions in object equality. These assertions should b
|
||||
PrimarySuffix/Arguments/ArgumentList/Expression/PrimaryExpression/PrimaryPrefix/Name
|
||||
[ends-with(@Image, '.equals')]
|
||||
]
|
||||
[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')] or //MarkerAnnotation/Name[pmd-java:typeIs('org.junit.Test')]]]
|
||||
[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')]
|
||||
or //MarkerAnnotation/Name[
|
||||
pmd-java:typeIs('org.junit.Test')
|
||||
or pmd-java:typeIs('org.junit.jupiter.api.Test') or pmd-java:typeIs('org.junit.jupiter.api.RepeatedTest')
|
||||
or pmd-java:typeIs('org.junit.jupiter.api.TestFactory') or pmd-java:typeIs('org.junit.jupiter.api.TestTemplate')
|
||||
or pmd-java:typeIs('org.junit.jupiter.params.ParameterizedTest')
|
||||
]
|
||||
]]
|
||||
```
|
||||
|
||||
**Example(s):**
|
||||
@ -1350,7 +1384,14 @@ more specific methods, like assertNull, assertNotNull.
|
||||
Expression/EqualityExpression/PrimaryExpression/PrimaryPrefix/Literal/NullLiteral
|
||||
]
|
||||
]
|
||||
[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')] or //MarkerAnnotation/Name[pmd-java:typeIs('org.junit.Test')]]]
|
||||
[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')]
|
||||
or //MarkerAnnotation/Name[
|
||||
pmd-java:typeIs('org.junit.Test')
|
||||
or pmd-java:typeIs('org.junit.jupiter.api.Test') or pmd-java:typeIs('org.junit.jupiter.api.RepeatedTest')
|
||||
or pmd-java:typeIs('org.junit.jupiter.api.TestFactory') or pmd-java:typeIs('org.junit.jupiter.api.TestTemplate')
|
||||
or pmd-java:typeIs('org.junit.jupiter.params.ParameterizedTest')
|
||||
]
|
||||
]]
|
||||
```
|
||||
|
||||
**Example(s):**
|
||||
@ -1390,7 +1431,14 @@ by more specific methods, like assertSame, assertNotSame.
|
||||
[PrimarySuffix/Arguments
|
||||
/ArgumentList/Expression
|
||||
/EqualityExpression[count(.//NullLiteral) = 0]]
|
||||
[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')] or //MarkerAnnotation/Name[pmd-java:typeIs('org.junit.Test')]]]
|
||||
[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')]
|
||||
or //MarkerAnnotation/Name[
|
||||
pmd-java:typeIs('org.junit.Test')
|
||||
or pmd-java:typeIs('org.junit.jupiter.api.Test') or pmd-java:typeIs('org.junit.jupiter.api.RepeatedTest')
|
||||
or pmd-java:typeIs('org.junit.jupiter.api.TestFactory') or pmd-java:typeIs('org.junit.jupiter.api.TestTemplate')
|
||||
or pmd-java:typeIs('org.junit.jupiter.params.ParameterizedTest')
|
||||
]
|
||||
]]
|
||||
```
|
||||
|
||||
**Example(s):**
|
||||
|
@ -5,7 +5,7 @@ permalink: pmd_rules_java_codestyle.html
|
||||
folder: pmd/rules/java
|
||||
sidebaractiveurl: /pmd_rules_java.html
|
||||
editmepath: ../pmd-java/src/main/resources/category/java/codestyle.xml
|
||||
keywords: Code Style, AbstractNaming, AtLeastOneConstructor, AvoidDollarSigns, AvoidFinalLocalVariable, AvoidPrefixingMethodParameters, AvoidProtectedFieldInFinalClass, AvoidProtectedMethodInFinalClassNotExtending, AvoidUsingNativeCode, BooleanGetMethodName, CallSuperInConstructor, ClassNamingConventions, CommentDefaultAccessModifier, ConfusingTernary, ControlStatementBraces, DefaultPackage, DontImportJavaLang, DuplicateImports, EmptyMethodInAbstractClassShouldBeAbstract, ExtendsObject, FieldDeclarationsShouldBeAtStartOfClass, ForLoopShouldBeWhileLoop, ForLoopsMustUseBraces, FormalParameterNamingConventions, GenericsNaming, IdenticalCatchBranches, IfElseStmtsMustUseBraces, IfStmtsMustUseBraces, LocalHomeNamingConvention, LocalInterfaceSessionNamingConvention, LocalVariableCouldBeFinal, LocalVariableNamingConventions, LongVariable, MDBAndSessionBeanNamingConvention, MethodArgumentCouldBeFinal, MethodNamingConventions, MIsLeadingVariableName, NoPackage, OnlyOneReturn, PackageCase, PrematureDeclaration, RemoteInterfaceNamingConvention, RemoteSessionInterfaceNamingConvention, ShortClassName, ShortMethodName, ShortVariable, SuspiciousConstantFieldName, TooManyStaticImports, UnnecessaryAnnotationValueElement, UnnecessaryConstructor, UnnecessaryFullyQualifiedName, UnnecessaryLocalBeforeReturn, UnnecessaryModifier, UnnecessaryReturn, UselessParentheses, UselessQualifiedThis, VariableNamingConventions, WhileLoopsMustUseBraces
|
||||
keywords: Code Style, AbstractNaming, AtLeastOneConstructor, AvoidDollarSigns, AvoidFinalLocalVariable, AvoidPrefixingMethodParameters, AvoidProtectedFieldInFinalClass, AvoidProtectedMethodInFinalClassNotExtending, AvoidUsingNativeCode, BooleanGetMethodName, CallSuperInConstructor, ClassNamingConventions, CommentDefaultAccessModifier, ConfusingTernary, ControlStatementBraces, DefaultPackage, DontImportJavaLang, DuplicateImports, EmptyMethodInAbstractClassShouldBeAbstract, ExtendsObject, FieldDeclarationsShouldBeAtStartOfClass, FieldNamingConventions, ForLoopShouldBeWhileLoop, ForLoopsMustUseBraces, FormalParameterNamingConventions, GenericsNaming, IdenticalCatchBranches, IfElseStmtsMustUseBraces, IfStmtsMustUseBraces, LinguisticNaming, LocalHomeNamingConvention, LocalInterfaceSessionNamingConvention, LocalVariableCouldBeFinal, LocalVariableNamingConventions, LongVariable, MDBAndSessionBeanNamingConvention, MethodArgumentCouldBeFinal, MethodNamingConventions, MIsLeadingVariableName, NoPackage, OnlyOneReturn, PackageCase, PrematureDeclaration, RemoteInterfaceNamingConvention, RemoteSessionInterfaceNamingConvention, ShortClassName, ShortMethodName, ShortVariable, SuspiciousConstantFieldName, TooManyStaticImports, UnnecessaryAnnotationValueElement, UnnecessaryConstructor, UnnecessaryFullyQualifiedName, UnnecessaryLocalBeforeReturn, UnnecessaryModifier, UnnecessaryReturn, UselessParentheses, UselessQualifiedThis, VariableNamingConventions, WhileLoopsMustUseBraces
|
||||
language: Java
|
||||
---
|
||||
## AbstractNaming
|
||||
@ -405,11 +405,11 @@ public class Éléphant {}
|
||||
|
||||
|Name|Default Value|Description|Multivalued|
|
||||
|----|-------------|-----------|-----------|
|
||||
|classPattern|[A-Z][a-zA-Z0-9]+|Regex which applies to concrete class names|no|
|
||||
|abstractClassPattern|[A-Z][a-zA-Z0-9]+|Regex which applies to abstract class names|no|
|
||||
|interfacePattern|[A-Z][a-zA-Z0-9]+|Regex which applies to interface names|no|
|
||||
|enumPattern|[A-Z][a-zA-Z0-9]+|Regex which applies to enum names|no|
|
||||
|annotationPattern|[A-Z][a-zA-Z0-9]+|Regex which applies to annotation names|no|
|
||||
|classPattern|[A-Z][a-zA-Z0-9]*|Regex which applies to concrete class names|no|
|
||||
|abstractClassPattern|[A-Z][a-zA-Z0-9]*|Regex which applies to abstract class names|no|
|
||||
|interfacePattern|[A-Z][a-zA-Z0-9]*|Regex which applies to interface names|no|
|
||||
|enumPattern|[A-Z][a-zA-Z0-9]*|Regex which applies to enum names|no|
|
||||
|annotationPattern|[A-Z][a-zA-Z0-9]*|Regex which applies to annotation names|no|
|
||||
|utilityClassPattern|[A-Z][a-zA-Z0-9]+(Utils?\|Helper)|Regex which applies to utility class names|no|
|
||||
|
||||
**Use this rule by referencing it:**
|
||||
@ -756,6 +756,58 @@ public class HelloWorldBean {
|
||||
<rule ref="category/java/codestyle.xml/FieldDeclarationsShouldBeAtStartOfClass" />
|
||||
```
|
||||
|
||||
## FieldNamingConventions
|
||||
|
||||
**Since:** PMD 6.7.0
|
||||
|
||||
**Priority:** High (1)
|
||||
|
||||
Configurable naming conventions for field declarations. This rule reports variable declarations
|
||||
which do not match the regex that applies to their specific kind ---e.g. constants (static final),
|
||||
enum constant, final field. Each regex can be configured through properties.
|
||||
|
||||
By default this rule uses the standard Java naming convention (Camel case), and uses the ALL_UPPER
|
||||
convention for constants and enum constants.
|
||||
|
||||
**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.codestyle.FieldNamingConventionsRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/FieldNamingConventionsRule.java)
|
||||
|
||||
**Example(s):**
|
||||
|
||||
``` java
|
||||
class Foo {
|
||||
int myField = 1; // This is in camel case, so it's ok
|
||||
int my_Field = 1; // This contains an underscore, it's not ok by default
|
||||
// but you may allow it, or even require the "my_" prefix
|
||||
|
||||
final int FinalField = 1; // you may configure a different convention for final fields,
|
||||
// e.g. here PascalCase: [A-Z][a-zA-Z0-9]*
|
||||
|
||||
interface Interface {
|
||||
double PI = 3.14; // interface "fields" use the constantPattern property
|
||||
}
|
||||
|
||||
enum AnEnum {
|
||||
ORG, NET, COM; // These use a separate property but are set to ALL_UPPER by default
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**This rule has the following properties:**
|
||||
|
||||
|Name|Default Value|Description|Multivalued|
|
||||
|----|-------------|-----------|-----------|
|
||||
|publicConstantPattern|[A-Z][A-Z_0-9]*|Regex which applies to public constant names|no|
|
||||
|constantPattern|[A-Z][A-Z_0-9]*|Regex which applies to non-public static final field names|no|
|
||||
|enumConstantPattern|[A-Z][A-Z_0-9]*|Regex which applies to enum constant names|no|
|
||||
|finalFieldPattern|[a-z][a-zA-Z0-9]*|Regex which applies to final field names|no|
|
||||
|staticFieldPattern|[a-z][a-zA-Z0-9]*|Regex which applies to static field names|no|
|
||||
|defaultFieldPattern|[a-z][a-zA-Z0-9]*|Regex which applies to field names|no|
|
||||
|
||||
**Use this rule by referencing it:**
|
||||
``` xml
|
||||
<rule ref="category/java/codestyle.xml/FieldNamingConventions" />
|
||||
```
|
||||
|
||||
## ForLoopShouldBeWhileLoop
|
||||
|
||||
**Since:** PMD 1.02
|
||||
@ -860,10 +912,10 @@ class Foo {
|
||||
|
||||
|Name|Default Value|Description|Multivalued|
|
||||
|----|-------------|-----------|-----------|
|
||||
|methodParameterPattern|[a-z][a-zA-Z0-9]+|Regex which applies to formal parameter names|no|
|
||||
|finalMethodParameterPattern|[a-z][a-zA-Z0-9]+|Regex which applies to final formal parameter names|no|
|
||||
|lambdaParameterPattern|[a-z][a-zA-Z0-9]+|Regex which applies to inferred-type lambda parameter names|no|
|
||||
|explicitLambdaParameterPattern|[a-z][a-zA-Z0-9]+|Regex which applies to explicitly-typed lambda parameter names|no|
|
||||
|methodParameterPattern|[a-z][a-zA-Z0-9]*|Regex which applies to formal parameter names|no|
|
||||
|finalMethodParameterPattern|[a-z][a-zA-Z0-9]*|Regex which applies to final formal parameter names|no|
|
||||
|lambdaParameterPattern|[a-z][a-zA-Z0-9]*|Regex which applies to inferred-type lambda parameter names|no|
|
||||
|explicitLambdaParameterPattern|[a-z][a-zA-Z0-9]*|Regex which applies to explicitly-typed lambda parameter names|no|
|
||||
|
||||
**Use this rule by referencing it:**
|
||||
``` xml
|
||||
@ -1020,6 +1072,87 @@ if (foo) { // preferred approach
|
||||
<rule ref="category/java/codestyle.xml/IfStmtsMustUseBraces" />
|
||||
```
|
||||
|
||||
## LinguisticNaming
|
||||
|
||||
**Since:** PMD 6.7.0
|
||||
|
||||
**Priority:** Medium (3)
|
||||
|
||||
This rule finds Linguistic Naming Antipatterns. It checks for fields, that are named, as if they should
|
||||
be boolean but have a different type. It also checks for methods, that according to their name, should
|
||||
return a boolean, but don't. Further, it checks, that getters return something and setters won't.
|
||||
Finally, it checks that methods, that start with "to" - so called transform methods - actually return
|
||||
something, since according to their name, they should convert or transform one object into another.
|
||||
There is additionally an option, to check for methods that contain "To" in their name - which are
|
||||
also transform methods. However, this is disabled by default, since this detection is prone to
|
||||
false positives.
|
||||
|
||||
For more information, see [Linguistic Antipatterns - What They Are and How
|
||||
Developers Perceive Them](https://doi.org/10.1007/s10664-014-9350-8).
|
||||
|
||||
**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.codestyle.LinguisticNamingRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/LinguisticNamingRule.java)
|
||||
|
||||
**Example(s):**
|
||||
|
||||
``` java
|
||||
public class LinguisticNaming {
|
||||
int isValid; // the field name indicates a boolean, but it is an int.
|
||||
boolean isTrue; // correct type of the field
|
||||
|
||||
void myMethod() {
|
||||
int hasMoneyLocal; // the local variable name indicates a boolean, but it is an int.
|
||||
boolean hasSalaryLocal; // correct naming and type
|
||||
}
|
||||
|
||||
// the name of the method indicates, it is a boolean, but the method returns an int.
|
||||
int isValid() {
|
||||
return 1;
|
||||
}
|
||||
// correct naming and return type
|
||||
boolean isSmall() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// the name indicates, this is a setter, but it returns something
|
||||
int setName() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// the name indicates, this is a getter, but it doesn't return anything
|
||||
void getName() {
|
||||
// nothing to return?
|
||||
}
|
||||
|
||||
// the name indicates, it transforms an object and should return the result
|
||||
void toDataType() {
|
||||
// nothing to return?
|
||||
}
|
||||
// the name indicates, it transforms an object and should return the result
|
||||
void grapeToWine() {
|
||||
// nothing to return?
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**This rule has the following properties:**
|
||||
|
||||
|Name|Default Value|Description|Multivalued|
|
||||
|----|-------------|-----------|-----------|
|
||||
|booleanFieldPrefixes|is \| has \| can \| have \| will \| should|the prefixes of fields and variables that indicate boolean|yes. Delimiter is '\|'.|
|
||||
|checkVariables|true|Check local variable names and types for inconsistent naming|no|
|
||||
|checkFields|true|Check field names and types for inconsistent naming|no|
|
||||
|booleanMethodPrefixes|is \| has \| can \| have \| will \| should|the prefixes of methods that return boolean|yes. Delimiter is '\|'.|
|
||||
|checkPrefixedTransformMethods|true|Check return type of methods whose names start with 'to'|no|
|
||||
|checkTransformMethods|false|Check return type of methods which contain 'To' in their name|no|
|
||||
|checkSetters|true|Check return type of setters|no|
|
||||
|checkGetters|true|Check return type of getters|no|
|
||||
|checkBooleanMethod|true|Check method names and types for inconsistent naming|no|
|
||||
|
||||
**Use this rule by referencing it:**
|
||||
``` xml
|
||||
<rule ref="category/java/codestyle.xml/LinguisticNaming" />
|
||||
```
|
||||
|
||||
## LocalHomeNamingConvention
|
||||
|
||||
**Since:** PMD 4.0
|
||||
@ -1157,9 +1290,9 @@ class Foo {
|
||||
|
||||
|Name|Default Value|Description|Multivalued|
|
||||
|----|-------------|-----------|-----------|
|
||||
|localVarPattern|[a-z][a-zA-Z0-9]+|Regex which applies to non-final local variable names|no|
|
||||
|finalVarPattern|[a-z][a-zA-Z0-9]+|Regex which applies to final local variable names|no|
|
||||
|catchParameterPattern|[a-z][a-zA-Z0-9]+|Regex which applies to exception block parameter names|no|
|
||||
|localVarPattern|[a-z][a-zA-Z0-9]*|Regex which applies to non-final local variable names|no|
|
||||
|finalVarPattern|[a-z][a-zA-Z0-9]*|Regex which applies to final local variable names|no|
|
||||
|catchParameterPattern|[a-z][a-zA-Z0-9]*|Regex which applies to exception block parameter names|no|
|
||||
|
||||
**Use this rule by referencing it:**
|
||||
``` xml
|
||||
@ -1298,11 +1431,11 @@ public class Foo {
|
||||
|Name|Default Value|Description|Multivalued|
|
||||
|----|-------------|-----------|-----------|
|
||||
|checkNativeMethods|true|<span style="border-radius: 0.25em; color: #fff; padding: 0.2em 0.6em 0.3em; display: inline; background-color: #d9534f; font-size: 75%;">Deprecated</span> Check native methods|no|
|
||||
|methodPattern|[a-z][a-zA-Z0-9]+|Regex which applies to instance method names|no|
|
||||
|staticPattern|[a-z][a-zA-Z0-9]+|Regex which applies to static method names|no|
|
||||
|nativePattern|[a-z][a-zA-Z0-9]+|Regex which applies to native method names|no|
|
||||
|methodPattern|[a-z][a-zA-Z0-9]*|Regex which applies to instance method names|no|
|
||||
|staticPattern|[a-z][a-zA-Z0-9]*|Regex which applies to static method names|no|
|
||||
|nativePattern|[a-z][a-zA-Z0-9]*|Regex which applies to native method names|no|
|
||||
|junit3TestPattern|test[A-Z0-9][a-zA-Z0-9]*|Regex which applies to JUnit 3 test method names|no|
|
||||
|junit4TestPattern|[a-z][a-zA-Z0-9]+|Regex which applies to JUnit 4 test method names|no|
|
||||
|junit4TestPattern|[a-z][a-zA-Z0-9]*|Regex which applies to JUnit 4 test method names|no|
|
||||
|
||||
**Use this rule by referencing it:**
|
||||
``` xml
|
||||
@ -1936,6 +2069,7 @@ Useless parentheses should be removed.
|
||||
[not(./CastExpression)]
|
||||
[not(./ConditionalExpression)]
|
||||
[not(./AdditiveExpression)]
|
||||
[not(./AssignmentOperator)]
|
||||
|
|
||||
//Expression[not(parent::PrimaryPrefix)]/PrimaryExpression[count(*)=1]
|
||||
/PrimaryPrefix/Expression
|
||||
|
@ -23,7 +23,7 @@ protected constructor in order to prevent instantiation than make the class misl
|
||||
//ClassOrInterfaceDeclaration
|
||||
[@Abstract = 'true']
|
||||
[count(//MethodDeclaration) + count(//ConstructorDeclaration) = 0]
|
||||
[not(../Annotation/MarkerAnnotation/Name[typeIs('com.google.auto.value.AutoValue')])]
|
||||
[not(../Annotation/MarkerAnnotation/Name[pmd-java:typeIs('com.google.auto.value.AutoValue')])]
|
||||
```
|
||||
|
||||
**Example(s):**
|
||||
@ -259,13 +259,13 @@ Exception, or Error, use a subclassed exception or error instead.
|
||||
``` xpath
|
||||
//ThrowStatement//AllocationExpression
|
||||
/ClassOrInterfaceType[
|
||||
typeIsExactly('java.lang.Throwable')
|
||||
pmd-java:typeIsExactly('java.lang.Throwable')
|
||||
or
|
||||
typeIsExactly('java.lang.Exception')
|
||||
pmd-java:typeIsExactly('java.lang.Exception')
|
||||
or
|
||||
typeIsExactly('java.lang.Error')
|
||||
pmd-java:typeIsExactly('java.lang.Error')
|
||||
or
|
||||
typeIsExactly('java.lang.RuntimeException')
|
||||
pmd-java:typeIsExactly('java.lang.RuntimeException')
|
||||
]
|
||||
```
|
||||
|
||||
@ -518,7 +518,7 @@ Errors are system exceptions. Do not extend them.
|
||||
**This rule is defined by the following XPath expression:**
|
||||
``` xpath
|
||||
//ClassOrInterfaceDeclaration/ExtendsList/ClassOrInterfaceType
|
||||
[typeIs('java.lang.Error')]
|
||||
[pmd-java:typeIs('java.lang.Error')]
|
||||
```
|
||||
|
||||
**Example(s):**
|
||||
@ -1406,7 +1406,14 @@ PrimaryExpression/PrimarySuffix/Arguments/ArgumentList
|
||||
/Expression/UnaryExpressionNotPlusMinus[@Image='!']
|
||||
/PrimaryExpression/PrimaryPrefix
|
||||
]
|
||||
[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')] or //MarkerAnnotation/Name[pmd-java:typeIs('org.junit.Test')]]]
|
||||
[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')]
|
||||
or //MarkerAnnotation/Name[
|
||||
pmd-java:typeIs('org.junit.Test')
|
||||
or pmd-java:typeIs('org.junit.jupiter.api.Test') or pmd-java:typeIs('org.junit.jupiter.api.RepeatedTest')
|
||||
or pmd-java:typeIs('org.junit.jupiter.api.TestFactory') or pmd-java:typeIs('org.junit.jupiter.api.TestTemplate')
|
||||
or pmd-java:typeIs('org.junit.jupiter.params.ParameterizedTest')
|
||||
]
|
||||
]]
|
||||
```
|
||||
|
||||
**Example(s):**
|
||||
|
@ -132,7 +132,7 @@ and unintentional empty constructors.
|
||||
``` xpath
|
||||
//ConstructorDeclaration[@Private='false']
|
||||
[count(BlockStatement) = 0 and ($ignoreExplicitConstructorInvocation = 'true' or not(ExplicitConstructorInvocation)) and @containsComment = 'false']
|
||||
[not(../Annotation/MarkerAnnotation/Name[typeIs('javax.inject.Inject')])]
|
||||
[not(../Annotation/MarkerAnnotation/Name[pmd-java:typeIs('javax.inject.Inject')])]
|
||||
```
|
||||
|
||||
**Example(s):**
|
||||
|
@ -796,9 +796,9 @@ Super should be called at the start of the method
|
||||
/Block[not(
|
||||
(BlockStatement[1]/Statement/StatementExpression/PrimaryExpression[./PrimaryPrefix[@SuperModifier='true']]/PrimarySuffix[@Image= ancestor::MethodDeclaration/MethodDeclarator/@Image]))]
|
||||
[ancestor::ClassOrInterfaceDeclaration[ExtendsList/ClassOrInterfaceType[
|
||||
typeIs('android.app.Activity') or
|
||||
typeIs('android.app.Application') or
|
||||
typeIs('android.app.Service')
|
||||
pmd-java:typeIs('android.app.Activity') or
|
||||
pmd-java:typeIs('android.app.Application') or
|
||||
pmd-java:typeIs('android.app.Service')
|
||||
]]]
|
||||
```
|
||||
|
||||
@ -839,9 +839,9 @@ Super should be called at the end of the method
|
||||
/Block/BlockStatement[last()]
|
||||
[not(Statement/StatementExpression/PrimaryExpression[./PrimaryPrefix[@SuperModifier='true']]/PrimarySuffix[@Image= ancestor::MethodDeclaration/MethodDeclarator/@Image])]
|
||||
[ancestor::ClassOrInterfaceDeclaration[ExtendsList/ClassOrInterfaceType[
|
||||
typeIs('android.app.Activity') or
|
||||
typeIs('android.app.Application') or
|
||||
typeIs('android.app.Service')
|
||||
pmd-java:typeIs('android.app.Activity') or
|
||||
pmd-java:typeIs('android.app.Application') or
|
||||
pmd-java:typeIs('android.app.Service')
|
||||
]]]
|
||||
```
|
||||
|
||||
@ -2176,7 +2176,14 @@ Some JUnit framework methods are easy to misspell.
|
||||
or (not(@Image = 'tearDown')
|
||||
and translate(@Image, 'TEARdOWN', 'tearDown') = 'tearDown')]
|
||||
[FormalParameters[count(*) = 0]]
|
||||
[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')] or //MarkerAnnotation/Name[pmd-java:typeIs('org.junit.Test')]]]
|
||||
[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')]
|
||||
or //MarkerAnnotation/Name[
|
||||
pmd-java:typeIs('org.junit.Test')
|
||||
or pmd-java:typeIs('org.junit.jupiter.api.Test') or pmd-java:typeIs('org.junit.jupiter.api.RepeatedTest')
|
||||
or pmd-java:typeIs('org.junit.jupiter.api.TestFactory') or pmd-java:typeIs('org.junit.jupiter.api.TestTemplate')
|
||||
or pmd-java:typeIs('org.junit.jupiter.params.ParameterizedTest')
|
||||
]
|
||||
]]
|
||||
```
|
||||
|
||||
**Example(s):**
|
||||
@ -2208,7 +2215,14 @@ The suite() method in a JUnit test needs to be both public and static.
|
||||
//MethodDeclaration[not(@Static='true') or not(@Public='true')]
|
||||
[MethodDeclarator/@Image='suite']
|
||||
[MethodDeclarator/FormalParameters/@ParameterCount=0]
|
||||
[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')] or //MarkerAnnotation/Name[pmd-java:typeIs('org.junit.Test')]]]
|
||||
[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')]
|
||||
or //MarkerAnnotation/Name[
|
||||
pmd-java:typeIs('org.junit.Test')
|
||||
or pmd-java:typeIs('org.junit.jupiter.api.Test') or pmd-java:typeIs('org.junit.jupiter.api.RepeatedTest')
|
||||
or pmd-java:typeIs('org.junit.jupiter.api.TestFactory') or pmd-java:typeIs('org.junit.jupiter.api.TestTemplate')
|
||||
or pmd-java:typeIs('org.junit.jupiter.params.ParameterizedTest')
|
||||
]
|
||||
]]
|
||||
```
|
||||
|
||||
**Example(s):**
|
||||
@ -2399,16 +2413,10 @@ Serializable classes should provide a serialVersionUID field.
|
||||
**This rule is defined by the following XPath expression:**
|
||||
``` xpath
|
||||
//ClassOrInterfaceDeclaration
|
||||
[
|
||||
count(ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration
|
||||
/FieldDeclaration/VariableDeclarator/VariableDeclaratorId[@Image='serialVersionUID']) = 0
|
||||
and
|
||||
count(ImplementsList
|
||||
[ClassOrInterfaceType/@Image='Serializable'
|
||||
or ClassOrInterfaceType/@Image='java.io.Serializable']) =1
|
||||
and
|
||||
@Abstract = 'false'
|
||||
]
|
||||
[@Abstract = 'false']
|
||||
[count(ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration
|
||||
/FieldDeclaration/VariableDeclarator/VariableDeclaratorId[@Image='serialVersionUID']) = 0]
|
||||
[(ImplementsList | ExtendsList)/ClassOrInterfaceType[pmd-java:typeIs('java.io.Serializable')]]
|
||||
```
|
||||
|
||||
**Example(s):**
|
||||
@ -3196,7 +3204,14 @@ or
|
||||
UnaryExpressionNotPlusMinus[@Image='!']
|
||||
/PrimaryExpression/PrimaryPrefix[Literal/BooleanLiteral or Name[count(../../*)=1]]]
|
||||
]
|
||||
[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')] or //MarkerAnnotation/Name[pmd-java:typeIs('org.junit.Test')]]]
|
||||
[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')]
|
||||
or //MarkerAnnotation/Name[
|
||||
pmd-java:typeIs('org.junit.Test')
|
||||
or pmd-java:typeIs('org.junit.jupiter.api.Test') or pmd-java:typeIs('org.junit.jupiter.api.RepeatedTest')
|
||||
or pmd-java:typeIs('org.junit.jupiter.api.TestFactory') or pmd-java:typeIs('org.junit.jupiter.api.TestTemplate')
|
||||
or pmd-java:typeIs('org.junit.jupiter.params.ParameterizedTest')
|
||||
]
|
||||
]]
|
||||
```
|
||||
|
||||
**Example(s):**
|
||||
|
@ -166,8 +166,8 @@ Explicitly calling Thread.run() method will execute in the caller's thread of co
|
||||
[
|
||||
./Name[ends-with(@Image, '.run') or @Image = 'run']
|
||||
and substring-before(Name/@Image, '.') =//VariableDeclarator/VariableDeclaratorId/@Image
|
||||
[../../../Type/ReferenceType/ClassOrInterfaceType[typeIs('java.lang.Thread')]]
|
||||
or (./AllocationExpression/ClassOrInterfaceType[typeIs('java.lang.Thread')]
|
||||
[../../../Type/ReferenceType/ClassOrInterfaceType[pmd-java:typeIs('java.lang.Thread')]]
|
||||
or (./AllocationExpression/ClassOrInterfaceType[pmd-java:typeIs('java.lang.Thread')]
|
||||
and ../PrimarySuffix[@Image = 'run'])
|
||||
]
|
||||
]
|
||||
|
@ -132,10 +132,10 @@ The FileReader and FileWriter constructors instantiate FileInputStream and FileO
|
||||
**This rule is defined by the following XPath expression:**
|
||||
``` xpath
|
||||
//PrimaryPrefix/AllocationExpression/ClassOrInterfaceType[
|
||||
typeIs('java.io.FileInputStream')
|
||||
or typeIs('java.io.FileOutputStream')
|
||||
or typeIs('java.io.FileReader')
|
||||
or typeIs('java.io.FileWriter')
|
||||
pmd-java:typeIs('java.io.FileInputStream')
|
||||
or pmd-java:typeIs('java.io.FileOutputStream')
|
||||
or pmd-java:typeIs('java.io.FileReader')
|
||||
or pmd-java:typeIs('java.io.FileWriter')
|
||||
]
|
||||
```
|
||||
|
||||
@ -208,10 +208,10 @@ adverse impacts on performance.
|
||||
``` xpath
|
||||
//FieldDeclaration/Type/PrimitiveType[@Image = 'short']
|
||||
|
|
||||
//ClassOrInterfaceBodyDeclaration[not(Annotation/MarkerAnnotation/Name[typeIs('java.lang.Override')])]
|
||||
//ClassOrInterfaceBodyDeclaration[not(Annotation/MarkerAnnotation/Name[pmd-java:typeIs('java.lang.Override')])]
|
||||
/MethodDeclaration/ResultType/Type/PrimitiveType[@Image = 'short']
|
||||
|
|
||||
//ClassOrInterfaceBodyDeclaration[not(Annotation/MarkerAnnotation/Name[typeIs('java.lang.Override')])]
|
||||
//ClassOrInterfaceBodyDeclaration[not(Annotation/MarkerAnnotation/Name[pmd-java:typeIs('java.lang.Override')])]
|
||||
/MethodDeclaration/MethodDeclarator/FormalParameters/FormalParameter/Type/PrimitiveType[@Image = 'short']
|
||||
|
|
||||
//LocalVariableDeclaration/Type/PrimitiveType[@Image = 'short']
|
||||
@ -300,7 +300,7 @@ Note that new Byte() is deprecated since JDK 9 for that reason.
|
||||
``` xpath
|
||||
//AllocationExpression
|
||||
[not (ArrayDimsAndInits)
|
||||
and ClassOrInterfaceType[typeIs('java.lang.Byte')]]
|
||||
and ClassOrInterfaceType[pmd-java:typeIs('java.lang.Byte')]]
|
||||
```
|
||||
|
||||
**Example(s):**
|
||||
@ -498,7 +498,7 @@ Note that new Integer() is deprecated since JDK 9 for that reason.
|
||||
``` xpath
|
||||
//AllocationExpression
|
||||
[not (ArrayDimsAndInits)
|
||||
and ClassOrInterfaceType[typeIs('java.lang.Integer')]]
|
||||
and ClassOrInterfaceType[pmd-java:typeIs('java.lang.Integer')]]
|
||||
```
|
||||
|
||||
**Example(s):**
|
||||
@ -528,7 +528,7 @@ Note that new Long() is deprecated since JDK 9 for that reason.
|
||||
``` xpath
|
||||
//AllocationExpression
|
||||
[not (ArrayDimsAndInits)
|
||||
and ClassOrInterfaceType[typeIs('java.lang.Long')]]
|
||||
and ClassOrInterfaceType[pmd-java:typeIs('java.lang.Long')]]
|
||||
```
|
||||
|
||||
**Example(s):**
|
||||
@ -647,7 +647,7 @@ Note that new Short() is deprecated since JDK 9 for that reason.
|
||||
``` xpath
|
||||
//AllocationExpression
|
||||
[not (ArrayDimsAndInits)
|
||||
and ClassOrInterfaceType[typeIs('java.lang.Short')]]
|
||||
and ClassOrInterfaceType[pmd-java:typeIs('java.lang.Short')]]
|
||||
```
|
||||
|
||||
**Example(s):**
|
||||
|
@ -16,6 +16,7 @@ folder: pmd/rules
|
||||
|
||||
{% include callout.html content="Rules which enforce a specific coding style." %}
|
||||
|
||||
* [ForLoopNaming](pmd_rules_plsql_codestyle.html#forloopnaming): In case you have loops please name the loop variables more meaningful.
|
||||
* [MisplacedPragma](pmd_rules_plsql_codestyle.html#misplacedpragma): Oracle states that the PRAQMA AUTONOMOUS_TRANSACTION must be in the declaration block,but the cod...
|
||||
|
||||
## Design
|
||||
|
@ -5,9 +5,73 @@ permalink: pmd_rules_plsql_codestyle.html
|
||||
folder: pmd/rules/plsql
|
||||
sidebaractiveurl: /pmd_rules_plsql.html
|
||||
editmepath: ../pmd-plsql/src/main/resources/category/plsql/codestyle.xml
|
||||
keywords: Code Style, MisplacedPragma
|
||||
keywords: Code Style, MisplacedPragma, ForLoopNaming
|
||||
language: PLSQL
|
||||
---
|
||||
## ForLoopNaming
|
||||
|
||||
**Since:** PMD 6.7.0
|
||||
|
||||
**Priority:** Medium (3)
|
||||
|
||||
In case you have loops please name the loop variables more meaningful.
|
||||
|
||||
**This rule is defined by the following XPath expression:**
|
||||
``` xpath
|
||||
//CursorForLoopStatement[
|
||||
$allowSimpleLoops = 'false' or
|
||||
(Statement//CursorForLoopStatement or ancestor::CursorForLoopStatement)
|
||||
]
|
||||
/ForIndex[not(matches(@Image, $cursorPattern))]
|
||||
|
|
||||
//ForStatement[
|
||||
$allowSimpleLoops = 'false' or
|
||||
(Statement//ForStatement or ancestor::ForStatement)
|
||||
]
|
||||
/ForIndex[not(matches(@Image, $indexPattern))]
|
||||
```
|
||||
|
||||
**Example(s):**
|
||||
|
||||
``` sql
|
||||
-- good example
|
||||
BEGIN
|
||||
FOR company IN (SELECT * FROM companies) LOOP
|
||||
FOR contact IN (SELECT * FROM contacts) LOOP
|
||||
FOR party IN (SELECT * FROM parties) LOOP
|
||||
NULL;
|
||||
END LOOP;
|
||||
END LOOP;
|
||||
END LOOP;
|
||||
END;
|
||||
/
|
||||
|
||||
-- bad example
|
||||
BEGIN
|
||||
FOR c1 IN (SELECT * FROM companies) LOOP
|
||||
FOR c2 IN (SELECT * FROM contacts) LOOP
|
||||
FOR c3 IN (SELECT * FROM parties) LOOP
|
||||
NULL;
|
||||
END LOOP;
|
||||
END LOOP;
|
||||
END LOOP;
|
||||
END;
|
||||
/
|
||||
```
|
||||
|
||||
**This rule has the following properties:**
|
||||
|
||||
|Name|Default Value|Description|Multivalued|
|
||||
|----|-------------|-----------|-----------|
|
||||
|allowSimpleLoops|false|Ignore simple loops, that are not nested|no|
|
||||
|cursorPattern|[a-zA-Z_0-9]{5,}|The pattern used for the curosr loop variable|no|
|
||||
|indexPattern|[a-zA-Z_0-9]{5,}|The pattern used for the index loop variable|no|
|
||||
|
||||
**Use this rule by referencing it:**
|
||||
``` xml
|
||||
<rule ref="category/plsql/codestyle.xml/ForLoopNaming" />
|
||||
```
|
||||
|
||||
## MisplacedPragma
|
||||
|
||||
**Since:** PMD 5.5.2
|
||||
|
@ -24,7 +24,7 @@ The first step is to create a new empty ruleset. You can use the following templ
|
||||
<ruleset name="Custom Rules"
|
||||
xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd">
|
||||
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 https://pmd.sourceforge.net/ruleset_2_0_0.xsd">
|
||||
|
||||
<description>
|
||||
My custom rules
|
||||
|
@ -4,11 +4,11 @@ permalink: pmd_release_notes.html
|
||||
keywords: changelog, release notes
|
||||
---
|
||||
|
||||
## ????? - 6.6.0-SNAPSHOT
|
||||
## {{ site.pmd.date }} - {{ site.pmd.version | append_unless: is_release_version, "-SNAPSHOT" }}
|
||||
|
||||
The PMD team is pleased to announce PMD 6.6.0.
|
||||
The PMD team is pleased to announce PMD {{ site.pmd.version }}.
|
||||
|
||||
This is a minor release.
|
||||
This is a {{ site.pmd.release_type }} release.
|
||||
|
||||
### Table Of Contents
|
||||
|
||||
@ -22,37 +22,58 @@ This is a minor release.
|
||||
|
||||
#### New Rules
|
||||
|
||||
* The new Java rule [`LocalVariableNamingConventions`](pmd_rules_java_codestyle.html#localvariablenamingconventions) (`java-codestlye`)
|
||||
detects local variable names that don't comply to a given convention. It defaults to standrd Java convention of using camelCase,
|
||||
but can be configured. Special cases can be configured for final variables and catched exceptions' names.
|
||||
* The new Java rule {% rule java/codestyle/LinguisticNaming %} (`java-codestyle`)
|
||||
detects cases, when a method name indicates it returns a boolean (such as `isSmall()`) but it doesn't.
|
||||
Besides method names, the rule also checks field and variable names. It also checks, that getters return
|
||||
something but setters won't. The rule has several properties with which it can be customized.
|
||||
|
||||
* The new Java rule [`FormalParameterNamingConventions`](pmd_rules_java_codestyle.html#formalparameternamingconventions) (`java-codestlye`)
|
||||
detects formal parameter names that don't comply to a given convention. It defaults to standrd Java convention of using camelCase,
|
||||
but can be configured. Special cases can be configured for final parameters and lambda parameters (considering wether they are
|
||||
explicitly typed or not)
|
||||
* The new PL/SQL rule {% rule plsql/codestyle/ForLoopNaming %} (`plsql-codestyle`)
|
||||
enforces a naming convention for "for loops". Both "cursor for loops" and "index for loops" are covered.
|
||||
The rule can be customized via patterns. By default, short variable names are reported.
|
||||
|
||||
* The new Java rule {% rule java/codestyle/FieldNamingConventions %} (`java-codestyle`)
|
||||
detects field names that don't comply to a given convention. It defaults to standard Java convention of using camelCase,
|
||||
but can be configured with ease for e.g. constants or static fields.
|
||||
|
||||
### Fixed Issues
|
||||
|
||||
* doc
|
||||
* [#1215](https://github.com/pmd/pmd/issues/1215): \[doc] TOC links don't work?
|
||||
* core
|
||||
* [#1191](https://github.com/pmd/pmd/issues/1191): \[core] Test Framework: Sort violations by line/column
|
||||
* [#1283](https://github.com/pmd/pmd/issues/1283): \[core] Deprecate ReportTree
|
||||
* [#1288](https://github.com/pmd/pmd/issues/1288): \[core] No supported build listeners found with Gradle
|
||||
* [#1300](https://github.com/pmd/pmd/issues/1300): \[core] PMD stops processing file completely, if one rule in a rule chain fails
|
||||
* java-bestpractices
|
||||
* [#940](https://github.com/pmd/pmd/issues/940): \[java] JUnit 4 false positives for JUnit 5 tests
|
||||
* [#1267](https://github.com/pmd/pmd/pull/1267): \[java] MissingOverrideRule: Avoid NoClassDefFoundError with incomplete classpath
|
||||
* java-codestyle
|
||||
* [#1211](https://github.com/pmd/pmd/issues/1211): \[java] CommentDefaultAccessModifier false positive with nested interfaces (regression from 6.4.0)
|
||||
* [#1216](https://github.com/pmd/pmd/issues/1216): \[java] UnnecessaryFullyQualifiedName false positive for the same name method
|
||||
* java-design
|
||||
* [#1217](https://github.com/pmd/pmd/issues/1217): \[java] CyclomaticComplexityRule counts ?-operator twice
|
||||
* [#1255](https://github.com/pmd/pmd/issues/1255): \[java] UnnecessaryFullyQualifiedName false positive: static method on shadowed implicitly imported class
|
||||
* [#1258](https://github.com/pmd/pmd/issues/1285): \[java] False positive "UselessParentheses" for parentheses that contain assignment
|
||||
* java-errorprone
|
||||
* [#1078](https://github.com/pmd/pmd/issues/1078): \[java] MissingSerialVersionUID rule does not seem to catch inherited classes
|
||||
* java-performance
|
||||
* [#1298](https://github.com/pmd/pmd/issues/1298): \[java] RedundantFieldInitializer - NumberFormatException with Long
|
||||
* jsp
|
||||
* [#1274](https://github.com/pmd/pmd/issues/1274): \[jsp] Support EL in tag attributes
|
||||
* [#1276](https://github.com/pmd/pmd/issues/1276): \[jsp] add support for jspf and tag extensions
|
||||
* plsql
|
||||
* [#980](https://github.com/pmd/pmd/issues/980): \[plsql] ParseException for CREATE TABLE
|
||||
* [#981](https://github.com/pmd/pmd/issues/981): \[plsql] ParseException when parsing VIEW
|
||||
* [#1047](https://github.com/pmd/pmd/issues/1047): \[plsql] ParseException when parsing EXECUTE IMMEDIATE
|
||||
* ui
|
||||
* [#1233](https://github.com/pmd/pmd/issues/1233): \[ui] XPath autocomplete arrows on first and last items
|
||||
* [#681](https://github.com/pmd/pmd/issues/681): \[plsql] Parse error with Cursor For Loop
|
||||
|
||||
### API Changes
|
||||
|
||||
* The `findDescendantsOfType` methods in `net.sourceforge.pmd.lang.ast.AbstractNode` no longer search for exact type matches, but will
|
||||
match subclasses too. That means, it's now possible to look for abstract node types such as `AbstractJavaTypeNode` and not only for it's concrete subtypes.
|
||||
* All classes in the package `net.sourceforge.pmd.lang.dfa.report` have been deprecated and will be removed
|
||||
with PMD 7.0.0. This includes the class `net.sourceforge.pmd.lang.dfa.report.ReportTree`. The reason is,
|
||||
that this class is very specific to Java and not suitable for other languages. It has only been used for
|
||||
`YAHTMLRenderer`, which has been rewritten to work without these classes.
|
||||
|
||||
### External Contributions
|
||||
|
||||
* [#1182](https://github.com/pmd/pmd/pull/1182): \[ui] XPath AutoComplete - [Akshat Bahety](https://github.com/akshatbahety)
|
||||
* [#1231](https://github.com/pmd/pmd/pull/1231): \[doc] Minor typo fix in installation.md - [Ashish Rana](https://github.com/ashishrana160796)
|
||||
* [#109](https://github.com/pmd/pmd/pull/109): \[java] Add two linguistics rules under naming - [Arda Aslan](https://github.com/ardaasln)
|
||||
* [#1254](https://github.com/pmd/pmd/pull/1254): \[ci] \[GSoC] Integrating the danger and pmdtester to travis CI - [BBG](https://github.com/djydewang)
|
||||
* [#1258](https://github.com/pmd/pmd/pull/1258): \[java] Use typeof in MissingSerialVersionUID - [krichter722](https://github.com/krichter722)
|
||||
* [#1264](https://github.com/pmd/pmd/pull/1264): \[cpp] Fix NullPointerException in CPPTokenizer:99 - [Rafael Cortês](https://github.com/mrfyda)
|
||||
* [#1277](https://github.com/pmd/pmd/pull/1277): \[jsp] #1276 add support for jspf and tag extensions - [Jordi Llach](https://github.com/jordillachmrf)
|
||||
* [#1275](https://github.com/pmd/pmd/pull/1275): \[jsp] Issue #1274 - Support EL in tag attributes - [Jordi Llach](https://github.com/jordillachmrf)
|
||||
* [#1278](https://github.com/pmd/pmd/pull/1278): \[ci] \[GSoC] Use pmdtester 1.0.0.pre.beta3 - [BBG](https://github.com/djydewang)
|
||||
* [#1289](https://github.com/pmd/pmd/pull/1289): \[java] UselessParentheses: Fix false positive with assignments - [cobratbq](https://github.com/cobratbq)
|
||||
* [#1290](https://github.com/pmd/pmd/pull/1290): \[docs] \[GSoC] Create the documentation about pmdtester - [BBG](https://github.com/djydewang)
|
||||
* [#1256](https://github.com/pmd/pmd/pull/1256): \[java] #940 Avoid JUnit 4 false positives for JUnit 5 tests - [Alex Shesterov](https://github.com/vovkss)
|
||||
|
@ -6,6 +6,83 @@ permalink: pmd_release_notes_old.html
|
||||
Previous versions of PMD can be downloaded here:
|
||||
http://sourceforge.net/projects/pmd/files/pmd/
|
||||
|
||||
## 29-July-2018 - 6.6.0
|
||||
|
||||
The PMD team is pleased to announce PMD 6.6.0.
|
||||
|
||||
This is a minor release.
|
||||
|
||||
### Table Of Contents
|
||||
|
||||
* [New and noteworthy](#new-and-noteworthy)
|
||||
* [Java 11 Support](#java-11-support)
|
||||
* [New Rules](#new-rules)
|
||||
* [Modified Rules](#modified-rules)
|
||||
* [Fixed Issues](#fixed-issues)
|
||||
* [API Changes](#api-changes)
|
||||
* [External Contributions](#external-contributions)
|
||||
|
||||
### New and noteworthy
|
||||
|
||||
#### Java 11 Support
|
||||
|
||||
PMD is now able to parse the local-variable declaration syntax `var xxx`, that has been
|
||||
extended for lambda parameters with Java 11 via
|
||||
[JEP 323: Local-Variable Syntax for Lambda Parameters](http://openjdk.java.net/jeps/323).
|
||||
|
||||
#### New Rules
|
||||
|
||||
* The new Java rule [`LocalVariableNamingConventions`](pmd_rules_java_codestyle.html#localvariablenamingconventions)
|
||||
(`java-codestyle`) detects local variable names that don't comply to a given convention. It defaults to standard
|
||||
Java convention of using camelCase, but can be configured. Special cases can be configured for final variables
|
||||
and caught exceptions' names.
|
||||
|
||||
* The new Java rule [`FormalParameterNamingConventions`](pmd_rules_java_codestyle.html#formalparameternamingconventions)
|
||||
(`java-codestyle`) detects formal parameter names that don't comply to a given convention. It defaults to
|
||||
standard Java convention of using camelCase, but can be configured. Special cases can be configured for final
|
||||
parameters and lambda parameters (considering whether they are explicitly typed or not).
|
||||
|
||||
#### Modified Rules
|
||||
|
||||
* The Java rules [`AccessorClassGeneration`](pmd_rules_java_bestpracices.html#accessorclassgeneration) and
|
||||
[`AccessorMethodGeneration`](pmd_rules_java_bestpracices.html#accessormethodgeneration) (both in category
|
||||
`java-bestpractices`) have been modified to be only valid up until Java 10. Java 11 adds support for
|
||||
[JEP 181: Nest-Based Access Control](http://openjdk.java.net/jeps/181) which avoids the generation of
|
||||
accessor classes / methods altogether.
|
||||
|
||||
### Fixed Issues
|
||||
|
||||
* core
|
||||
* [#1178](https://github.com/pmd/pmd/issues/1178): \[core] "Unsupported build listener" in gradle build
|
||||
* [#1225](https://github.com/pmd/pmd/issues/1225): \[core] Error in sed expression on line 82 of run.sh while detecting installed version of Java
|
||||
* doc
|
||||
* [#1215](https://github.com/pmd/pmd/issues/1215): \[doc] TOC links don't work?
|
||||
* java-codestyle
|
||||
* [#1211](https://github.com/pmd/pmd/issues/1211): \[java] CommentDefaultAccessModifier false positive with nested interfaces (regression from 6.4.0)
|
||||
* [#1216](https://github.com/pmd/pmd/issues/1216): \[java] UnnecessaryFullyQualifiedName false positive for the same name method
|
||||
* java-design
|
||||
* [#1217](https://github.com/pmd/pmd/issues/1217): \[java] CyclomaticComplexityRule counts ?-operator twice
|
||||
* [#1226](https://github.com/pmd/pmd/issues/1226): \[java] NPath complexity false negative due to overflow
|
||||
* plsql
|
||||
* [#980](https://github.com/pmd/pmd/issues/980): \[plsql] ParseException for CREATE TABLE
|
||||
* [#981](https://github.com/pmd/pmd/issues/981): \[plsql] ParseException when parsing VIEW
|
||||
* [#1047](https://github.com/pmd/pmd/issues/1047): \[plsql] ParseException when parsing EXECUTE IMMEDIATE
|
||||
* ui
|
||||
* [#1233](https://github.com/pmd/pmd/issues/1233): \[ui] XPath autocomplete arrows on first and last items
|
||||
|
||||
### API Changes
|
||||
|
||||
* The `findDescendantsOfType` methods in `net.sourceforge.pmd.lang.ast.AbstractNode` no longer search for
|
||||
exact type matches, but will match subclasses, too. That means, it's now possible to look for abstract node
|
||||
types such as `AbstractJavaTypeNode` and not only for it's concrete subtypes.
|
||||
|
||||
### External Contributions
|
||||
|
||||
* [#1182](https://github.com/pmd/pmd/pull/1182): \[ui] XPath AutoComplete - [Akshat Bahety](https://github.com/akshatbahety)
|
||||
* [#1231](https://github.com/pmd/pmd/pull/1231): \[doc] Minor typo fix in installation.md - [Ashish Rana](https://github.com/ashishrana160796)
|
||||
* [#1250](https://github.com/pmd/pmd/pull/1250): \[ci] \[GSoC] Upload baseline of pmdtester automatically - [BBG](https://github.com/djydewang)
|
||||
|
||||
|
||||
## 26-June-2018 - 6.5.0
|
||||
|
||||
The PMD team is pleased to announce PMD 6.5.0.
|
||||
|
@ -8,7 +8,7 @@
|
||||
<parent>
|
||||
<groupId>net.sourceforge.pmd</groupId>
|
||||
<artifactId>pmd</artifactId>
|
||||
<version>6.6.0-SNAPSHOT</version>
|
||||
<version>6.7.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user