Merge branch 'java-grammar' into grammar-prefix-postfix
This commit is contained in:
29
.travis.yml
29
.travis.yml
@ -13,10 +13,9 @@ env:
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
allow_failures:
|
||||
- os: windows
|
||||
include:
|
||||
- name: "linux - mvn deploy"
|
||||
- stage: build
|
||||
name: "linux - mvn deploy"
|
||||
os: linux
|
||||
dist: bionic
|
||||
env: BUILD=deploy
|
||||
@ -28,10 +27,12 @@ matrix:
|
||||
os: linux
|
||||
dist: bionic
|
||||
env: BUILD=sonar
|
||||
if: "type = push && repo = pmd/pmd && fork = false"
|
||||
- name: "linux - run coveralls"
|
||||
os: linux
|
||||
dist: bionic
|
||||
env: BUILD=coveralls
|
||||
if: "type = push && repo = pmd/pmd && fork = false"
|
||||
- name: "macosx - mvn verify"
|
||||
os: osx
|
||||
env: BUILD=deploy
|
||||
@ -39,6 +40,12 @@ matrix:
|
||||
os: windows
|
||||
env: BUILD=deploy
|
||||
language: shell
|
||||
- stage: publish
|
||||
name: "Release Build - Publish"
|
||||
os: linux
|
||||
dist: bionic
|
||||
if: "type = push && repo = pmd/pmd && fork = false && tag is present"
|
||||
env: BUILD=publish
|
||||
|
||||
before_install:
|
||||
- bash .travis/before_install.sh "11.0.5+10"
|
||||
@ -49,22 +56,6 @@ script: source .travis/build-$BUILD.sh
|
||||
after_success: true
|
||||
|
||||
|
||||
before_deploy: true
|
||||
deploy:
|
||||
provider: releases
|
||||
api_key: ${GITHUB_OAUTH_TOKEN}
|
||||
file_glob: true
|
||||
file:
|
||||
- pmd-dist/target/pmd-*.zip
|
||||
- docs/pmd-doc-*.zip
|
||||
skip_cleanup: true
|
||||
draft: true
|
||||
on:
|
||||
tags: true
|
||||
repo: pmd/pmd
|
||||
condition: "${TRAVIS_SECURE_ENV_VARS} = true && ${BUILD} != sonar && ${BUILD} != coveralls && ${TRAVIS_OS_NAME} = linux"
|
||||
after_deploy: bash .travis/release.sh
|
||||
|
||||
notifications:
|
||||
webhooks:
|
||||
urls:
|
||||
|
@ -3,24 +3,9 @@ set -e
|
||||
|
||||
source .travis/logger.sh
|
||||
source .travis/common-functions.sh
|
||||
|
||||
function upload_baseline() {
|
||||
log_info "Generating and uploading baseline for pmdtester..."
|
||||
cd ..
|
||||
bundle config --local gemfile pmd/Gemfile
|
||||
pmd/.travis/travis_wait "bundle exec 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}/
|
||||
../../pmd/.travis/travis_wait "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/"
|
||||
exit 1
|
||||
else
|
||||
log_success "Successfully uploaded ${BRANCH_FILENAME}-baseline.zip to sourceforge"
|
||||
fi
|
||||
}
|
||||
source .travis/github-releases-api.sh
|
||||
source .travis/sourceforge-api.sh
|
||||
source .travis/regression-tester.sh
|
||||
|
||||
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}"
|
||||
@ -41,16 +26,8 @@ elif travis_isPullRequest; then
|
||||
|
||||
log_info "This is a pull-request build"
|
||||
./mvnw verify $MVN_BUILD_FLAGS
|
||||
(
|
||||
set +e
|
||||
# Create a corresponding remote branch locally
|
||||
if ! git show-ref --verify --quiet refs/heads/${TRAVIS_BRANCH}; then
|
||||
git fetch --no-tags origin +refs/heads/${TRAVIS_BRANCH}:refs/remotes/origin/${TRAVIS_BRANCH}
|
||||
git branch ${TRAVIS_BRANCH} origin/${TRAVIS_BRANCH}
|
||||
fi
|
||||
log_info "Running danger"
|
||||
bundle exec danger --verbose
|
||||
)
|
||||
|
||||
regression-tester_executeDanger
|
||||
|
||||
elif travis_isPush; then
|
||||
|
||||
@ -58,10 +35,35 @@ elif travis_isPush; then
|
||||
echo -e "\n\n"
|
||||
log_info "This is a release build for tag ${TRAVIS_TAG}"
|
||||
echo -e "\n\n"
|
||||
|
||||
# create a draft github release
|
||||
gh_releases_createDraftRelease "${TRAVIS_TAG}" "$(git show-ref --hash ${TRAVIS_TAG})"
|
||||
GH_RELEASE="$RESULT"
|
||||
|
||||
# Build and deploy to ossrh / maven-central
|
||||
./mvnw deploy -Possrh,sign,pmd-release $MVN_BUILD_FLAGS
|
||||
echo -e "\n\n"
|
||||
|
||||
# Deploy to github releases
|
||||
gh_release_uploadAsset "$GH_RELEASE" "pmd-dist/target/pmd-bin-${VERSION}.zip"
|
||||
gh_release_uploadAsset "$GH_RELEASE" "pmd-dist/target/pmd-src-${VERSION}.zip"
|
||||
|
||||
# Deploy to sourceforge files
|
||||
sourceforge_uploadFile "${VERSION}" "pmd-dist/target/pmd-bin-${VERSION}.zip"
|
||||
sourceforge_uploadFile "${VERSION}" "pmd-dist/target/pmd-src-${VERSION}.zip"
|
||||
|
||||
regression-tester_uploadBaseline
|
||||
|
||||
elif [[ "${VERSION}" == *-SNAPSHOT ]]; then
|
||||
log_info "This is a snapshot build"
|
||||
./mvnw deploy -Possrh,sign $MVN_BUILD_FLAGS
|
||||
|
||||
# Deploy to sourceforge files
|
||||
sourceforge_uploadFile "${VERSION}" "pmd-dist/target/pmd-bin-${VERSION}.zip"
|
||||
sourceforge_uploadFile "${VERSION}" "pmd-dist/target/pmd-src-${VERSION}.zip"
|
||||
|
||||
regression-tester_uploadBaseline
|
||||
|
||||
else
|
||||
# other build. Can happen during release: the commit with a non snapshot version is built, but not from the tag.
|
||||
log_info "This is some other build, probably during release: commit with a non-snapshot version on branch master..."
|
||||
@ -70,53 +72,6 @@ elif travis_isPush; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
(
|
||||
# disable fast fail, exit immediately, in this subshell
|
||||
set +e
|
||||
|
||||
echo -e "\n\n"
|
||||
log_info "Uploading pmd distribution to sourceforge..."
|
||||
.travis/travis_wait "rsync -avh pmd-dist/target/pmd-*-${VERSION}.zip ${PMD_SF_USER}@web.sourceforge.net:/home/frs/project/pmd/pmd/${VERSION}/"
|
||||
if [ $? -ne 0 ]; then
|
||||
log_error "Error while uploading pmd-*-${VERSION}.zip to sourceforge!"
|
||||
log_error "Please upload manually: https://sourceforge.net/projects/pmd/files/pmd/"
|
||||
exit 1
|
||||
else
|
||||
log_success "Successfully uploaded pmd-*-${VERSION}.zip to sourceforge"
|
||||
fi
|
||||
|
||||
)
|
||||
|
||||
( # UPLOAD RELEASE NOTES TO SOURCEFORGE
|
||||
|
||||
# This handler is called if any command fails
|
||||
function release_notes_fail() {
|
||||
log_error "Error while uploading release_notes.md as ReadMe.md to sourceforge!"
|
||||
log_error "Please upload manually: https://sourceforge.net/projects/pmd/files/pmd/"
|
||||
}
|
||||
|
||||
# exit subshell after trap
|
||||
set -e
|
||||
trap release_notes_fail ERR
|
||||
|
||||
RELEASE_NOTES_TMP=$(mktemp -t)
|
||||
|
||||
bundle exec .travis/render_release_notes.rb docs/pages/release_notes.md | tail -n +6 > "$RELEASE_NOTES_TMP"
|
||||
|
||||
rsync -avh "$RELEASE_NOTES_TMP" ${PMD_SF_USER}@web.sourceforge.net:/home/frs/project/pmd/pmd/${VERSION}/ReadMe.md
|
||||
|
||||
log_success "Successfully uploaded release_notes.md as ReadMe.md to sourceforge"
|
||||
|
||||
)
|
||||
|
||||
|
||||
(
|
||||
# disable fast fail, exit immediately, in this subshell
|
||||
set +e
|
||||
|
||||
upload_baseline
|
||||
)
|
||||
|
||||
else
|
||||
log_info "This is neither a pull request nor a push. Not executing any build."
|
||||
exit 1
|
||||
|
@ -3,92 +3,155 @@ set -e
|
||||
|
||||
source .travis/logger.sh
|
||||
source .travis/common-functions.sh
|
||||
source .travis/github-releases-api.sh
|
||||
source .travis/sourceforge-api.sh
|
||||
|
||||
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 Documentation ${VERSION} on branch ${TRAVIS_BRANCH}"
|
||||
function main() {
|
||||
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 Documentation ${VERSION} on branch ${TRAVIS_BRANCH}"
|
||||
|
||||
#
|
||||
# First step: build pmd with profile "generate-rule-docs"
|
||||
# The docs should appear under "docs/pages/rules/..." for each language
|
||||
#
|
||||
./mvnw clean verify -Dmaven.test.skip=true -Dmaven.javadoc.skip=true -P generate-rule-docs
|
||||
#
|
||||
# First step: build pmd with profile "generate-rule-docs"
|
||||
# The docs should appear under "docs/pages/rules/..." for each language
|
||||
# With this profile, also the checks are executed (e.g. DeadLinksChecker).
|
||||
#
|
||||
./mvnw clean verify -Dmaven.test.skip=true -Dmaven.javadoc.skip=true -P generate-rule-docs
|
||||
|
||||
|
||||
# in order to prevent that this documentation job is deploying the binary distributions to github releases
|
||||
# we delete it here
|
||||
|
||||
rm -f pmd-dist/target/pmd-*.zip
|
||||
|
||||
|
||||
|
||||
if ! travis_isPush; then
|
||||
log_info "Not publishing site, since this is not a push!"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
||||
|
||||
pushd docs
|
||||
|
||||
# run jekyll
|
||||
echo -e "\n\n"
|
||||
log_info "Building documentation using jekyll..."
|
||||
bundle install
|
||||
bundle exec jekyll build
|
||||
|
||||
# create pmd-doc archive
|
||||
echo -e "\n\n"
|
||||
log_info "Creating pmd-doc archive..."
|
||||
mv _site pmd-doc-${VERSION}
|
||||
zip -qr pmd-doc-${VERSION}.zip pmd-doc-${VERSION}/
|
||||
log_success "Successfully created pmd-doc-${VERSION}.zip:"
|
||||
ls -lh pmd-doc-${VERSION}.zip
|
||||
|
||||
(
|
||||
# disable fast fail, exit immediately, in this subshell
|
||||
set +e
|
||||
|
||||
if [[ "${TRAVIS_TAG}" != "" || "${VERSION}" == *-SNAPSHOT ]]; then
|
||||
echo -e "\n\n"
|
||||
log_info "Uploading pmd doc distribution to sourceforge..."
|
||||
../.travis/travis_wait "rsync -avh pmd-doc-${VERSION}.zip ${PMD_SF_USER}@web.sourceforge.net:/home/frs/project/pmd/pmd/${VERSION}/"
|
||||
if [ $? -ne 0 ]; then
|
||||
log_error "Couldn't upload pmd-doc-${VERSION}.zip!"
|
||||
log_error "Please upload manually: https://sourceforge.net/projects/pmd/files/pmd/"
|
||||
else
|
||||
log_success "Successfully uploaded pmd-doc-${VERSION}.zip to sourceforge"
|
||||
fi
|
||||
if ! travis_isPush; then
|
||||
log_info "Not publishing site, since this is not a push!"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# rsync site to pmd.sourceforge.net/snapshot
|
||||
if [[ "${VERSION}" == *-SNAPSHOT && "${TRAVIS_BRANCH}" == "master" ]] && has_docs_change; then
|
||||
echo -e "\n\n"
|
||||
log_info "Uploading snapshot site to pmd.sourceforge.net/snapshot..."
|
||||
../.travis/travis_wait "rsync -ah --stats --delete pmd-doc-${VERSION}/ ${PMD_SF_USER}@web.sourceforge.net:/home/project-web/pmd/htdocs/snapshot/"
|
||||
if [ $? -ne 0 ]; then
|
||||
log_error "Couldn't upload the snapshot documentation. It won't be current on http://pmd.sourceforge.net/snapshot/"
|
||||
else
|
||||
log_success "Successfully uploaded snapshot documentation: http://pmd.sourceforge.net/snapshot/"
|
||||
fi
|
||||
#
|
||||
# For pushes, we'll update the online documentation
|
||||
#
|
||||
generate_jekyll_doc
|
||||
create_pmd-doc_archive
|
||||
|
||||
# Deploy to sourceforge files
|
||||
sourceforge_uploadFile "${VERSION}" "docs/pmd-doc-${VERSION}.zip"
|
||||
|
||||
if [[ "${VERSION}" == *-SNAPSHOT && "${TRAVIS_BRANCH}" == "master" ]]; then
|
||||
# only for snapshot builds from branch master
|
||||
|
||||
# update github pages https://pmd.github.io/pmd/
|
||||
publish_to_github_pages
|
||||
# rsync site to https://pmd.sourceforge.io/snapshot
|
||||
sourceforge_rsyncSnapshotDocumentation "${VERSION}" "snapshot"
|
||||
fi
|
||||
|
||||
true
|
||||
)
|
||||
|
||||
if [[ "${VERSION}" != *-SNAPSHOT && "${TRAVIS_TAG}" != "" ]]; then
|
||||
log_info "This is a release documentation build for pmd ${VERSION}"
|
||||
|
||||
# Deploy to github releases
|
||||
gh_releases_getLatestDraftRelease
|
||||
GH_RELEASE="$RESULT"
|
||||
|
||||
gh_release_uploadAsset "$GH_RELEASE" "docs/pmd-doc-${VERSION}.zip"
|
||||
|
||||
# updating github release text
|
||||
# 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)
|
||||
RELEASE_NAME="PMD ${VERSION} ($(date -u +%d-%B-%Y))"
|
||||
gh_release_updateRelease "$GH_RELEASE" "$RELEASE_NAME" "$RENDERED_RELEASE_NOTES"
|
||||
sourceforge_uploadReleaseNotes "${VERSION}" "${RENDERED_RELEASE_NOTES}"
|
||||
|
||||
publish_release_documentation_github
|
||||
sourceforge_rsyncSnapshotDocumentation "${VERSION}" "pmd-${VERSION}"
|
||||
fi
|
||||
}
|
||||
|
||||
#
|
||||
# Push the generated site to gh-pages branch
|
||||
# only for snapshot builds from branch master
|
||||
# Executes jekyll and generates the documentation
|
||||
# The documentation will be generated in the directory "docs/_site".
|
||||
#
|
||||
if [[ "${VERSION}" == *-SNAPSHOT && "${TRAVIS_BRANCH}" == "master" ]] && has_docs_change; then
|
||||
function generate_jekyll_doc() {
|
||||
pushd docs
|
||||
|
||||
echo -e "\n\n"
|
||||
log_info "Building documentation using jekyll..."
|
||||
bundle install
|
||||
bundle exec jekyll build
|
||||
|
||||
popd
|
||||
}
|
||||
|
||||
#
|
||||
# Creates the pmd-doc.zip archive. It will be placed in "docs/".
|
||||
#
|
||||
function create_pmd-doc_archive() {
|
||||
pushd docs
|
||||
|
||||
echo -e "\n\n"
|
||||
log_info "Creating pmd-doc archive..."
|
||||
mv _site pmd-doc-${VERSION}
|
||||
zip -qr pmd-doc-${VERSION}.zip pmd-doc-${VERSION}/
|
||||
log_success "Successfully created pmd-doc-${VERSION}.zip"
|
||||
|
||||
popd
|
||||
}
|
||||
|
||||
#
|
||||
# Publishes the site to https://pmd.github.io/pmd-${VERSION} and
|
||||
# https://pmd.github.io/latest/
|
||||
#
|
||||
function publish_release_documentation_github() {
|
||||
echo -e "\n\n"
|
||||
log_info "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
|
||||
(
|
||||
cd pmd.github.io
|
||||
git init
|
||||
git config user.name "Travis CI (pmd-bot)"
|
||||
git config user.email "andreas.dangel+pmd-bot@adangel.org"
|
||||
git config core.sparsecheckout true
|
||||
git remote add origin git@github.com:pmd/pmd.github.io.git
|
||||
echo "/latest/" > .git/info/sparse-checkout
|
||||
echo "/sitemap.xml" >> .git/info/sparse-checkout
|
||||
git pull --depth=1 origin master
|
||||
log_info "Copying documentation from ../docs/pmd-doc-${VERSION}/ to pmd-${VERSION}/ ..."
|
||||
rsync -ah --stats ../docs/pmd-doc-${VERSION}/ pmd-${VERSION}/
|
||||
git status
|
||||
echo "Executing: git add pmd-${VERSION}"
|
||||
git add pmd-${VERSION}
|
||||
echo "Executing: git commit..."
|
||||
git commit -q -m "Added pmd-${VERSION}"
|
||||
|
||||
log_info "Copying pmd-${VERSION} to latest ..."
|
||||
git rm -qr latest
|
||||
cp -a pmd-${VERSION} latest
|
||||
echo "Executing: git add latest"
|
||||
git add latest
|
||||
echo "Executing: git commit..."
|
||||
git commit -q -m "Copying pmd-${VERSION} to latest"
|
||||
|
||||
log_info "Generating sitemap.xml"
|
||||
../.travis/sitemap_generator.sh > sitemap.xml
|
||||
echo "Executing: git add sitemap.xml"
|
||||
git add sitemap.xml
|
||||
echo "Executing: git commit..."
|
||||
git commit -q -m "Generated sitemap.xml"
|
||||
|
||||
echo "Executing: git push origin master"
|
||||
git push origin master
|
||||
)
|
||||
}
|
||||
|
||||
#
|
||||
# Updates github pages of the main repository,
|
||||
# so that https://pmd.github.io/pmd/ has the latest (snapshot) content
|
||||
#
|
||||
function publish_to_github_pages() {
|
||||
echo -e "\n\n"
|
||||
log_info "Pushing the new site to github pages..."
|
||||
git clone --branch gh-pages --depth 1 git@github.com:pmd/pmd.git pmd-gh-pages
|
||||
# clear the files first
|
||||
rm -rf pmd-gh-pages/*
|
||||
# copy the new site
|
||||
cp -a pmd-doc-${VERSION}/* pmd-gh-pages/
|
||||
cp -a docs/pmd-doc-${VERSION}/* pmd-gh-pages/
|
||||
(
|
||||
cd pmd-gh-pages
|
||||
git config user.name "Travis CI (pmd-bot)"
|
||||
@ -102,6 +165,6 @@ TRAVIS_COMMIT_RANGE=${TRAVIS_COMMIT_RANGE}"
|
||||
git push git@github.com:pmd/pmd.git HEAD:gh-pages
|
||||
log_success "Successfully pushed site to https://pmd.github.io/pmd/"
|
||||
)
|
||||
fi
|
||||
}
|
||||
|
||||
popd
|
||||
main
|
||||
|
28
.travis/build-publish.sh
Normal file
28
.travis/build-publish.sh
Normal file
@ -0,0 +1,28 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
source .travis/logger.sh
|
||||
source .travis/common-functions.sh
|
||||
source .travis/github-releases-api.sh
|
||||
source .travis/sourceforge-api.sh
|
||||
|
||||
VERSION=$(./mvnw -q -Dexec.executable="echo" -Dexec.args='${project.version}' --non-recursive org.codehaus.mojo:exec-maven-plugin:1.5.0:exec)
|
||||
log_info "PMD Release ${VERSION}"
|
||||
|
||||
if ! travis_isPush; then
|
||||
log_info "Not publishing release, since this is not a push!"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${VERSION}" == *-SNAPSHOT || "${TRAVIS_TAG}" == "" ]]; then
|
||||
log_info "Not publishing release, since this is not a release!"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
||||
# Publish github release
|
||||
gh_releases_getLatestDraftRelease
|
||||
GH_RELEASE="$RESULT"
|
||||
|
||||
gh_release_publishRelease "$GH_RELEASE"
|
||||
sourceforge_selectDefault "${VERSION}"
|
@ -53,14 +53,3 @@ function travis_isWindows() {
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
function has_docs_change() {
|
||||
if [[ $(git diff --name-only ${TRAVIS_COMMIT_RANGE}) = *"docs/"* ]]; then
|
||||
log_info "Checking for changes in docs/ (TRAVIS_COMMIT_RANGE=${TRAVIS_COMMIT_RANGE}): changes found"
|
||||
return 0
|
||||
else
|
||||
log_info "Checking for changes in docs/ (TRAVIS_COMMIT_RANGE=${TRAVIS_COMMIT_RANGE}): no changes"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
200
.travis/github-releases-api.sh
Normal file
200
.travis/github-releases-api.sh
Normal file
@ -0,0 +1,200 @@
|
||||
#
|
||||
# The functions here require the following scripts:
|
||||
# .travis/logger.sh
|
||||
#
|
||||
# The functions here require the following environment variables:
|
||||
# GITHUB_OAUTH_TOKEN
|
||||
#
|
||||
|
||||
#
|
||||
# Creates a new release on github with the given tag and target_commit.
|
||||
# The release is draft and not published.
|
||||
#
|
||||
# $RESULT = release json string
|
||||
#
|
||||
# See: https://developer.github.com/v3/repos/releases/#create-a-release
|
||||
#
|
||||
function gh_releases_createDraftRelease() {
|
||||
local tagName="$1"
|
||||
local targetCommitish="$2"
|
||||
|
||||
log_debug "$FUNCNAME: Creating new draft release for tag=$tagName and commit=$targetCommitish"
|
||||
|
||||
local request=$(cat <<-EOF
|
||||
{
|
||||
"tag_name": "${tagName}",
|
||||
"target_commitish": "${targetCommitish}",
|
||||
"name": "${tagName}",
|
||||
"draft": true
|
||||
}
|
||||
EOF
|
||||
)
|
||||
|
||||
log_debug "POST https://api.github.com/repos/pmd/pmd/releases"
|
||||
log_info "Creating gihtub draft release"
|
||||
RESULT=$(curl --fail -s -H "Authorization: token ${GITHUB_OAUTH_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-X POST \
|
||||
--data "${request}" \
|
||||
"https://api.github.com/repos/pmd/pmd/releases")
|
||||
log_debug " -> response: $RESULT"
|
||||
|
||||
log_success "Created draft release with id $(echo $RESULT | jq --raw-output ".url")"
|
||||
}
|
||||
|
||||
#
|
||||
# Gets the latest release, if it is a draft and returns with 0.
|
||||
# Returns with 1, if the latest release is not a draft - meaning, there is no
|
||||
# draft release (yet?).
|
||||
#
|
||||
# RESULT = release json string
|
||||
#
|
||||
# See: https://developer.github.com/v3/repos/releases/#list-releases-for-a-repository
|
||||
#
|
||||
function gh_releases_getLatestDraftRelease() {
|
||||
log_debug "$FUNCNAME"
|
||||
log_debug "GET https://api.github.com/repos/pmd/pmd/releases?per_page=1"
|
||||
RESULT=$(curl --fail -s -H "Authorization: token ${GITHUB_OAUTH_TOKEN}" \
|
||||
"https://api.github.com/repos/pmd/pmd/releases?per_page=1" | jq ".[0]")
|
||||
log_debug " -> response: $RESULT"
|
||||
local draft=$(echo $RESULT | jq ".draft")
|
||||
if [ "$draft" != "true" ]; then
|
||||
RESULT=""
|
||||
log_error "Could not find draft release!"
|
||||
return 1
|
||||
fi
|
||||
log_info "Found draft release: $(echo $RESULT | jq --raw-output ".url")"
|
||||
}
|
||||
|
||||
#
|
||||
# Deletes a release.
|
||||
#
|
||||
# See: https://developer.github.com/v3/repos/releases/#delete-a-release
|
||||
#
|
||||
function gh_release_deleteRelease() {
|
||||
local release="$1"
|
||||
|
||||
gh_release_getIdFromData "$release"
|
||||
local releaseId="$RESULT"
|
||||
log_debug "$FUNCNAME id=$releaseId"
|
||||
log_debug "DELETE https://api.github.com/repos/pmd/pmd/releases/$releaseId"
|
||||
log_info "Deleting github release $releaseId"
|
||||
local response
|
||||
response=$(curl --fail -s -H "Authorization: token ${GITHUB_OAUTH_TOKEN}" \
|
||||
-X DELETE \
|
||||
"https://api.github.com/repos/pmd/pmd/releases/$releaseId")
|
||||
log_debug " -> response: $response"
|
||||
log_success "Deleted release with id $releaseId"
|
||||
}
|
||||
|
||||
#
|
||||
# Determines the release id from the given JSON release data.
|
||||
#
|
||||
# RESULT = "the release id"
|
||||
#
|
||||
function gh_release_getIdFromData() {
|
||||
local release="$1"
|
||||
|
||||
RESULT=$(echo $release | jq --raw-output ".id")
|
||||
}
|
||||
|
||||
#
|
||||
# Uploads a asset to an existing release.
|
||||
#
|
||||
# See: https://developer.github.com/v3/repos/releases/#upload-a-release-asset
|
||||
#
|
||||
function gh_release_uploadAsset() {
|
||||
local release="$1"
|
||||
local filename="$2"
|
||||
local name=$(basename $filename)
|
||||
|
||||
gh_release_getIdFromData "$release"
|
||||
local releaseId="$RESULT"
|
||||
log_debug "$FUNCNAME: releaseId=$releaseId file=$filename name=$name"
|
||||
|
||||
local uploadUrl=$(echo "$release" | jq --raw-output ".upload_url")
|
||||
uploadUrl="${uploadUrl%%\{\?name,label\}}"
|
||||
uploadUrl="${uploadUrl}?name=${name}"
|
||||
log_debug "POST $uploadUrl"
|
||||
log_info "Uploading $filename to github release $releaseId"
|
||||
local response
|
||||
response=$(curl --fail -s -H "Authorization: token ${GITHUB_OAUTH_TOKEN}" \
|
||||
-H "Content-Type: application/zip" \
|
||||
--data-binary "@$filename" \
|
||||
-X POST \
|
||||
"${uploadUrl}")
|
||||
log_debug " -> response: $response"
|
||||
log_success "Uploaded release asset $filename for release $releaseId"
|
||||
}
|
||||
|
||||
#
|
||||
# Updates the release info: name and body.
|
||||
# The body is escaped to fit into JSON, so it is allowed for the body to be
|
||||
# a multi-line string.
|
||||
#
|
||||
# See: https://developer.github.com/v3/repos/releases/#edit-a-release
|
||||
#
|
||||
function gh_release_updateRelease() {
|
||||
local release="$1"
|
||||
local name="$2"
|
||||
local body="$3"
|
||||
|
||||
gh_release_getIdFromData "$release"
|
||||
local releaseId="$RESULT"
|
||||
log_debug "$FUNCNAME releaseId=$releaseId name=$name"
|
||||
|
||||
body="${body//'\'/\\\\}"
|
||||
body="${body//$'\r'/}"
|
||||
body="${body//$'\n'/\\r\\n}"
|
||||
body="${body//'"'/\\\"}"
|
||||
|
||||
local request=$(cat <<-EOF
|
||||
{
|
||||
"name": "${name}",
|
||||
"body": "${body}"
|
||||
}
|
||||
EOF
|
||||
)
|
||||
|
||||
log_debug "PATCH https://api.github.com/repos/pmd/pmd/releases/${releaseId}"
|
||||
log_debug " -> request: $request"
|
||||
log_info "Updating github release $releaseId"
|
||||
local response
|
||||
response=$(curl --fail -s -H "Authorization: token ${GITHUB_OAUTH_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data "${request}" \
|
||||
-X PATCH \
|
||||
"https://api.github.com/repos/pmd/pmd/releases/${releaseId}")
|
||||
log_debug " -> response: $response"
|
||||
log_success "Updated release with id=$releaseId"
|
||||
}
|
||||
|
||||
#
|
||||
# Publish a release by setting draft="false".
|
||||
# Note: This will send out the notification emails if somebody
|
||||
# watched the releases.
|
||||
#
|
||||
# See: https://developer.github.com/v3/repos/releases/#edit-a-release
|
||||
#
|
||||
function gh_release_publishRelease() {
|
||||
local release="$1"
|
||||
|
||||
gh_release_getIdFromData "$release"
|
||||
local releaseId="$RESULT"
|
||||
log_debug "$FUNCNAME releaseId=$releaseId"
|
||||
|
||||
local request='{"draft":false}'
|
||||
log_debug "PATCH https://api.github.com/repos/pmd/pmd/releases/${releaseId}"
|
||||
log_debug " -> request: $request"
|
||||
log_info "Publishing github release $releaseId"
|
||||
local response
|
||||
response=$(curl --fail -s -H "Authorization: token ${GITHUB_OAUTH_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data "${request}" \
|
||||
-X PATCH \
|
||||
"https://api.github.com/repos/pmd/pmd/releases/${releaseId}")
|
||||
log_debug " -> response: $response"
|
||||
local htmlUrl=$(echo "$response" | jq --raw-output ".html_url")
|
||||
log_success "Published release with id=$releaseId at $htmlUrl"
|
||||
}
|
||||
|
@ -6,13 +6,18 @@ COL_RESET="\e[0m"
|
||||
COL_YELLOW="\e[33;1m"
|
||||
|
||||
function log_error() {
|
||||
echo -e "${COL_RED}[ERROR] $*${COL_RESET}"
|
||||
echo -e "${COL_RED}[ERROR ] $*${COL_RESET}"
|
||||
}
|
||||
|
||||
function log_info() {
|
||||
echo -e "${COL_YELLOW}[INFO] $*${COL_RESET}"
|
||||
echo -e "${COL_YELLOW}[INFO ] $*${COL_RESET}"
|
||||
}
|
||||
|
||||
function log_success() {
|
||||
echo -e "${COL_GREEN}[SUCCESS] $*${COL_RESET}"
|
||||
}
|
||||
|
||||
function log_debug() {
|
||||
true
|
||||
#echo -e "[DEBUG ] $*"
|
||||
}
|
||||
|
79
.travis/regression-tester.sh
Normal file
79
.travis/regression-tester.sh
Normal file
@ -0,0 +1,79 @@
|
||||
#
|
||||
# The functions here require the following scripts:
|
||||
# .travis/logger.sh
|
||||
#
|
||||
# The functions here require the following environment variables:
|
||||
# PMD_SF_USER
|
||||
|
||||
#
|
||||
# Generate a new baseline and upload it to sourceforge
|
||||
#
|
||||
# Note: this function always succeeds, even if the upload fails.
|
||||
# In that case, just a error logging is provided.
|
||||
#
|
||||
function regression-tester_uploadBaseline() {
|
||||
log_debug "$FUNCNAME branch=${TRAVIS_BRANCH}"
|
||||
local targetUrl="https://sourceforge.net/projects/pmd/files/pmd-regression-tester/"
|
||||
|
||||
local errexitstate="$(shopt -po errexit)"
|
||||
set +e # disable errexit
|
||||
(
|
||||
# This handler is called if any command fails
|
||||
function upload_failed() {
|
||||
log_error "Error while uploading ${BRANCH_FILENAME}-baseline.zip to sourceforge!"
|
||||
log_error "Please upload manually: ${targetUrl}"
|
||||
}
|
||||
|
||||
# exit subshell after trap
|
||||
set -e
|
||||
trap upload_failed ERR
|
||||
|
||||
log_info "Generating and uploading baseline for pmdtester..."
|
||||
cd ..
|
||||
bundle config --local gemfile pmd/Gemfile
|
||||
pmd/.travis/travis_wait "bundle exec 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}/
|
||||
../../pmd/.travis/travis_wait "rsync -avh ${BRANCH_FILENAME}-baseline.zip ${PMD_SF_USER}@web.sourceforge.net:/home/frs/project/pmd/pmd-regression-tester/"
|
||||
log_success "Successfully uploaded ${BRANCH_FILENAME}-baseline.zip to ${targetUrl}"
|
||||
)
|
||||
# restore errexit state
|
||||
eval "$errexitstate"
|
||||
}
|
||||
|
||||
#
|
||||
# Execute danger, which executes pmd-regression-tester (via Dangerfile).
|
||||
#
|
||||
# Note: this function always succeeds, even if the danger fails.
|
||||
# In that case, just a error logging is provided.
|
||||
#
|
||||
function regression-tester_executeDanger() {
|
||||
log_debug "$FUNCNAME"
|
||||
|
||||
local errexitstate="$(shopt -po errexit)"
|
||||
set +e # disable errexit
|
||||
(
|
||||
# This handler is called if any command fails
|
||||
function danger_failed() {
|
||||
log_error "Error while executing danger/pmd-regression-tester"
|
||||
}
|
||||
|
||||
# exit subshell after trap
|
||||
set -e
|
||||
trap danger_failed ERR
|
||||
|
||||
# Create a corresponding remote branch locally
|
||||
if ! git show-ref --verify --quiet refs/heads/${TRAVIS_BRANCH}; then
|
||||
git fetch --no-tags origin +refs/heads/${TRAVIS_BRANCH}:refs/remotes/origin/${TRAVIS_BRANCH}
|
||||
git branch ${TRAVIS_BRANCH} origin/${TRAVIS_BRANCH}
|
||||
log_debug "Created local branch ${TRAVIS_BRANCH}"
|
||||
fi
|
||||
|
||||
log_info "Running danger on branch ${TRAVIS_BRANCH}"
|
||||
bundle exec danger --verbose
|
||||
log_success "Executing danger successfully"
|
||||
)
|
||||
# restore errexit state
|
||||
eval "$errexitstate"
|
||||
}
|
@ -1,135 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
source .travis/logger.sh
|
||||
|
||||
echo "BUILD: $BUILD"
|
||||
RELEASE_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 "RELEASE_VERSION: $RELEASE_VERSION"
|
||||
|
||||
if [ "${BUILD}" = "deploy" ]; then
|
||||
|
||||
# Deploy to ossrh has already been done with the usual build. See build-deploy.sh
|
||||
|
||||
(
|
||||
# disable fast fail, exit immediately, in this subshell
|
||||
set +e
|
||||
|
||||
# The site has been built before, the files have already been uploaded to sourceforge.
|
||||
# Since this is a release, making the binary the new default file...
|
||||
log_info "Selecting pmd-bin-${RELEASE_VERSION} as default on sourceforge.net..."
|
||||
curl -H "Accept: application/json" -X PUT -d "default=windows&default=mac&default=linux&default=bsd&default=solaris&default=others" \
|
||||
-d "api_key=${PMD_SF_APIKEY}" https://sourceforge.net/projects/pmd/files/pmd/${RELEASE_VERSION}/pmd-bin-${RELEASE_VERSION}.zip
|
||||
if [ $? -ne 0 ]; then
|
||||
log_error "Couldn't select latest binary as default on sourceforge.net"
|
||||
else
|
||||
log_info "pmd-bin-${RELEASE_VERSION} is now the default download option."
|
||||
fi
|
||||
true
|
||||
)
|
||||
|
||||
fi
|
||||
|
||||
|
||||
if [ "${BUILD}" = "doc" ]; then
|
||||
|
||||
echo -e "\n\n"
|
||||
log_info "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
|
||||
(
|
||||
cd pmd.github.io
|
||||
git init
|
||||
git config user.name "Travis CI (pmd-bot)"
|
||||
git config user.email "andreas.dangel+pmd-bot@adangel.org"
|
||||
git config core.sparsecheckout true
|
||||
git remote add origin git@github.com:pmd/pmd.github.io.git
|
||||
echo "/latest/" > .git/info/sparse-checkout
|
||||
echo "/sitemap.xml" >> .git/info/sparse-checkout
|
||||
git pull --depth=1 origin master
|
||||
log_info "Copying documentation from ../docs/pmd-doc-${RELEASE_VERSION}/ to pmd-${RELEASE_VERSION}/ ..."
|
||||
rsync -ah --stats ../docs/pmd-doc-${RELEASE_VERSION}/ pmd-${RELEASE_VERSION}/
|
||||
git status
|
||||
echo "Executing: git add pmd-${RELEASE_VERSION}"
|
||||
git add pmd-${RELEASE_VERSION}
|
||||
echo "Executing: git commit..."
|
||||
git commit -q -m "Added pmd-${RELEASE_VERSION}"
|
||||
|
||||
log_info "Copying pmd-${RELEASE_VERSION} to latest ..."
|
||||
git rm -qr latest
|
||||
cp -a pmd-${RELEASE_VERSION} latest
|
||||
echo "Executing: git add latest"
|
||||
git add latest
|
||||
echo "Executing: git commit..."
|
||||
git commit -q -m "Copying pmd-${RELEASE_VERSION} to latest"
|
||||
|
||||
log_info "Generating sitemap.xml"
|
||||
../.travis/sitemap_generator.sh > sitemap.xml
|
||||
echo "Executing: git add sitemap.xml"
|
||||
git add sitemap.xml
|
||||
echo "Executing: git commit..."
|
||||
git commit -q -m "Generated sitemap.xml"
|
||||
|
||||
echo "Executing: git push origin master"
|
||||
git push origin master
|
||||
)
|
||||
|
||||
# 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="$RENDERED_RELEASE_NOTES"
|
||||
RELEASE_BODY="${RELEASE_BODY//'\'/\\\\}"
|
||||
RELEASE_BODY="${RELEASE_BODY//$'\r'/}"
|
||||
RELEASE_BODY="${RELEASE_BODY//$'\n'/\\r\\n}"
|
||||
RELEASE_BODY="${RELEASE_BODY//'"'/\\\"}"
|
||||
cat > release-edit-request.json <<EOF
|
||||
{
|
||||
"name": "$RELEASE_NAME",
|
||||
"body": "$RELEASE_BODY",
|
||||
"draft": false
|
||||
}
|
||||
EOF
|
||||
echo -e "\n\n"
|
||||
log_info "Updating and publishing release at https://api.github.com/repos/pmd/pmd/releases/${RELEASE_ID}..."
|
||||
|
||||
|
||||
RESPONSE=$(curl -i -s -H "Authorization: token ${GITHUB_OAUTH_TOKEN}" -H "Content-Type: application/json" --data "@release-edit-request.json" -X PATCH https://api.github.com/repos/pmd/pmd/releases/${RELEASE_ID})
|
||||
if [[ "$RESPONSE" != *"HTTP/1.1 200"* ]]; then
|
||||
log_error "Github Request failed!"
|
||||
echo "Request:"
|
||||
cat release-edit-request.json
|
||||
echo
|
||||
echo "Response:"
|
||||
echo "$RESPONSE"
|
||||
else
|
||||
log_success "Update OK"
|
||||
fi
|
||||
|
||||
|
||||
|
||||
(
|
||||
echo -e "\n\n"
|
||||
|
||||
# disable fast fail, exit immediately, in this subshell
|
||||
set +e
|
||||
|
||||
log_info "Uploading the new release to pmd.sourceforge.net which serves as an archive..."
|
||||
|
||||
.travis/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..."
|
||||
log_error "Please upload manually (PMD Version: ${RELEASE_VERSION})"
|
||||
else
|
||||
log_success "The documentation is now available under http://pmd.sourceforge.net/pmd-${RELEASE_VERSION}/"
|
||||
fi
|
||||
true
|
||||
)
|
||||
|
||||
|
||||
fi
|
||||
|
@ -1,6 +1,9 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
source .travis/logger.sh
|
||||
source .travis/common-functions.sh
|
||||
|
||||
if [ "${TRAVIS_REPO_SLUG}" != "pmd/pmd" ] || [ "${TRAVIS_PULL_REQUEST}" != "false" ] || [ "${TRAVIS_SECURE_ENV_VARS}" != "true" ] || [ "${encrypted_5630fbebf057_iv}" = "" ]; then
|
||||
echo "Not setting up secrets:"
|
||||
echo " TRAVIS_REPO_SLUG=${TRAVIS_REPO_SLUG}"
|
||||
@ -18,8 +21,17 @@ mkdir -p "$HOME/.ssh"
|
||||
chmod 700 "$HOME/.ssh"
|
||||
mv .travis/id_rsa "$HOME/.ssh/id_rsa"
|
||||
chmod 600 "$HOME/.ssh/id_rsa"
|
||||
mkdir -p "$HOME/.gpg"
|
||||
gpg --batch --import .travis/release-signing-key-82DE7BE82166E84E.gpg
|
||||
|
||||
if travis_isLinux; then
|
||||
mkdir -p "$HOME/.gpg"
|
||||
gpg --batch --import .travis/release-signing-key-82DE7BE82166E84E.gpg
|
||||
else
|
||||
log_info "Not setting up gpg for ${TRAVIS_OS_NAME}."
|
||||
# Note: importing keys into gpg will start gpg-agent. This background task then
|
||||
# prevents travis-ci from terminating the build job under Windows.
|
||||
# Alternatively "gpgconf --kill gpg-agent" can be executed to stop the
|
||||
# gpg-agent at the end, if the gpg keys are needed.
|
||||
fi
|
||||
rm .travis/secrets.tar
|
||||
rm .travis/release-signing-key-82DE7BE82166E84E.gpg
|
||||
|
||||
|
166
.travis/sourceforge-api.sh
Normal file
166
.travis/sourceforge-api.sh
Normal file
@ -0,0 +1,166 @@
|
||||
#
|
||||
# The functions here require the following scripts:
|
||||
# .travis/logger.sh
|
||||
#
|
||||
# The functions here require the following environment variables:
|
||||
# PMD_SF_USER
|
||||
# PMD_SF_APIKEY
|
||||
#
|
||||
|
||||
#
|
||||
# Uploads the release notes to sourceforge files as "ReadMe.md".
|
||||
#
|
||||
# Note: this function always succeeds, even if the upload fails.
|
||||
# In that case, just a error logging is provided.
|
||||
#
|
||||
function sourceforge_uploadReleaseNotes() {
|
||||
local pmdVersion="$1"
|
||||
local releaseNotes="$2"
|
||||
|
||||
log_debug "$FUNCNAME pmdVersion=$pmdVersion"
|
||||
local targetUrl="https://sourceforge.net/projects/pmd/files/pmd/${pmdVersion}"
|
||||
|
||||
local errexitstate="$(shopt -po errexit)"
|
||||
set +e # disable errexit
|
||||
(
|
||||
# This handler is called if any command fails
|
||||
function release_notes_fail() {
|
||||
log_error "Error while uploading release notes as ReadMe.md to sourceforge!"
|
||||
log_error "Please upload manually: ${targetUrl}"
|
||||
cleanup_temp_dir
|
||||
}
|
||||
|
||||
function cleanup_temp_dir() {
|
||||
log_debug "Cleanup tempdir $releaseNotesTempDir"
|
||||
rm "${releaseNotesTempDir}/${pmdVersion}/ReadMe.md" || true
|
||||
rmdir "${releaseNotesTempDir}/${pmdVersion}" || true
|
||||
rmdir "${releaseNotesTempDir}" || true
|
||||
}
|
||||
|
||||
# exit subshell after trap
|
||||
set -e
|
||||
trap release_notes_fail ERR
|
||||
|
||||
local releaseNotesTempDir=$(mktemp -d)
|
||||
log_debug "Tempdir: $releaseNotesTempDir"
|
||||
mkdir -p "${releaseNotesTempDir}/${pmdVersion}"
|
||||
echo "$releaseNotes" > "${releaseNotesTempDir}/${pmdVersion}/ReadMe.md"
|
||||
|
||||
log_info "Uploading release notes to sourceforge for version $pmdVersion"
|
||||
rsync -avz \
|
||||
"${releaseNotesTempDir}/" \
|
||||
"${PMD_SF_USER}@web.sourceforge.net:/home/frs/project/pmd/pmd/"
|
||||
|
||||
log_success "Successfully uploaded release notes as ReadMe.md to sourceforge: ${targetUrl}"
|
||||
|
||||
cleanup_temp_dir
|
||||
)
|
||||
# restore errexit state
|
||||
eval "$errexitstate"
|
||||
}
|
||||
|
||||
#
|
||||
# Uploads the given file to sourceforge.
|
||||
#
|
||||
# Note: This function always succeeds, even if the upload fails.
|
||||
# In that case, just a error logging is provided.
|
||||
#
|
||||
function sourceforge_uploadFile() {
|
||||
local pmdVersion="$1"
|
||||
local filename="$2"
|
||||
|
||||
log_debug "$FUNCNAME pmdVersion=$pmdVersion filename=$filename"
|
||||
local targetUrl="https://sourceforge.net/projects/pmd/files/pmd/${pmdVersion}"
|
||||
|
||||
local errexitstate="$(shopt -po errexit)"
|
||||
set +e # disable errexit
|
||||
(
|
||||
# This handler is called if any command fails
|
||||
function upload_failed() {
|
||||
log_error "Error while uploading ${filename} to sourceforge!"
|
||||
log_error "Please upload manually: ${targetUrl}"
|
||||
}
|
||||
|
||||
# exit subshell after trap
|
||||
set -e
|
||||
trap upload_failed ERR
|
||||
|
||||
log_info "Uploading $filename to sourceforge..."
|
||||
.travis/travis_wait "rsync -avh ${filename} ${PMD_SF_USER}@web.sourceforge.net:/home/frs/project/pmd/pmd/${pmdVersion}/"
|
||||
log_success "Successfully uploaded ${filename} to sourceforge: ${targetUrl}"
|
||||
)
|
||||
# restore errexit state
|
||||
eval "$errexitstate"
|
||||
}
|
||||
|
||||
#
|
||||
# Select the given version as the new default download.
|
||||
#
|
||||
# Note: This function always succeeds, even if the request fails.
|
||||
# In that case, just a error logging is provided.
|
||||
#
|
||||
function sourceforge_selectDefault() {
|
||||
local pmdVersion="$1"
|
||||
|
||||
log_debug "$FUNCNAME pmdVersion=$pmdVersion"
|
||||
local targetUrl="https://sourceforge.net/projects/pmd/files/pmd/${pmdVersion}"
|
||||
|
||||
local errexitstate="$(shopt -po errexit)"
|
||||
set +e # disable errexit
|
||||
(
|
||||
# This handler is called if any command fails
|
||||
function request_failed() {
|
||||
log_error "Error while selecting ${pmdVersion} as new default download on sourceforge!"
|
||||
log_error "Please do it manually: ${targetUrl}"
|
||||
}
|
||||
|
||||
# exit subshell after trap
|
||||
set -e
|
||||
trap request_failed ERR
|
||||
|
||||
log_info "Selecting $pmdVersion as new default on sourceforge..."
|
||||
local response
|
||||
response=$(curl --fail -s -H "Accept: application/json" \
|
||||
-X PUT \
|
||||
-d "api_key=${PMD_SF_APIKEY}" \
|
||||
-d "default=windows&default=mac&default=linux&default=bsd&default=solaris&default=others" \
|
||||
"https://sourceforge.net/projects/pmd/files/pmd/${pmdVersion}/pmd-bin-${pmdVersion}.zip")
|
||||
log_debug " -> response: $response"
|
||||
log_success "Successfully selected $pmdVersion as new default on sourceforge: ${targetUrl}"
|
||||
)
|
||||
# restore errexit state
|
||||
eval "$errexitstate"
|
||||
}
|
||||
|
||||
#
|
||||
# Rsyncs the complete documentation to sourceforge.
|
||||
#
|
||||
# Note: This function always succeeds, even if the upload fails.
|
||||
# In that case, just a error logging is provided.
|
||||
#
|
||||
function sourceforge_rsyncSnapshotDocumentation() {
|
||||
local pmdVersion="$1"
|
||||
local targetPath="$2"
|
||||
|
||||
log_debug "$FUNCNAME pmdVersion=$pmdVersion targetPath=$targetPath"
|
||||
local targetUrl="https://pmd.sourceforge.io/${targetPath}/"
|
||||
|
||||
local errexitstate="$(shopt -po errexit)"
|
||||
set +e # disable errexit
|
||||
(
|
||||
# This handler is called if any command fails
|
||||
function upload_failed() {
|
||||
log_error "Couldn't upload the documentation. It won't be current on ${targetUrl}"
|
||||
}
|
||||
|
||||
# exit subshell after trap
|
||||
set -e
|
||||
trap upload_failed ERR
|
||||
|
||||
log_info "Uploading documentation to ${targetUrl}..."
|
||||
.travis/travis_wait "rsync -ah --stats --delete docs/pmd-doc-${VERSION}/ ${PMD_SF_USER}@web.sourceforge.net:/home/project-web/pmd/htdocs/snapshot/"
|
||||
log_success "Successfully uploaded documentation: ${targetUrl}"
|
||||
)
|
||||
# restore errexit state
|
||||
eval "$errexitstate"
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
repository: pmd/pmd
|
||||
|
||||
pmd:
|
||||
version: 6.20.0
|
||||
previous_version: 6.19.0
|
||||
date: ??-November-2019
|
||||
version: 6.21.0
|
||||
previous_version: 6.20.0
|
||||
date: ??-December-2019
|
||||
release_type: minor
|
||||
|
||||
# release types: major, minor, bugfix
|
||||
|
@ -352,6 +352,9 @@ entries:
|
||||
- title: Pmdtester
|
||||
url: /pmd_devdocs_pmdtester.html
|
||||
output: web, pdf
|
||||
- title: Rule Deprecation Policy
|
||||
url: /pmd_devdocs_rule_deprecation_policy.html
|
||||
output: web, pdf
|
||||
- title: null
|
||||
output: web, pdf
|
||||
subfolders:
|
||||
|
@ -193,6 +193,10 @@ the breaking API changes will be performed in 7.0.0.
|
||||
an API is tagged as `@Deprecated` or not in the latest minor release. During the development of 7.0.0,
|
||||
we may decide to remove some APIs that were not tagged as deprecated, though we'll try to avoid it." %}
|
||||
|
||||
#### 6.20.0
|
||||
|
||||
No changes.
|
||||
|
||||
#### 6.19.0
|
||||
|
||||
##### Deprecated APIs
|
||||
|
106
docs/pages/pmd/devdocs/rule_deprecation.md
Normal file
106
docs/pages/pmd/devdocs/rule_deprecation.md
Normal file
@ -0,0 +1,106 @@
|
||||
---
|
||||
title: Rule deprecation policy
|
||||
tags: [devdocs]
|
||||
summary: Describes when and how rules are deprecated
|
||||
last_updated: November 15, 2019
|
||||
permalink: pmd_devdocs_rule_deprecation_policy.html
|
||||
author: Andreas Dangel
|
||||
---
|
||||
|
||||
When improving PMD over time, some rules might become obsolete. This could be because the underlying
|
||||
technology a specific rule is checking (such as a specific JVM version) is not relevant anymore or a rule
|
||||
has been replaced by a better implementation.
|
||||
|
||||
In order to remove the requirement to maintain such rules forever, these rules can be marked as **deprecated**.
|
||||
This means, that such rules can entirely be removed in the future.
|
||||
However, the rules must not be removed immediately, since that would break any (custom) ruleset, that
|
||||
references this rule.
|
||||
|
||||
This policy tries to establish some ground rules about how and when rules are deprecated and removed.
|
||||
The main goal is, to maintain compatibility of custom rulesets throughout the deprecation process.
|
||||
|
||||
|
||||
## Renaming rules
|
||||
|
||||
If a rule is enhanced, it might make sense to also rename the rule, to reflect that enhancement. However,
|
||||
simply renaming the rule would break existing (custom) ruleset. Therefore the following procedure should be used:
|
||||
|
||||
* Rename the rule to the new name (and also the rule tests and resources)
|
||||
* Add a deprecated rule reference with the old name, that points to the new rule name:
|
||||
|
||||
`<rule name="OldRuleName" ref="NewRuleName" deprecated="true" />`
|
||||
|
||||
*Note:* When referencing the complete rulesets or categories,
|
||||
these deprecated rule references are ignored, so that the rule is not used twice.
|
||||
|
||||
## Moving rules between categories
|
||||
|
||||
Every rule is in one category. It might happen, that the focus of the rule shifts and it makes more
|
||||
sense, if it would be in a different, better fitting category.
|
||||
|
||||
* Move the rule to the new category (and also the rule tests and resources)
|
||||
* Add a deprecated rule reference in the old category, that points to the rule in the new category:
|
||||
|
||||
`<rule name="MyRule" ref="category/java/errorprone.xml/MyRule" deprecated="true" />`
|
||||
|
||||
*Note:* When referencing the complete rulesets or categories,
|
||||
these deprecated rule references are ignored, so that the rule is not used twice, if both categories
|
||||
are used.
|
||||
|
||||
## Deprecating rules
|
||||
|
||||
Before a rule can be removed, it must have been marked as deprecated:
|
||||
|
||||
```
|
||||
<rule name="MyRule" class="...." deprecated="true">
|
||||
...
|
||||
</rule>
|
||||
```
|
||||
|
||||
This has the effect, that it is **automatically disabled** if the complete ruleset or category
|
||||
is referenced. The rule can still be used, if it is referenced directly.
|
||||
|
||||
The reasons for the deprecation should be explained in the rule description. If there is a replacement rule
|
||||
available, then this rule should be mentioned in the description as well.
|
||||
|
||||
## Removing rules
|
||||
|
||||
Removing rules completely can only be done
|
||||
|
||||
* if the rules have been deprecated before
|
||||
* for a new **major** release.
|
||||
|
||||
Removing a rule from a ruleset or category will break any custom ruleset, that references
|
||||
this rule directly. Therefore rules can only be removed with the next major release of PMD.
|
||||
|
||||
## Rule property compatibility
|
||||
|
||||
Renaming or removing rule properties is not backwards compatible and can only be done
|
||||
with a major release of PMD.
|
||||
|
||||
In order to prepare for the change, properties can be deprecated as well: If the property description
|
||||
starts with the magic string `deprecated!`, then this property is rendered in the rule documentation
|
||||
as deprecated. However, there is no automatic check done if such a property is used and no
|
||||
deprecation warning is issued with the log.
|
||||
|
||||
Therefore, the process for **renaming a property** looks like this:
|
||||
|
||||
* Create a new property with the same type and new name
|
||||
* Prefix the description of the old property with `deprecated!` and also add a explanation
|
||||
either in the property description or in the rule description, which property should be used
|
||||
instead of the deprecated property.
|
||||
* Adjust the rule implementation to first check the old property. If it has a value other than the
|
||||
default value, then the old (deprecated) property has been used and a deprecation warning should
|
||||
be logged. If the new property is used (it has a value other than the default), then it takes
|
||||
preference, but the deprecation warning for the old property should still be issued.
|
||||
* The deprecated property can be removed with the next major release of PMD.
|
||||
|
||||
|
||||
**Changing the default value** of a property might have some results, that make the rule
|
||||
behavioral incompatible: E.g. it could find many more violations with a different default
|
||||
configuration and therefore lead to a sudden increase of violations after a PMD upgrade.
|
||||
It should be judged per case, whether the new default can be considered compatible or not.
|
||||
If it is not compatible, then the new default value should be configured only with the next
|
||||
major release of PMD.
|
||||
|
||||
|
@ -18,7 +18,7 @@ author: Tom Copeland <tom@infoether.org>
|
||||
|
||||
* <a href="http://www.vanwardtechnologies.com/products.php">Vanward Technology's Convergence [link broken]</a> -
|
||||
a quality management dashboard for the Java platform. Thanks to Vanward Technologies for their support of PMD
|
||||
by buying copies of <a href="http://pmdapplied.com/">PMD Applied</a>!
|
||||
by buying copies of <a href="https://pmdapplied.thomasleecopeland.com/">PMD Applied</a>!
|
||||
|
||||
* <a href="http://javacentral.compuware.com/products/optimaladvisor/">Compuware's OptimalAdvisor [link broken]</a>
|
||||
<a href="http://www.componentsource.com/beasv/products/compuware-optimaladvisor/index.html">OptimalAdvisor from ComponentSource</a> -
|
||||
@ -26,8 +26,9 @@ author: Tom Copeland <tom@infoether.org>
|
||||
|
||||
## Books that mention PMD
|
||||
|
||||
* <a href="http://pmdapplied.com">PMD Applied</a> - the official manual; get an extra copy for the home!
|
||||
Or office! Whatever!
|
||||
* <a href="https://pmdapplied.thomasleecopeland.com/">PMD Applied</a> - the official manual by Tom Copeland.
|
||||
|
||||
*Note:* This book is from November 2005 and quite outdated. It discusses PMD 3.
|
||||
|
||||
* <a href="http://www.oreilly.com/catalog/9780596510237">Checking Java Programs</a> - by Ian Darwin;
|
||||
also discusses FindBugs.
|
||||
|
@ -324,8 +324,7 @@ I’ve found that my rules usually don’t work the first time, and so I have to
|
||||
|
||||
As an acceptance test of sorts, I usually run a rule on the JDK 1.4 source code and make sure that a random sampling of the problems found are in fact legitimate rule violations. This also ensures that the rule doesn’t get confused by nested inner classes or any of the other oddities that appear at various points in the JDK source.
|
||||
|
||||
You’re rolling now. If you think a rule would benefit the Java development community as a whole, post a message to [the forum](http://sourceforge.net/p/pmd/discussion/188192) so we can get the rule moved into one of the core rulesets.
|
||||
You’re rolling now. If you think a rule would benefit the (Java) development community as a whole,
|
||||
create a [issue on github](https://github.com/pmd/pmd/issues) so we can get the rule moved into one of the core rulesets.
|
||||
|
||||
Or, if you can improve one of the existing rules, that’d be great too! Thanks!
|
||||
|
||||
Finally, for many more details on writing rules, pick up [PMD Applied](http://pmdapplied.com/)!
|
||||
|
@ -196,6 +196,3 @@ public class ExampleCode {
|
||||
</ruleset>
|
||||
```
|
||||
|
||||
|
||||
|
||||
Finally, for many more details on writing XPath rules, pick up [PMD Applied](http://pmdapplied.com/)!
|
||||
|
@ -21,22 +21,30 @@ This is a {{ site.pmd.release_type }} release.
|
||||
|
||||
### Fixed Issues
|
||||
|
||||
* apex
|
||||
* [#2092](https://github.com/pmd/pmd/issues/2092): \[apex] ApexLexer logs visible when Apex is the selected language upon starting the designer
|
||||
* core
|
||||
* [#2096](https://github.com/pmd/pmd/issues/2096): \[core] Referencing category errorprone.xml produces deprecation warnings for InvalidSlf4jMessageFormat
|
||||
* java
|
||||
* [#1861](https://github.com/pmd/pmd/issues/1861): \[java] Be more lenient with version numbers
|
||||
* [#2105](https://github.com/pmd/pmd/issues/2105): \[java] Wrong name for inner classes in violations
|
||||
|
||||
### API Changes
|
||||
|
||||
|
||||
#### Deprecated APIs
|
||||
|
||||
##### Internal API
|
||||
|
||||
* {% jdoc java::lang.java.JavaLanguageHandler %}
|
||||
* {% jdoc java::lang.java.JavaLanguageParser %}
|
||||
* {% jdoc java::lang.java.JavaDataFlowHandler %}
|
||||
* Implementations of {% jdoc core::lang.rule.RuleViolationFactory %} in each
|
||||
language module, eg {% jdoc java::lang.java.rule.JavaRuleViolationFactory %}.
|
||||
See javadoc of {% jdoc core::lang.rule.RuleViolationFactory %}.
|
||||
* Implementations of {% jdoc core::RuleViolation %} in each language module,
|
||||
eg {% jdoc java::lang.java.rule.JavaRuleViolation %}. See javadoc of
|
||||
{% jdoc core::RuleViolation %}.
|
||||
|
||||
##### For removal
|
||||
|
||||
* {% jdoc java::lang.java.AbstractJavaParser %}
|
||||
* {% jdoc java::lang.java.AbstractJavaHandler %}
|
||||
|
||||
|
||||
### External Contributions
|
||||
|
||||
* [#2088](https://github.com/pmd/pmd/pull/2088): \[java] Add more version shortcuts for older java - [Henning Schmiedehausen](https://github.com/hgschmie)
|
||||
* [#2089](https://github.com/pmd/pmd/pull/2089): \[core] Minor unrelated improvements to code - [Gonzalo Exequiel Ibars Ingman](https://github.com/gibarsin)
|
||||
* [#2091](https://github.com/pmd/pmd/pull/2091): \[core] Fix pmd warnings (IdenticalCatchCases) - [Gonzalo Exequiel Ibars Ingman](https://github.com/gibarsin)
|
||||
* [#2106](https://github.com/pmd/pmd/pull/2106): \[java] Wrong name for inner classes - [Andi Pabst](https://github.com/andipabst)
|
||||
|
||||
{% endtocmaker %}
|
||||
|
||||
|
@ -5,6 +5,50 @@ permalink: pmd_release_notes_old.html
|
||||
|
||||
Previous versions of PMD can be downloaded here: https://github.com/pmd/pmd/releases
|
||||
|
||||
## 29-November-2019 - 6.20.0
|
||||
|
||||
The PMD team is pleased to announce PMD 6.20.0.
|
||||
|
||||
This is a minor release.
|
||||
|
||||
### Table Of Contents
|
||||
|
||||
* [Fixed Issues](#fixed-issues)
|
||||
* [External Contributions](#external-contributions)
|
||||
|
||||
### Fixed Issues
|
||||
|
||||
* apex
|
||||
* [#2092](https://github.com/pmd/pmd/issues/2092): \[apex] ApexLexer logs visible when Apex is the selected language upon starting the designer
|
||||
* [#2136](https://github.com/pmd/pmd/issues/2136): \[apex] Provide access to underlying query of SoqlExpression
|
||||
* core
|
||||
* [#2002](https://github.com/pmd/pmd/issues/2002): \[doc] Issue with http://pmdapplied.com/ linking to a gambling Web site
|
||||
* [#2062](https://github.com/pmd/pmd/issues/2062): \[core] Shortnames parameter does not work with Ant
|
||||
* [#2090](https://github.com/pmd/pmd/issues/2090): \[ci] Release notes and draft releases
|
||||
* [#2096](https://github.com/pmd/pmd/issues/2096): \[core] Referencing category errorprone.xml produces deprecation warnings for InvalidSlf4jMessageFormat
|
||||
* java
|
||||
* [#1861](https://github.com/pmd/pmd/issues/1861): \[java] Be more lenient with version numbers
|
||||
* [#2105](https://github.com/pmd/pmd/issues/2105): \[java] Wrong name for inner classes in violations
|
||||
* java-bestpractices
|
||||
* [#2016](https://github.com/pmd/pmd/issues/2016): \[java] UnusedImports: False positive if wildcard is used and only static methods
|
||||
* java-codestyle
|
||||
* [#1362](https://github.com/pmd/pmd/issues/1362): \[java] LinguisticNaming flags Predicates with boolean-style names
|
||||
* [#2029](https://github.com/pmd/pmd/issues/2029): \[java] UnnecessaryFullyQualifiedName false-positive for non-static nested classes
|
||||
* [#2098](https://github.com/pmd/pmd/issues/2098): \[java] UnnecessaryFullyQualifiedName: regression / false positive
|
||||
* java-design
|
||||
* [#2075](https://github.com/pmd/pmd/issues/2075): \[java] ImmutableField false positive with inner class
|
||||
* [#2125](https://github.com/pmd/pmd/issues/2125): \[java] ImmutableField: False positive when variable is updated in conditional loop
|
||||
* java-errorprone
|
||||
* [#2102](https://github.com/pmd/pmd/issues/2102): \[java] False positive MissingStaticMethodInNonInstantiatableClass when inheritors are instantiable
|
||||
|
||||
### External Contributions
|
||||
|
||||
* [#2088](https://github.com/pmd/pmd/pull/2088): \[java] Add more version shortcuts for older java - [Henning Schmiedehausen](https://github.com/hgschmie)
|
||||
* [#2089](https://github.com/pmd/pmd/pull/2089): \[core] Minor unrelated improvements to code - [Gonzalo Exequiel Ibars Ingman](https://github.com/gibarsin)
|
||||
* [#2091](https://github.com/pmd/pmd/pull/2091): \[core] Fix pmd warnings (IdenticalCatchCases) - [Gonzalo Exequiel Ibars Ingman](https://github.com/gibarsin)
|
||||
* [#2106](https://github.com/pmd/pmd/pull/2106): \[java] Wrong name for inner classes - [Andi Pabst](https://github.com/andipabst)
|
||||
* [#2121](https://github.com/pmd/pmd/pull/2121): \[java] Predicates treated like booleans - [Ozan Gulle](https://github.com/ozangulle)
|
||||
|
||||
## 31-October-2019 - 6.19.0
|
||||
|
||||
The PMD team is pleased to announce PMD 6.19.0.
|
||||
@ -7630,5 +7674,3 @@ The binary package still contains all languages and can be used as usual. Have a
|
||||
## June 25 2002 - 0.1:
|
||||
|
||||
Initial release
|
||||
|
||||
The PMD book - $20 - http://pmdapplied.com/
|
||||
|
@ -11,7 +11,6 @@ import net.sourceforge.pmd.lang.AbstractPmdLanguageVersionHandler;
|
||||
import net.sourceforge.pmd.lang.Parser;
|
||||
import net.sourceforge.pmd.lang.ParserOptions;
|
||||
import net.sourceforge.pmd.lang.VisitorStarter;
|
||||
import net.sourceforge.pmd.lang.XPathHandler;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTMethod;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTUserClassOrInterface;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ApexNode;
|
||||
@ -19,8 +18,7 @@ import net.sourceforge.pmd.lang.apex.metrics.ApexMetricsComputer;
|
||||
import net.sourceforge.pmd.lang.apex.metrics.api.ApexClassMetricKey;
|
||||
import net.sourceforge.pmd.lang.apex.metrics.api.ApexOperationMetricKey;
|
||||
import net.sourceforge.pmd.lang.apex.multifile.ApexMultifileVisitorFacade;
|
||||
import net.sourceforge.pmd.lang.apex.rule.ApexRuleViolationFactory;
|
||||
import net.sourceforge.pmd.lang.ast.xpath.DefaultASTXPathHandler;
|
||||
import net.sourceforge.pmd.lang.apex.rule.internal.ApexRuleViolationFactory;
|
||||
import net.sourceforge.pmd.lang.metrics.LanguageMetricsProvider;
|
||||
import net.sourceforge.pmd.lang.metrics.internal.AbstractLanguageMetricsProvider;
|
||||
import net.sourceforge.pmd.lang.rule.RuleViolationFactory;
|
||||
@ -35,12 +33,6 @@ public class ApexHandler extends AbstractPmdLanguageVersionHandler {
|
||||
return rootNode -> new ApexMultifileVisitorFacade().initializeWith((ApexNode<?>) rootNode);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public XPathHandler getXPathHandler() {
|
||||
return new DefaultASTXPathHandler();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RuleViolationFactory getRuleViolationFactory() {
|
||||
return ApexRuleViolationFactory.INSTANCE;
|
||||
|
@ -5,7 +5,6 @@
|
||||
package net.sourceforge.pmd.lang.apex;
|
||||
|
||||
import java.io.Reader;
|
||||
import java.util.Map;
|
||||
|
||||
import net.sourceforge.pmd.lang.AbstractParser;
|
||||
import net.sourceforge.pmd.lang.ParserOptions;
|
||||
@ -34,8 +33,4 @@ public class ApexParser extends AbstractParser {
|
||||
return apexParser.parse(source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Integer, String> getSuppressMap() {
|
||||
return apexParser.getSuppressMap();
|
||||
}
|
||||
}
|
||||
|
@ -16,4 +16,8 @@ public class ASTSoqlExpression extends AbstractApexNode<SoqlExpression> {
|
||||
public Object jjtAccept(ApexParserVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
|
||||
public String getQuery() {
|
||||
return getNode().getRawQuery();
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,9 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.apex.ast;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.RootNode;
|
||||
import net.sourceforge.pmd.lang.ast.SourceCodePositioner;
|
||||
|
||||
@ -11,6 +14,9 @@ import apex.jorje.semantic.ast.AstNode;
|
||||
import apex.jorje.services.Version;
|
||||
|
||||
public abstract class ApexRootNode<T extends AstNode> extends AbstractApexNode<T> implements RootNode {
|
||||
|
||||
private Map<Integer, String> noPmdComments = Collections.emptyMap();
|
||||
|
||||
public ApexRootNode(T node) {
|
||||
super(node);
|
||||
}
|
||||
@ -32,4 +38,14 @@ public abstract class ApexRootNode<T extends AstNode> extends AbstractApexNode<T
|
||||
public double getApexVersion() {
|
||||
return getNode().getDefiningType().getCodeUnitDetails().getVersion().getExternal();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Map<Integer, String> getNoPmdComments() {
|
||||
return noPmdComments;
|
||||
}
|
||||
|
||||
void setNoPmdComments(Map<Integer, String> noPmdComments) {
|
||||
this.noPmdComments = noPmdComments;
|
||||
}
|
||||
}
|
||||
|
@ -1,69 +0,0 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.lang.apex.rule;
|
||||
|
||||
import net.sourceforge.pmd.Rule;
|
||||
import net.sourceforge.pmd.RuleContext;
|
||||
import net.sourceforge.pmd.lang.apex.ast.CanSuppressWarnings;
|
||||
import net.sourceforge.pmd.lang.ast.Node;
|
||||
import net.sourceforge.pmd.lang.rule.ParametricRuleViolation;
|
||||
|
||||
/**
|
||||
* This is an Apex RuleViolation. It knows how to try to extract the following
|
||||
* extra information from the violation node:
|
||||
* <ul>
|
||||
* <li>Package name</li>
|
||||
* <li>Class name</li>
|
||||
* <li>Method name</li>
|
||||
* <li>Variable name</li>
|
||||
* <li>Suppression indicator</li>
|
||||
* </ul>
|
||||
* @param <T>
|
||||
*/
|
||||
@SuppressWarnings("PMD.UseUtilityClass") // we inherit non-static methods...
|
||||
public class ApexRuleViolation<T> extends ParametricRuleViolation<Node> {
|
||||
|
||||
public ApexRuleViolation(Rule rule, RuleContext ctx, Node node, String message, int beginLine, int endLine) {
|
||||
this(rule, ctx, node, message);
|
||||
|
||||
setLines(beginLine, endLine);
|
||||
}
|
||||
|
||||
public ApexRuleViolation(Rule rule, RuleContext ctx, Node node, String message) {
|
||||
super(rule, ctx, node, message);
|
||||
|
||||
if (node != null) {
|
||||
if (!suppressed) {
|
||||
suppressed = isSupressed(node, getRule());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for suppression on this node, on parents, and on contained types
|
||||
* for ASTCompilationUnit
|
||||
*
|
||||
* @deprecated Is internal API, not useful, there's a typo. See <a href="https://github.com/pmd/pmd/pull/1927">#1927</a>
|
||||
*/
|
||||
@Deprecated
|
||||
public static boolean isSupressed(Node node, Rule rule) {
|
||||
boolean result = suppresses(node, rule);
|
||||
|
||||
if (!result) {
|
||||
Node parent = node.jjtGetParent();
|
||||
while (!result && parent != null) {
|
||||
result = suppresses(parent, rule);
|
||||
parent = parent.jjtGetParent();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static boolean suppresses(final Node node, Rule rule) {
|
||||
return node instanceof CanSuppressWarnings
|
||||
&& ((CanSuppressWarnings) node).hasSuppressWarningsAnnotationFor(rule);
|
||||
}
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.lang.apex.rule;
|
||||
|
||||
import net.sourceforge.pmd.Rule;
|
||||
import net.sourceforge.pmd.RuleContext;
|
||||
import net.sourceforge.pmd.RuleViolation;
|
||||
import net.sourceforge.pmd.lang.ast.Node;
|
||||
import net.sourceforge.pmd.lang.rule.AbstractRuleViolationFactory;
|
||||
|
||||
public final class ApexRuleViolationFactory extends AbstractRuleViolationFactory {
|
||||
|
||||
public static final ApexRuleViolationFactory INSTANCE = new ApexRuleViolationFactory();
|
||||
|
||||
private ApexRuleViolationFactory() {
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Override
|
||||
protected RuleViolation createRuleViolation(Rule rule, RuleContext ruleContext, Node node, String message) {
|
||||
return new ApexRuleViolation<>(rule, ruleContext, node, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("rawtypes")
|
||||
protected RuleViolation createRuleViolation(Rule rule, RuleContext ruleContext, Node node, String message,
|
||||
int beginLine, int endLine) {
|
||||
return new ApexRuleViolation(rule, ruleContext, node, message, beginLine, endLine);
|
||||
}
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.lang.apex.rule.internal;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
import net.sourceforge.pmd.Report;
|
||||
import net.sourceforge.pmd.Report.SuppressedViolation;
|
||||
import net.sourceforge.pmd.Rule;
|
||||
import net.sourceforge.pmd.RuleViolation;
|
||||
import net.sourceforge.pmd.ViolationSuppressor;
|
||||
import net.sourceforge.pmd.lang.apex.ast.CanSuppressWarnings;
|
||||
import net.sourceforge.pmd.lang.ast.Node;
|
||||
import net.sourceforge.pmd.lang.rule.impl.DefaultRuleViolationFactory;
|
||||
|
||||
public final class ApexRuleViolationFactory extends DefaultRuleViolationFactory {
|
||||
|
||||
public static final ApexRuleViolationFactory INSTANCE = new ApexRuleViolationFactory();
|
||||
private static final ViolationSuppressor APEX_ANNOT_SUPPRESSOR = new ViolationSuppressor() {
|
||||
@Override
|
||||
public String getId() {
|
||||
return "@SuppressWarnings";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Report.SuppressedViolation suppressOrNull(RuleViolation rv, @NonNull Node node) {
|
||||
if (isSuppressed(node, rv.getRule())) {
|
||||
return new SuppressedViolation(rv, this, null);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
private ApexRuleViolationFactory() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<ViolationSuppressor> getSuppressors() {
|
||||
return Collections.singletonList(APEX_ANNOT_SUPPRESSOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for suppression on this node, on parents, and on contained types
|
||||
* for ASTCompilationUnit
|
||||
*
|
||||
* @param node
|
||||
*/
|
||||
private static boolean isSuppressed(Node node, Rule rule) {
|
||||
boolean result = suppresses(node, rule);
|
||||
|
||||
if (!result) {
|
||||
Node parent = node.jjtGetParent();
|
||||
while (!result && parent != null) {
|
||||
result = suppresses(parent, rule);
|
||||
parent = parent.jjtGetParent();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static boolean suppresses(final Node node, Rule rule) {
|
||||
return node instanceof CanSuppressWarnings
|
||||
&& ((CanSuppressWarnings) node).hasSuppressWarningsAnnotationFor(rule);
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.lang.apex.ast;
|
||||
|
||||
import static net.sourceforge.pmd.lang.apex.ast.ApexParserTestHelpers.parse;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import apex.jorje.semantic.ast.compilation.Compilation;
|
||||
|
||||
public class ASTSoqlExpressionTest {
|
||||
|
||||
@Test
|
||||
public void testQuery() {
|
||||
ApexNode<Compilation> node = parse("class Foo { void test1() { Account acc = [SELECT 1 FROM Account]; } }");
|
||||
ASTSoqlExpression soqlExpression = node.getFirstDescendantOfType(ASTSoqlExpression.class);
|
||||
Assert.assertEquals("SELECT 1 FROM Account", soqlExpression.getQuery());
|
||||
}
|
||||
}
|
@ -42,7 +42,6 @@ public class Report implements Iterable<RuleViolation> {
|
||||
private final List<ThreadSafeReportListener> listeners = new ArrayList<>();
|
||||
private List<ProcessingError> errors;
|
||||
private List<ConfigurationError> configErrors;
|
||||
private Map<Integer, String> linesToSuppress = new HashMap<>();
|
||||
private long start;
|
||||
private long end;
|
||||
private List<SuppressedViolation> suppressedRuleViolations = new ArrayList<>();
|
||||
@ -177,72 +176,6 @@ public class Report implements Iterable<RuleViolation> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a violation, that has been suppressed.
|
||||
*/
|
||||
public static class SuppressedViolation {
|
||||
private final RuleViolation rv;
|
||||
private final boolean isNOPMD;
|
||||
private final String userMessage;
|
||||
|
||||
/**
|
||||
* Creates a suppressed violation.
|
||||
*
|
||||
* @param rv
|
||||
* the actual violation, that has been suppressed
|
||||
* @param isNOPMD
|
||||
* the suppression mode: <code>true</code> if it is
|
||||
* suppressed via a NOPMD comment, <code>false</code> if
|
||||
* suppressed via annotations.
|
||||
* @param userMessage
|
||||
* contains the suppressed code line or <code>null</code>
|
||||
*/
|
||||
public SuppressedViolation(RuleViolation rv, boolean isNOPMD, String userMessage) {
|
||||
this.isNOPMD = isNOPMD;
|
||||
this.rv = rv;
|
||||
this.userMessage = userMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if the violation has been suppressed via a
|
||||
* NOPMD comment.
|
||||
*
|
||||
* @return <code>true</code> if the violation has been suppressed via a
|
||||
* NOPMD comment.
|
||||
*/
|
||||
public boolean suppressedByNOPMD() {
|
||||
return this.isNOPMD;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if the violation has been suppressed via a
|
||||
* annotation.
|
||||
*
|
||||
* @return <code>true</code> if the violation has been suppressed via a
|
||||
* annotation.
|
||||
*/
|
||||
public boolean suppressedByAnnotation() {
|
||||
return !this.isNOPMD;
|
||||
}
|
||||
|
||||
public RuleViolation getRuleViolation() {
|
||||
return this.rv;
|
||||
}
|
||||
|
||||
public String getUserMessage() {
|
||||
return userMessage;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the lines, that are suppressed via a NOPMD comment.
|
||||
*
|
||||
* @param lines
|
||||
* the suppressed lines
|
||||
*/
|
||||
public void suppress(Map<Integer, String> lines) {
|
||||
linesToSuppress = lines;
|
||||
}
|
||||
|
||||
private static String keyFor(RuleViolation rv) {
|
||||
|
||||
@ -301,6 +234,46 @@ public class Report implements Iterable<RuleViolation> {
|
||||
return suppressedRuleViolations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a violation, that has been suppressed.
|
||||
* TODO this should implement RuleViolation
|
||||
*/
|
||||
public static class SuppressedViolation {
|
||||
private final RuleViolation rv;
|
||||
private final String userMessage;
|
||||
private final ViolationSuppressor suppressor;
|
||||
|
||||
/**
|
||||
* Creates a suppressed violation.
|
||||
*
|
||||
* @param rv The violation, that has been suppressed
|
||||
* @param suppressor The suppressor which suppressed the violation
|
||||
* @param userMessage Any relevant info given by the suppressor
|
||||
*/
|
||||
public SuppressedViolation(RuleViolation rv, ViolationSuppressor suppressor, String userMessage) {
|
||||
this.suppressor = suppressor;
|
||||
this.rv = rv;
|
||||
this.userMessage = userMessage;
|
||||
}
|
||||
|
||||
public ViolationSuppressor getSuppressor() {
|
||||
return suppressor;
|
||||
}
|
||||
|
||||
public RuleViolation getRuleViolation() {
|
||||
return this.rv;
|
||||
}
|
||||
|
||||
public String getUserMessage() {
|
||||
return userMessage;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void addSuppressedViolation(SuppressedViolation sv) {
|
||||
suppressedRuleViolations.add(sv);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new rule violation to the report and notify the listeners.
|
||||
*
|
||||
@ -308,19 +281,6 @@ public class Report implements Iterable<RuleViolation> {
|
||||
* the violation to add
|
||||
*/
|
||||
public void addRuleViolation(RuleViolation violation) {
|
||||
|
||||
// NOPMD suppress
|
||||
int line = violation.getBeginLine();
|
||||
if (linesToSuppress.containsKey(line)) {
|
||||
suppressedRuleViolations.add(new SuppressedViolation(violation, true, linesToSuppress.get(line)));
|
||||
return;
|
||||
}
|
||||
|
||||
if (violation.isSuppressed()) {
|
||||
suppressedRuleViolations.add(new SuppressedViolation(violation, false, null));
|
||||
return;
|
||||
}
|
||||
|
||||
int index = Collections.binarySearch(violations, violation, RuleViolationComparator.INSTANCE);
|
||||
violations.add(index < 0 ? -index - 1 : index, violation);
|
||||
violationTree.addRuleViolation(violation);
|
||||
|
@ -6,7 +6,11 @@ package net.sourceforge.pmd;
|
||||
|
||||
/**
|
||||
* A RuleViolation is created by a Rule when it identifies a violation of the
|
||||
* Rule constraints.
|
||||
* Rule constraints. RuleViolations are simple data holders that are collected
|
||||
* into a {@link Report}.
|
||||
*
|
||||
* <p>Since PMD 6.21.0, implementations of this interface are considered internal
|
||||
* API and hence deprecated. Clients should exclusively use this interface.
|
||||
*
|
||||
* @see Rule
|
||||
*/
|
||||
@ -26,13 +30,6 @@ public interface RuleViolation {
|
||||
*/
|
||||
String getDescription();
|
||||
|
||||
/**
|
||||
* Indicates whether this violation has been suppressed.
|
||||
*
|
||||
* @return <code>true</code> if this violation is suppressed,
|
||||
* <code>false</code> otherwise.
|
||||
*/
|
||||
boolean isSuppressed();
|
||||
|
||||
/**
|
||||
* Get the source file name in which this violation was identified.
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user