diff --git a/.all-contributorsrc b/.all-contributorsrc index ce485028d8..21a93ff2c9 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -7145,6 +7145,34 @@ "bug", "code" ] + }, + { + "login": "nwcm", + "name": "nwcm", + "avatar_url": "https://avatars.githubusercontent.com/u/111259588?v=4", + "profile": "https://github.com/nwcm", + "contributions": [ + "doc" + ] + }, + { + "login": "PimvanderLoos", + "name": "Pim van der Loos", + "avatar_url": "https://avatars.githubusercontent.com/u/3114723?v=4", + "profile": "https://github.com/PimvanderLoos", + "contributions": [ + "code", + "test" + ] + }, + { + "login": "joaodinissf", + "name": "João Dinis Ferreira", + "avatar_url": "https://avatars.githubusercontent.com/u/6786818?v=4", + "profile": "https://github.com/joaodinissf", + "contributions": [ + "doc" + ] } ], "contributorsPerLine": 7, diff --git a/.ci/README.md b/.ci/README.md index 87250d6ba7..6286fd14b4 100644 --- a/.ci/README.md +++ b/.ci/README.md @@ -138,7 +138,7 @@ f=check-environment.sh; \ Calling `.ci/build.sh` directly would re-release the tag $TAG_NAME - that's why it is commented out. All the side-effects of a release would be carried out like creating and publishing a release on github, -uploading the release to sourceforge, uploading the docs to pmd.github.io/docs.pmd-code.org, uploading a +uploading the release to sourceforge, uploading the docs to docs.pmd-code.org, uploading a new baseline for the regression tester and so on. While the release should be reproducible and therefore should produce exactly the same artifacts, re-uploading artifacts is not desired just for testing. diff --git a/.ci/build.sh b/.ci/build.sh index 5f4d321698..ac5986007b 100755 --- a/.ci/build.sh +++ b/.ci/build.sh @@ -55,6 +55,13 @@ function build() { # stop early for invalid maven version and branch/tag combination pmd_ci_maven_verify_version || exit 0 + # skip tests when doing a release build - this makes the process faster + # it's a manual task now to verify that a release is only started, when the main branch + # was green before. This is usually checked via a local build, see ./do-release.sh + if pmd_ci_maven_isReleaseBuild; then + PMD_MAVEN_EXTRA_OPTS+=(-DskipTests=true) + fi + if [ "$(pmd_ci_utils_get_os)" != "linux" ]; then pmd_ci_log_group_start "Build with mvnw" ./mvnw clean verify --show-version --errors --batch-mode --no-transfer-progress "${PMD_MAVEN_EXTRA_OPTS[@]}" @@ -179,6 +186,11 @@ function pmd_ci_deploy_build_artifacts() { # Deploy to sourceforge files https://sourceforge.net/projects/pmd/files/pmd/ pmd_ci_sourceforge_uploadFile "pmd/${PMD_CI_MAVEN_PROJECT_VERSION}" "pmd-dist/target/pmd-bin-${PMD_CI_MAVEN_PROJECT_VERSION}.zip" pmd_ci_sourceforge_uploadFile "pmd/${PMD_CI_MAVEN_PROJECT_VERSION}" "pmd-dist/target/pmd-src-${PMD_CI_MAVEN_PROJECT_VERSION}.zip" + # Deploy SBOM + cp pmd-dist/target/bom.xml "pmd-dist/target/pmd-${PMD_CI_MAVEN_PROJECT_VERSION}-cyclonedx.xml" + cp pmd-dist/target/bom.json "pmd-dist/target/pmd-${PMD_CI_MAVEN_PROJECT_VERSION}-cyclonedx.json" + pmd_ci_sourceforge_uploadFile "pmd/${PMD_CI_MAVEN_PROJECT_VERSION}" "pmd-dist/target/pmd-${PMD_CI_MAVEN_PROJECT_VERSION}-cyclonedx.xml" + pmd_ci_sourceforge_uploadFile "pmd/${PMD_CI_MAVEN_PROJECT_VERSION}" "pmd-dist/target/pmd-${PMD_CI_MAVEN_PROJECT_VERSION}-cyclonedx.json" if pmd_ci_maven_isReleaseBuild; then # create a draft github release @@ -188,6 +200,9 @@ function pmd_ci_deploy_build_artifacts() { # Deploy to github releases pmd_ci_gh_releases_uploadAsset "$GH_RELEASE" "pmd-dist/target/pmd-bin-${PMD_CI_MAVEN_PROJECT_VERSION}.zip" pmd_ci_gh_releases_uploadAsset "$GH_RELEASE" "pmd-dist/target/pmd-src-${PMD_CI_MAVEN_PROJECT_VERSION}.zip" + # Deploy SBOM + pmd_ci_gh_releases_uploadAsset "$GH_RELEASE" "pmd-dist/target/pmd-${PMD_CI_MAVEN_PROJECT_VERSION}-cyclonedx.xml" + pmd_ci_gh_releases_uploadAsset "$GH_RELEASE" "pmd-dist/target/pmd-${PMD_CI_MAVEN_PROJECT_VERSION}-cyclonedx.json" fi } @@ -224,7 +239,7 @@ function pmd_ci_build_and_upload_doc() { pmd_ci_sourceforge_uploadReleaseNotes "pmd/${PMD_CI_MAVEN_PROJECT_VERSION}" "${rendered_release_notes}" if pmd_ci_maven_isSnapshotBuild && [ "${PMD_CI_BRANCH}" = "master" ]; then - # only for snapshot builds from branch master + # only for snapshot builds from branch master: https://docs.pmd-code.org/snapshot -> pmd-doc-${PMD_CI_MAVEN_PROJECT_VERSION} pmd_code_createSymlink "${PMD_CI_MAVEN_PROJECT_VERSION}" "snapshot" # update github pages https://pmd.github.io/pmd/ @@ -249,14 +264,12 @@ function pmd_ci_build_and_upload_doc() { local rendered_release_notes_with_links rendered_release_notes_with_links=" * Downloads: https://github.com/pmd/pmd/releases/tag/pmd_releases%2F${PMD_CI_MAVEN_PROJECT_VERSION} -* Documentation: https://pmd.github.io/pmd-${PMD_CI_MAVEN_PROJECT_VERSION}/ +* Documentation: https://docs.pmd-code.org/pmd-doc-${PMD_CI_MAVEN_PROJECT_VERSION}/ ${rendered_release_notes}" pmd_ci_sourceforge_createDraftBlogPost "${release_name} released" "${rendered_release_notes_with_links}" "pmd,release" SF_BLOG_URL="${RESULT}" - # updates https://pmd.github.io/latest/ and https://pmd.github.io/pmd-${PMD_CI_MAVEN_PROJECT_VERSION} - publish_release_documentation_github # rsync site to https://pmd.sourceforge.io/pmd-${PMD_CI_MAVEN_PROJECT_VERSION} pmd_ci_sourceforge_rsyncSnapshotDocumentation "${PMD_CI_MAVEN_PROJECT_VERSION}" "pmd-${PMD_CI_MAVEN_PROJECT_VERSION}" fi diff --git a/.ci/inc/pmd-doc.inc b/.ci/inc/pmd-doc.inc index 4a6d5acc14..8969f8a4d8 100644 --- a/.ci/inc/pmd-doc.inc +++ b/.ci/inc/pmd-doc.inc @@ -42,55 +42,7 @@ function pmd_doc_create_archive() { } # -# Publishes the site to https://pmd.github.io/pmd-${PMD_CI_MAVEN_PROJECT_VERSION} and -# https://pmd.github.io/latest/ -# -function publish_release_documentation_github() { - echo -e "\n\n" - pmd_ci_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 || { echo "Directory 'pmd.github.io' doesn't exist"; exit 1; } - git init - git config user.name "PMD CI (pmd-bot)" - git config user.email "pmd-bot@users.noreply.github.com" - git config core.sparsecheckout true - git remote add origin git@github.com-pmd.github.io:pmd/pmd.github.io.git - echo "/latest/" > .git/info/sparse-checkout - echo "/sitemap.xml" >> .git/info/sparse-checkout - git pull --depth=1 origin master - pmd_ci_log_info "Copying documentation from ../docs/pmd-doc-${PMD_CI_MAVEN_PROJECT_VERSION}/ to pmd-${PMD_CI_MAVEN_PROJECT_VERSION}/ ..." - rsync -ah --stats "../docs/pmd-doc-${PMD_CI_MAVEN_PROJECT_VERSION}/" "pmd-${PMD_CI_MAVEN_PROJECT_VERSION}/" - git status - pmd_ci_log_debug "Executing: git add pmd-${PMD_CI_MAVEN_PROJECT_VERSION}" - git add --sparse "pmd-${PMD_CI_MAVEN_PROJECT_VERSION}" - pmd_ci_log_debug "Executing: git commit..." - git commit -q -m "Added pmd-${PMD_CI_MAVEN_PROJECT_VERSION}" - - pmd_ci_log_info "Copying pmd-${PMD_CI_MAVEN_PROJECT_VERSION} to latest ..." - git rm -qr latest - cp -a "pmd-${PMD_CI_MAVEN_PROJECT_VERSION}" latest - pmd_ci_log_debug "Executing: git add latest" - git add latest - pmd_ci_log_debug "Executing: git commit..." - git commit -q -m "Copying pmd-${PMD_CI_MAVEN_PROJECT_VERSION} to latest" - - pmd_ci_log_info "Generating sitemap.xml" - ../docs/sitemap_generator.sh > sitemap.xml - pmd_ci_log_debug "Executing: git add sitemap.xml" - git add sitemap.xml - pmd_ci_log_debug "Executing: git commit..." - git commit -q -m "Generated sitemap.xml" - - pmd_ci_log_info "Executing: git push origin master" - git push origin master - ) -} - -# -# Updates github pages of the main repository, +# Updates github pages branch "gh-pages" of the main repository, # so that https://pmd.github.io/pmd/ has the latest (snapshot) content # function pmd_doc_publish_to_github_pages() { diff --git a/.github/ISSUE_TEMPLATE/0rule_violation_false-positive.md b/.github/ISSUE_TEMPLATE/0rule_violation_false-positive.md index 8faed7c14a..9daab4f380 100644 --- a/.github/ISSUE_TEMPLATE/0rule_violation_false-positive.md +++ b/.github/ISSUE_TEMPLATE/0rule_violation_false-positive.md @@ -13,7 +13,7 @@ assignees: '' **Rule:** Please provide the rule name and a link to the rule documentation: - + **Description:** diff --git a/.github/ISSUE_TEMPLATE/1rule_violation_false-negative.md b/.github/ISSUE_TEMPLATE/1rule_violation_false-negative.md index 51702e0038..d6ae5c5d0d 100644 --- a/.github/ISSUE_TEMPLATE/1rule_violation_false-negative.md +++ b/.github/ISSUE_TEMPLATE/1rule_violation_false-negative.md @@ -13,7 +13,7 @@ assignees: '' **Rule:** Please provide the rule name and a link to the rule documentation: - + **Description:** diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ed97a2878b..b4fe5f9d27 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -33,11 +33,11 @@ When filing a bug report, please provide as much information as possible, so tha ## Documentation -There is some documentation available under . Feel free to create a bug report if +There is some documentation available under . Feel free to create a bug report if documentation is missing, incomplete or outdated. See [Bug reports](#bug-reports). The documentation is generated as a Jekyll site, the source is available at: . You can find build instructions there. -For more on contributing documentation check +For more on contributing documentation check ## Questions diff --git a/Gemfile.lock b/Gemfile.lock index aa09f3659b..d96519a4e1 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ GEM remote: https://rubygems.org/ specs: - addressable (2.8.1) + addressable (2.8.4) public_suffix (>= 2.0.2, < 6.0) claide (1.1.0) claide-plugins (0.9.2) @@ -31,13 +31,13 @@ GEM faraday (2.7.4) faraday-net_http (>= 2.0, < 3.1) ruby2_keywords (>= 0.0.4) - faraday-http-cache (2.4.1) + faraday-http-cache (2.5.0) faraday (>= 0.8) faraday-net_http (3.0.2) fugit (1.8.1) et-orbi (~> 1, >= 1.2.7) raabro (~> 1.4) - git (1.17.2) + git (1.18.0) addressable (~> 2.8) rchardet (~> 1.8) kramdown (2.4.0) @@ -49,7 +49,7 @@ GEM mini_portile2 (2.8.1) nap (1.1.0) no_proxy_fix (0.1.2) - nokogiri (1.14.2) + nokogiri (1.14.3) mini_portile2 (~> 2.8.0) racc (~> 1.4) octokit (5.6.1) diff --git a/README.md b/README.md index 5fe24a5db5..382eb8ca61 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ [![Coverage Status](https://coveralls.io/repos/github/pmd/pmd/badge.svg)](https://coveralls.io/github/pmd/pmd) [![Codacy Badge](https://app.codacy.com/project/badge/Grade/ea550046a02344ec850553476c4aa2ca)](https://www.codacy.com/gh/pmd/pmd/dashboard?utm_source=github.com&utm_medium=referral&utm_content=pmd/pmd&utm_campaign=Badge_Grade) [![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-v2.0%20adopted-ff69b4.svg)](code_of_conduct.md) -[![Documentation (latest)](https://img.shields.io/badge/docs-latest-green)](https://pmd.github.io/latest/) +[![Documentation (latest)](https://img.shields.io/badge/docs-latest-green)](https://docs.pmd-code.org/latest/) **PMD** is a source code analyzer. It finds common programming flaws like unused variables, empty catch blocks, unnecessary object creation, and so forth. It supports many languages. It can be extended with custom rules. @@ -32,9 +32,9 @@ it makes sense. Download the latest binary zip from the [releases](https://github.com/pmd/pmd/releases/latest) and extract it somewhere. -Execute `bin/run.sh pmd` or `bin\pmd.bat`. +Execute `bin/pmd check` or `bin\pmd.bat check`. -See also [Getting Started](https://pmd.github.io/latest/pmd_userdocs_installation.html) +See also [Getting Started](https://docs.pmd-code.org/latest/pmd_userdocs_installation.html) **Demo:** @@ -43,7 +43,7 @@ This shows how PMD can detect for loops, that can be replaced by for-each loops. ![Demo](docs/images/userdocs/pmd-demo.gif) There are plugins for Maven and Gradle as well as for various IDEs. -See [Tools / Integrations](https://pmd.github.io/latest/pmd_userdocs_tools.html) +See [Tools / Integrations](https://docs.pmd-code.org/latest/pmd_userdocs_tools.html) ## ℹ️ How to get support? @@ -54,7 +54,7 @@ See [Tools / Integrations](https://pmd.github.io/latest/pmd_userdocs_tools.html) * I got this error and I'm sure it's a bug -- file an [issue](https://github.com/pmd/pmd/issues). * I have an idea/request/question -- create a new [discussion](https://github.com/pmd/pmd/discussions). * I have a quick question -- ask in our [Gitter room](https://app.gitter.im/#/room/#pmd_pmd:gitter.im). -* Where's your documentation? -- +* Where's your documentation? -- ## 🤝 Contributing diff --git a/do-release.sh b/do-release.sh index 7a42d9be4e..60d060c944 100755 --- a/do-release.sh +++ b/do-release.sh @@ -165,26 +165,13 @@ git commit -a -m "Prepare pmd release ${RELEASE_VERSION}" fi ) -# for release candidates, allow snapshot dependencies -if [[ "${RELEASE_VERSION}" == *-rc* ]]; then - ./mvnw versions:set -DnewVersion="${RELEASE_VERSION}" -DgenerateBackupPoms=false - git commit -S -a -m "[release] prepare release pmd_releases/${RELEASE_VERSION}" - git tag -a -s -m "[release] tag pmd_releases/${RELEASE_VERSION}" "pmd_releases/${RELEASE_VERSION}" - # test build - ./mvnw clean verify -Denforcer.skip=true - ./mvnw versions:set -DnewVersion="${DEVELOPMENT_VERSION}" -DgenerateBackupPoms=false - git commit -S -a -m "[release] prepare for next development iteration" - # push - git push origin - git push origin tag "pmd_releases/${RELEASE_VERSION}" -else - ./mvnw -B release:clean release:prepare \ - -Dtag="pmd_releases/${RELEASE_VERSION}" \ - -DreleaseVersion="${RELEASE_VERSION}" \ - -DdevelopmentVersion="${DEVELOPMENT_VERSION}" \ - -DscmCommentPrefix="[release] " \ - -Pgenerate-rule-docs -fi +./mvnw -B release:clean release:prepare \ + -Dtag="pmd_releases/${RELEASE_VERSION}" \ + -DreleaseVersion="${RELEASE_VERSION}" \ + -DdevelopmentVersion="${DEVELOPMENT_VERSION}" \ + -DscmCommentPrefix="[release] " \ + -Pgenerate-rule-docs + echo echo "Tag has been pushed.... now check github actions: " diff --git a/docs/Gemfile.lock b/docs/Gemfile.lock index 0a0f1cccb1..661669d561 100644 --- a/docs/Gemfile.lock +++ b/docs/Gemfile.lock @@ -6,17 +6,17 @@ GEM i18n (>= 1.6, < 2) minitest (>= 5.1) tzinfo (~> 2.0) - addressable (2.8.1) + addressable (2.8.4) public_suffix (>= 2.0.2, < 6.0) coffee-script (2.4.1) coffee-script-source execjs coffee-script-source (1.11.1) colorator (1.1.0) - commonmarker (0.23.8) + commonmarker (0.23.9) concurrent-ruby (1.2.2) - dnsruby (1.61.9) - simpleidn (~> 0.1) + dnsruby (1.70.0) + simpleidn (~> 0.2.1) em-websocket (0.5.3) eventmachine (>= 0.12.9) http_parser.rb (~> 0) @@ -86,7 +86,7 @@ GEM activesupport (>= 2) nokogiri (>= 1.4) http_parser.rb (0.8.0) - i18n (1.12.0) + i18n (1.13.0) concurrent-ruby (~> 1.0) jekyll (3.9.3) addressable (~> 2.4) @@ -211,7 +211,7 @@ GEM jekyll-feed (~> 0.9) jekyll-seo-tag (~> 2.1) minitest (5.18.0) - nokogiri (1.14.2) + nokogiri (1.14.3) mini_portile2 (~> 2.8.0) racc (~> 1.4) octokit (4.25.1) diff --git a/docs/README.md b/docs/README.md index d0aef2914f..71c8eaf911 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,8 +1,10 @@ # PMD Documentation -The documentation is available at: +The snapshot documentation (build by github pages) is available at: . -The documentation for the latest release is at: +The same documentation (build with our own scripts) is available at: . + +The documentation for the latest release is at: ## Site Theme diff --git a/docs/_config.yml b/docs/_config.yml index 920e5d9a1c..540e3ad8ae 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -3,7 +3,7 @@ repository: pmd/pmd pmd: version: 7.0.0-SNAPSHOT previous_version: 6.55.0 - date: ??-????-2023 + date: 27-May-2023 release_type: major # release types: major, minor, bugfix @@ -44,7 +44,6 @@ exclude: - pdf-*.sh - pdfconfigs/ - pdf/ - - sitemap_generator.sh - render_release_notes.rb feedback_subject_line: PMD Source Code Analyzer @@ -117,7 +116,7 @@ description: "Intended as a documentation theme based on Jekyll for technical wr # the description is used in the feed.xml file # needed for sitemap.xml file only -url: https://pmd.github.io/pmd +url: https://docs.pmd-code.org/latest baseurl: "" # used by javadoc_tag.rb diff --git a/docs/_data/sidebars/pmd_sidebar.yml b/docs/_data/sidebars/pmd_sidebar.yml index 6ca086dc8f..41ea0109ce 100644 --- a/docs/_data/sidebars/pmd_sidebar.yml +++ b/docs/_data/sidebars/pmd_sidebar.yml @@ -409,6 +409,9 @@ entries: - title: Java url: /pmd_languages_java.html output: web, pdf + - title: JavaScript / TypeScript + url: /pmd_languages_js_ts.html + output: web, pdf - title: JSP url: /pmd_languages_jsp.html output: web, pdf @@ -430,6 +433,12 @@ entries: - title: Gherkin url: /pmd_languages_gherkin.html output: web, pdf + - title: Julia + url: /pmd_languages_julia.html + output: web, pdf + - title: Coco + url: /pmd_languages_coco.html + output: web, pdf - title: Developer Documentation output: web, pdf folderitems: @@ -469,7 +478,7 @@ entries: - title: Adding a new language (JavaCC) url: /pmd_devdocs_major_adding_new_language_javacc.html output: web, pdf - - title: Adding a new language (Antlr) + - title: Adding a new language (ANTLR) url: /pmd_devdocs_major_adding_new_language_antlr.html output: web, pdf - title: Adding a new CPD language diff --git a/docs/_includes/footer.html b/docs/_includes/footer.html index e8e3c871f4..46187408cf 100755 --- a/docs/_includes/footer.html +++ b/docs/_includes/footer.html @@ -9,7 +9,7 @@ target="_blank" href="https://github.com/{{site.github_editme_path}}{{editmepath}}" role="button" - > Edit on GitHub Edit on GitHub {% endif %} diff --git a/docs/_includes/head.html b/docs/_includes/head.html index 806206b577..a81e15c796 100644 --- a/docs/_includes/head.html +++ b/docs/_includes/head.html @@ -6,7 +6,7 @@ {{ page.title }} | {{ site.site_title }} - + @@ -15,7 +15,7 @@ - - + + diff --git a/docs/_plugins/rule_tag.rb b/docs/_plugins/rule_tag.rb index 36eeb12032..7b5aa3ee13 100644 --- a/docs/_plugins/rule_tag.rb +++ b/docs/_plugins/rule_tag.rb @@ -53,7 +53,7 @@ class RuleTag < Liquid::Tag # 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"]}/" + url_prefix = "https://docs.pmd-code.org/pmd-doc-#{context["site.pmd.version"]}/" end if @was_removed diff --git a/docs/assets/README.md b/docs/assets/README.md index 947fb59af0..48125954f8 100644 --- a/docs/assets/README.md +++ b/docs/assets/README.md @@ -4,7 +4,7 @@ Doc: https://fontawesome.com/how-to-use/on-the-web/setup/hosting-font-awesome-yourself -Download: https://use.fontawesome.com/releases/v5.14.0/fontawesome-free-5.14.0-web.zip +Download: https://use.fontawesome.com/releases/v5.15.4/fontawesome-free-5.15.4-web.zip ## Bootstrap diff --git a/docs/assets/fontawesome-free-5.14.0-web/css/all.min.css b/docs/assets/fontawesome-free-5.14.0-web/css/all.min.css deleted file mode 100644 index f7eacc802d..0000000000 --- a/docs/assets/fontawesome-free-5.14.0-web/css/all.min.css +++ /dev/null @@ -1,5 +0,0 @@ -/*! - * Font Awesome Free 5.14.0 by @fontawesome - https://fontawesome.com - * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) - */ -.fa,.fab,.fad,.fal,.far,.fas{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-.0667em}.fa-xs{font-size:.75em}.fa-sm{font-size:.875em}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-6x{font-size:6em}.fa-7x{font-size:7em}.fa-8x{font-size:8em}.fa-9x{font-size:9em}.fa-10x{font-size:10em}.fa-fw{text-align:center;width:1.25em}.fa-ul{list-style-type:none;margin-left:2.5em;padding-left:0}.fa-ul>li{position:relative}.fa-li{left:-2em;position:absolute;text-align:center;width:2em;line-height:inherit}.fa-border{border:.08em solid #eee;border-radius:.1em;padding:.2em .25em .15em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left,.fab.fa-pull-left,.fal.fa-pull-left,.far.fa-pull-left,.fas.fa-pull-left{margin-right:.3em}.fa.fa-pull-right,.fab.fa-pull-right,.fal.fa-pull-right,.far.fa-pull-right,.fas.fa-pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s linear infinite;animation:fa-spin 2s linear infinite}.fa-pulse{-webkit-animation:fa-spin 1s steps(8) infinite;animation:fa-spin 1s steps(8) infinite}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-webkit-transform:scaleY(-1);transform:scaleY(-1)}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical,.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical{-webkit-transform:scale(-1);transform:scale(-1)}:root .fa-flip-both,:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{-webkit-filter:none;filter:none}.fa-stack{display:inline-block;height:2em;line-height:2em;position:relative;vertical-align:middle;width:2.5em}.fa-stack-1x,.fa-stack-2x{left:0;position:absolute;text-align:center;width:100%}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-500px:before{content:"\f26e"}.fa-accessible-icon:before{content:"\f368"}.fa-accusoft:before{content:"\f369"}.fa-acquisitions-incorporated:before{content:"\f6af"}.fa-ad:before{content:"\f641"}.fa-address-book:before{content:"\f2b9"}.fa-address-card:before{content:"\f2bb"}.fa-adjust:before{content:"\f042"}.fa-adn:before{content:"\f170"}.fa-adobe:before{content:"\f778"}.fa-adversal:before{content:"\f36a"}.fa-affiliatetheme:before{content:"\f36b"}.fa-air-freshener:before{content:"\f5d0"}.fa-airbnb:before{content:"\f834"}.fa-algolia:before{content:"\f36c"}.fa-align-center:before{content:"\f037"}.fa-align-justify:before{content:"\f039"}.fa-align-left:before{content:"\f036"}.fa-align-right:before{content:"\f038"}.fa-alipay:before{content:"\f642"}.fa-allergies:before{content:"\f461"}.fa-amazon:before{content:"\f270"}.fa-amazon-pay:before{content:"\f42c"}.fa-ambulance:before{content:"\f0f9"}.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-amilia:before{content:"\f36d"}.fa-anchor:before{content:"\f13d"}.fa-android:before{content:"\f17b"}.fa-angellist:before{content:"\f209"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-down:before{content:"\f107"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angry:before{content:"\f556"}.fa-angrycreative:before{content:"\f36e"}.fa-angular:before{content:"\f420"}.fa-ankh:before{content:"\f644"}.fa-app-store:before{content:"\f36f"}.fa-app-store-ios:before{content:"\f370"}.fa-apper:before{content:"\f371"}.fa-apple:before{content:"\f179"}.fa-apple-alt:before{content:"\f5d1"}.fa-apple-pay:before{content:"\f415"}.fa-archive:before{content:"\f187"}.fa-archway:before{content:"\f557"}.fa-arrow-alt-circle-down:before{content:"\f358"}.fa-arrow-alt-circle-left:before{content:"\f359"}.fa-arrow-alt-circle-right:before{content:"\f35a"}.fa-arrow-alt-circle-up:before{content:"\f35b"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-down:before{content:"\f063"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrows-alt:before{content:"\f0b2"}.fa-arrows-alt-h:before{content:"\f337"}.fa-arrows-alt-v:before{content:"\f338"}.fa-artstation:before{content:"\f77a"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asterisk:before{content:"\f069"}.fa-asymmetrik:before{content:"\f372"}.fa-at:before{content:"\f1fa"}.fa-atlas:before{content:"\f558"}.fa-atlassian:before{content:"\f77b"}.fa-atom:before{content:"\f5d2"}.fa-audible:before{content:"\f373"}.fa-audio-description:before{content:"\f29e"}.fa-autoprefixer:before{content:"\f41c"}.fa-avianex:before{content:"\f374"}.fa-aviato:before{content:"\f421"}.fa-award:before{content:"\f559"}.fa-aws:before{content:"\f375"}.fa-baby:before{content:"\f77c"}.fa-baby-carriage:before{content:"\f77d"}.fa-backspace:before{content:"\f55a"}.fa-backward:before{content:"\f04a"}.fa-bacon:before{content:"\f7e5"}.fa-bacteria:before{content:"\e059"}.fa-bacterium:before{content:"\e05a"}.fa-bahai:before{content:"\f666"}.fa-balance-scale:before{content:"\f24e"}.fa-balance-scale-left:before{content:"\f515"}.fa-balance-scale-right:before{content:"\f516"}.fa-ban:before{content:"\f05e"}.fa-band-aid:before{content:"\f462"}.fa-bandcamp:before{content:"\f2d5"}.fa-barcode:before{content:"\f02a"}.fa-bars:before{content:"\f0c9"}.fa-baseball-ball:before{content:"\f433"}.fa-basketball-ball:before{content:"\f434"}.fa-bath:before{content:"\f2cd"}.fa-battery-empty:before{content:"\f244"}.fa-battery-full:before{content:"\f240"}.fa-battery-half:before{content:"\f242"}.fa-battery-quarter:before{content:"\f243"}.fa-battery-three-quarters:before{content:"\f241"}.fa-battle-net:before{content:"\f835"}.fa-bed:before{content:"\f236"}.fa-beer:before{content:"\f0fc"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-bell:before{content:"\f0f3"}.fa-bell-slash:before{content:"\f1f6"}.fa-bezier-curve:before{content:"\f55b"}.fa-bible:before{content:"\f647"}.fa-bicycle:before{content:"\f206"}.fa-biking:before{content:"\f84a"}.fa-bimobject:before{content:"\f378"}.fa-binoculars:before{content:"\f1e5"}.fa-biohazard:before{content:"\f780"}.fa-birthday-cake:before{content:"\f1fd"}.fa-bitbucket:before{content:"\f171"}.fa-bitcoin:before{content:"\f379"}.fa-bity:before{content:"\f37a"}.fa-black-tie:before{content:"\f27e"}.fa-blackberry:before{content:"\f37b"}.fa-blender:before{content:"\f517"}.fa-blender-phone:before{content:"\f6b6"}.fa-blind:before{content:"\f29d"}.fa-blog:before{content:"\f781"}.fa-blogger:before{content:"\f37c"}.fa-blogger-b:before{content:"\f37d"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-bold:before{content:"\f032"}.fa-bolt:before{content:"\f0e7"}.fa-bomb:before{content:"\f1e2"}.fa-bone:before{content:"\f5d7"}.fa-bong:before{content:"\f55c"}.fa-book:before{content:"\f02d"}.fa-book-dead:before{content:"\f6b7"}.fa-book-medical:before{content:"\f7e6"}.fa-book-open:before{content:"\f518"}.fa-book-reader:before{content:"\f5da"}.fa-bookmark:before{content:"\f02e"}.fa-bootstrap:before{content:"\f836"}.fa-border-all:before{content:"\f84c"}.fa-border-none:before{content:"\f850"}.fa-border-style:before{content:"\f853"}.fa-bowling-ball:before{content:"\f436"}.fa-box:before{content:"\f466"}.fa-box-open:before{content:"\f49e"}.fa-box-tissue:before{content:"\e05b"}.fa-boxes:before{content:"\f468"}.fa-braille:before{content:"\f2a1"}.fa-brain:before{content:"\f5dc"}.fa-bread-slice:before{content:"\f7ec"}.fa-briefcase:before{content:"\f0b1"}.fa-briefcase-medical:before{content:"\f469"}.fa-broadcast-tower:before{content:"\f519"}.fa-broom:before{content:"\f51a"}.fa-brush:before{content:"\f55d"}.fa-btc:before{content:"\f15a"}.fa-buffer:before{content:"\f837"}.fa-bug:before{content:"\f188"}.fa-building:before{content:"\f1ad"}.fa-bullhorn:before{content:"\f0a1"}.fa-bullseye:before{content:"\f140"}.fa-burn:before{content:"\f46a"}.fa-buromobelexperte:before{content:"\f37f"}.fa-bus:before{content:"\f207"}.fa-bus-alt:before{content:"\f55e"}.fa-business-time:before{content:"\f64a"}.fa-buy-n-large:before{content:"\f8a6"}.fa-buysellads:before{content:"\f20d"}.fa-calculator:before{content:"\f1ec"}.fa-calendar:before{content:"\f133"}.fa-calendar-alt:before{content:"\f073"}.fa-calendar-check:before{content:"\f274"}.fa-calendar-day:before{content:"\f783"}.fa-calendar-minus:before{content:"\f272"}.fa-calendar-plus:before{content:"\f271"}.fa-calendar-times:before{content:"\f273"}.fa-calendar-week:before{content:"\f784"}.fa-camera:before{content:"\f030"}.fa-camera-retro:before{content:"\f083"}.fa-campground:before{content:"\f6bb"}.fa-canadian-maple-leaf:before{content:"\f785"}.fa-candy-cane:before{content:"\f786"}.fa-cannabis:before{content:"\f55f"}.fa-capsules:before{content:"\f46b"}.fa-car:before{content:"\f1b9"}.fa-car-alt:before{content:"\f5de"}.fa-car-battery:before{content:"\f5df"}.fa-car-crash:before{content:"\f5e1"}.fa-car-side:before{content:"\f5e4"}.fa-caravan:before{content:"\f8ff"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-caret-square-down:before{content:"\f150"}.fa-caret-square-left:before{content:"\f191"}.fa-caret-square-right:before{content:"\f152"}.fa-caret-square-up:before{content:"\f151"}.fa-caret-up:before{content:"\f0d8"}.fa-carrot:before{content:"\f787"}.fa-cart-arrow-down:before{content:"\f218"}.fa-cart-plus:before{content:"\f217"}.fa-cash-register:before{content:"\f788"}.fa-cat:before{content:"\f6be"}.fa-cc-amazon-pay:before{content:"\f42d"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-apple-pay:before{content:"\f416"}.fa-cc-diners-club:before{content:"\f24c"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-cc-visa:before{content:"\f1f0"}.fa-centercode:before{content:"\f380"}.fa-centos:before{content:"\f789"}.fa-certificate:before{content:"\f0a3"}.fa-chair:before{content:"\f6c0"}.fa-chalkboard:before{content:"\f51b"}.fa-chalkboard-teacher:before{content:"\f51c"}.fa-charging-station:before{content:"\f5e7"}.fa-chart-area:before{content:"\f1fe"}.fa-chart-bar:before{content:"\f080"}.fa-chart-line:before{content:"\f201"}.fa-chart-pie:before{content:"\f200"}.fa-check:before{content:"\f00c"}.fa-check-circle:before{content:"\f058"}.fa-check-double:before{content:"\f560"}.fa-check-square:before{content:"\f14a"}.fa-cheese:before{content:"\f7ef"}.fa-chess:before{content:"\f439"}.fa-chess-bishop:before{content:"\f43a"}.fa-chess-board:before{content:"\f43c"}.fa-chess-king:before{content:"\f43f"}.fa-chess-knight:before{content:"\f441"}.fa-chess-pawn:before{content:"\f443"}.fa-chess-queen:before{content:"\f445"}.fa-chess-rook:before{content:"\f447"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-down:before{content:"\f078"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-chevron-up:before{content:"\f077"}.fa-child:before{content:"\f1ae"}.fa-chrome:before{content:"\f268"}.fa-chromecast:before{content:"\f838"}.fa-church:before{content:"\f51d"}.fa-circle:before{content:"\f111"}.fa-circle-notch:before{content:"\f1ce"}.fa-city:before{content:"\f64f"}.fa-clinic-medical:before{content:"\f7f2"}.fa-clipboard:before{content:"\f328"}.fa-clipboard-check:before{content:"\f46c"}.fa-clipboard-list:before{content:"\f46d"}.fa-clock:before{content:"\f017"}.fa-clone:before{content:"\f24d"}.fa-closed-captioning:before{content:"\f20a"}.fa-cloud:before{content:"\f0c2"}.fa-cloud-download-alt:before{content:"\f381"}.fa-cloud-meatball:before{content:"\f73b"}.fa-cloud-moon:before{content:"\f6c3"}.fa-cloud-moon-rain:before{content:"\f73c"}.fa-cloud-rain:before{content:"\f73d"}.fa-cloud-showers-heavy:before{content:"\f740"}.fa-cloud-sun:before{content:"\f6c4"}.fa-cloud-sun-rain:before{content:"\f743"}.fa-cloud-upload-alt:before{content:"\f382"}.fa-cloudscale:before{content:"\f383"}.fa-cloudsmith:before{content:"\f384"}.fa-cloudversify:before{content:"\f385"}.fa-cocktail:before{content:"\f561"}.fa-code:before{content:"\f121"}.fa-code-branch:before{content:"\f126"}.fa-codepen:before{content:"\f1cb"}.fa-codiepie:before{content:"\f284"}.fa-coffee:before{content:"\f0f4"}.fa-cog:before{content:"\f013"}.fa-cogs:before{content:"\f085"}.fa-coins:before{content:"\f51e"}.fa-columns:before{content:"\f0db"}.fa-comment:before{content:"\f075"}.fa-comment-alt:before{content:"\f27a"}.fa-comment-dollar:before{content:"\f651"}.fa-comment-dots:before{content:"\f4ad"}.fa-comment-medical:before{content:"\f7f5"}.fa-comment-slash:before{content:"\f4b3"}.fa-comments:before{content:"\f086"}.fa-comments-dollar:before{content:"\f653"}.fa-compact-disc:before{content:"\f51f"}.fa-compass:before{content:"\f14e"}.fa-compress:before{content:"\f066"}.fa-compress-alt:before{content:"\f422"}.fa-compress-arrows-alt:before{content:"\f78c"}.fa-concierge-bell:before{content:"\f562"}.fa-confluence:before{content:"\f78d"}.fa-connectdevelop:before{content:"\f20e"}.fa-contao:before{content:"\f26d"}.fa-cookie:before{content:"\f563"}.fa-cookie-bite:before{content:"\f564"}.fa-copy:before{content:"\f0c5"}.fa-copyright:before{content:"\f1f9"}.fa-cotton-bureau:before{content:"\f89e"}.fa-couch:before{content:"\f4b8"}.fa-cpanel:before{content:"\f388"}.fa-creative-commons:before{content:"\f25e"}.fa-creative-commons-by:before{content:"\f4e7"}.fa-creative-commons-nc:before{content:"\f4e8"}.fa-creative-commons-nc-eu:before{content:"\f4e9"}.fa-creative-commons-nc-jp:before{content:"\f4ea"}.fa-creative-commons-nd:before{content:"\f4eb"}.fa-creative-commons-pd:before{content:"\f4ec"}.fa-creative-commons-pd-alt:before{content:"\f4ed"}.fa-creative-commons-remix:before{content:"\f4ee"}.fa-creative-commons-sa:before{content:"\f4ef"}.fa-creative-commons-sampling:before{content:"\f4f0"}.fa-creative-commons-sampling-plus:before{content:"\f4f1"}.fa-creative-commons-share:before{content:"\f4f2"}.fa-creative-commons-zero:before{content:"\f4f3"}.fa-credit-card:before{content:"\f09d"}.fa-critical-role:before{content:"\f6c9"}.fa-crop:before{content:"\f125"}.fa-crop-alt:before{content:"\f565"}.fa-cross:before{content:"\f654"}.fa-crosshairs:before{content:"\f05b"}.fa-crow:before{content:"\f520"}.fa-crown:before{content:"\f521"}.fa-crutch:before{content:"\f7f7"}.fa-css3:before{content:"\f13c"}.fa-css3-alt:before{content:"\f38b"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-cut:before{content:"\f0c4"}.fa-cuttlefish:before{content:"\f38c"}.fa-d-and-d:before{content:"\f38d"}.fa-d-and-d-beyond:before{content:"\f6ca"}.fa-dailymotion:before{content:"\e052"}.fa-dashcube:before{content:"\f210"}.fa-database:before{content:"\f1c0"}.fa-deaf:before{content:"\f2a4"}.fa-deezer:before{content:"\e077"}.fa-delicious:before{content:"\f1a5"}.fa-democrat:before{content:"\f747"}.fa-deploydog:before{content:"\f38e"}.fa-deskpro:before{content:"\f38f"}.fa-desktop:before{content:"\f108"}.fa-dev:before{content:"\f6cc"}.fa-deviantart:before{content:"\f1bd"}.fa-dharmachakra:before{content:"\f655"}.fa-dhl:before{content:"\f790"}.fa-diagnoses:before{content:"\f470"}.fa-diaspora:before{content:"\f791"}.fa-dice:before{content:"\f522"}.fa-dice-d20:before{content:"\f6cf"}.fa-dice-d6:before{content:"\f6d1"}.fa-dice-five:before{content:"\f523"}.fa-dice-four:before{content:"\f524"}.fa-dice-one:before{content:"\f525"}.fa-dice-six:before{content:"\f526"}.fa-dice-three:before{content:"\f527"}.fa-dice-two:before{content:"\f528"}.fa-digg:before{content:"\f1a6"}.fa-digital-ocean:before{content:"\f391"}.fa-digital-tachograph:before{content:"\f566"}.fa-directions:before{content:"\f5eb"}.fa-discord:before{content:"\f392"}.fa-discourse:before{content:"\f393"}.fa-disease:before{content:"\f7fa"}.fa-divide:before{content:"\f529"}.fa-dizzy:before{content:"\f567"}.fa-dna:before{content:"\f471"}.fa-dochub:before{content:"\f394"}.fa-docker:before{content:"\f395"}.fa-dog:before{content:"\f6d3"}.fa-dollar-sign:before{content:"\f155"}.fa-dolly:before{content:"\f472"}.fa-dolly-flatbed:before{content:"\f474"}.fa-donate:before{content:"\f4b9"}.fa-door-closed:before{content:"\f52a"}.fa-door-open:before{content:"\f52b"}.fa-dot-circle:before{content:"\f192"}.fa-dove:before{content:"\f4ba"}.fa-download:before{content:"\f019"}.fa-draft2digital:before{content:"\f396"}.fa-drafting-compass:before{content:"\f568"}.fa-dragon:before{content:"\f6d5"}.fa-draw-polygon:before{content:"\f5ee"}.fa-dribbble:before{content:"\f17d"}.fa-dribbble-square:before{content:"\f397"}.fa-dropbox:before{content:"\f16b"}.fa-drum:before{content:"\f569"}.fa-drum-steelpan:before{content:"\f56a"}.fa-drumstick-bite:before{content:"\f6d7"}.fa-drupal:before{content:"\f1a9"}.fa-dumbbell:before{content:"\f44b"}.fa-dumpster:before{content:"\f793"}.fa-dumpster-fire:before{content:"\f794"}.fa-dungeon:before{content:"\f6d9"}.fa-dyalog:before{content:"\f399"}.fa-earlybirds:before{content:"\f39a"}.fa-ebay:before{content:"\f4f4"}.fa-edge:before{content:"\f282"}.fa-edge-legacy:before{content:"\e078"}.fa-edit:before{content:"\f044"}.fa-egg:before{content:"\f7fb"}.fa-eject:before{content:"\f052"}.fa-elementor:before{content:"\f430"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-ello:before{content:"\f5f1"}.fa-ember:before{content:"\f423"}.fa-empire:before{content:"\f1d1"}.fa-envelope:before{content:"\f0e0"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-text:before{content:"\f658"}.fa-envelope-square:before{content:"\f199"}.fa-envira:before{content:"\f299"}.fa-equals:before{content:"\f52c"}.fa-eraser:before{content:"\f12d"}.fa-erlang:before{content:"\f39d"}.fa-ethereum:before{content:"\f42e"}.fa-ethernet:before{content:"\f796"}.fa-etsy:before{content:"\f2d7"}.fa-euro-sign:before{content:"\f153"}.fa-evernote:before{content:"\f839"}.fa-exchange-alt:before{content:"\f362"}.fa-exclamation:before{content:"\f12a"}.fa-exclamation-circle:before{content:"\f06a"}.fa-exclamation-triangle:before{content:"\f071"}.fa-expand:before{content:"\f065"}.fa-expand-alt:before{content:"\f424"}.fa-expand-arrows-alt:before{content:"\f31e"}.fa-expeditedssl:before{content:"\f23e"}.fa-external-link-alt:before{content:"\f35d"}.fa-external-link-square-alt:before{content:"\f360"}.fa-eye:before{content:"\f06e"}.fa-eye-dropper:before{content:"\f1fb"}.fa-eye-slash:before{content:"\f070"}.fa-facebook:before{content:"\f09a"}.fa-facebook-f:before{content:"\f39e"}.fa-facebook-messenger:before{content:"\f39f"}.fa-facebook-square:before{content:"\f082"}.fa-fan:before{content:"\f863"}.fa-fantasy-flight-games:before{content:"\f6dc"}.fa-fast-backward:before{content:"\f049"}.fa-fast-forward:before{content:"\f050"}.fa-faucet:before{content:"\e005"}.fa-fax:before{content:"\f1ac"}.fa-feather:before{content:"\f52d"}.fa-feather-alt:before{content:"\f56b"}.fa-fedex:before{content:"\f797"}.fa-fedora:before{content:"\f798"}.fa-female:before{content:"\f182"}.fa-fighter-jet:before{content:"\f0fb"}.fa-figma:before{content:"\f799"}.fa-file:before{content:"\f15b"}.fa-file-alt:before{content:"\f15c"}.fa-file-archive:before{content:"\f1c6"}.fa-file-audio:before{content:"\f1c7"}.fa-file-code:before{content:"\f1c9"}.fa-file-contract:before{content:"\f56c"}.fa-file-csv:before{content:"\f6dd"}.fa-file-download:before{content:"\f56d"}.fa-file-excel:before{content:"\f1c3"}.fa-file-export:before{content:"\f56e"}.fa-file-image:before{content:"\f1c5"}.fa-file-import:before{content:"\f56f"}.fa-file-invoice:before{content:"\f570"}.fa-file-invoice-dollar:before{content:"\f571"}.fa-file-medical:before{content:"\f477"}.fa-file-medical-alt:before{content:"\f478"}.fa-file-pdf:before{content:"\f1c1"}.fa-file-powerpoint:before{content:"\f1c4"}.fa-file-prescription:before{content:"\f572"}.fa-file-signature:before{content:"\f573"}.fa-file-upload:before{content:"\f574"}.fa-file-video:before{content:"\f1c8"}.fa-file-word:before{content:"\f1c2"}.fa-fill:before{content:"\f575"}.fa-fill-drip:before{content:"\f576"}.fa-film:before{content:"\f008"}.fa-filter:before{content:"\f0b0"}.fa-fingerprint:before{content:"\f577"}.fa-fire:before{content:"\f06d"}.fa-fire-alt:before{content:"\f7e4"}.fa-fire-extinguisher:before{content:"\f134"}.fa-firefox:before{content:"\f269"}.fa-firefox-browser:before{content:"\e007"}.fa-first-aid:before{content:"\f479"}.fa-first-order:before{content:"\f2b0"}.fa-first-order-alt:before{content:"\f50a"}.fa-firstdraft:before{content:"\f3a1"}.fa-fish:before{content:"\f578"}.fa-fist-raised:before{content:"\f6de"}.fa-flag:before{content:"\f024"}.fa-flag-checkered:before{content:"\f11e"}.fa-flag-usa:before{content:"\f74d"}.fa-flask:before{content:"\f0c3"}.fa-flickr:before{content:"\f16e"}.fa-flipboard:before{content:"\f44d"}.fa-flushed:before{content:"\f579"}.fa-fly:before{content:"\f417"}.fa-folder:before{content:"\f07b"}.fa-folder-minus:before{content:"\f65d"}.fa-folder-open:before{content:"\f07c"}.fa-folder-plus:before{content:"\f65e"}.fa-font:before{content:"\f031"}.fa-font-awesome:before{content:"\f2b4"}.fa-font-awesome-alt:before{content:"\f35c"}.fa-font-awesome-flag:before{content:"\f425"}.fa-font-awesome-logo-full:before{content:"\f4e6"}.fa-fonticons:before{content:"\f280"}.fa-fonticons-fi:before{content:"\f3a2"}.fa-football-ball:before{content:"\f44e"}.fa-fort-awesome:before{content:"\f286"}.fa-fort-awesome-alt:before{content:"\f3a3"}.fa-forumbee:before{content:"\f211"}.fa-forward:before{content:"\f04e"}.fa-foursquare:before{content:"\f180"}.fa-free-code-camp:before{content:"\f2c5"}.fa-freebsd:before{content:"\f3a4"}.fa-frog:before{content:"\f52e"}.fa-frown:before{content:"\f119"}.fa-frown-open:before{content:"\f57a"}.fa-fulcrum:before{content:"\f50b"}.fa-funnel-dollar:before{content:"\f662"}.fa-futbol:before{content:"\f1e3"}.fa-galactic-republic:before{content:"\f50c"}.fa-galactic-senate:before{content:"\f50d"}.fa-gamepad:before{content:"\f11b"}.fa-gas-pump:before{content:"\f52f"}.fa-gavel:before{content:"\f0e3"}.fa-gem:before{content:"\f3a5"}.fa-genderless:before{content:"\f22d"}.fa-get-pocket:before{content:"\f265"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-ghost:before{content:"\f6e2"}.fa-gift:before{content:"\f06b"}.fa-gifts:before{content:"\f79c"}.fa-git:before{content:"\f1d3"}.fa-git-alt:before{content:"\f841"}.fa-git-square:before{content:"\f1d2"}.fa-github:before{content:"\f09b"}.fa-github-alt:before{content:"\f113"}.fa-github-square:before{content:"\f092"}.fa-gitkraken:before{content:"\f3a6"}.fa-gitlab:before{content:"\f296"}.fa-gitter:before{content:"\f426"}.fa-glass-cheers:before{content:"\f79f"}.fa-glass-martini:before{content:"\f000"}.fa-glass-martini-alt:before{content:"\f57b"}.fa-glass-whiskey:before{content:"\f7a0"}.fa-glasses:before{content:"\f530"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-globe:before{content:"\f0ac"}.fa-globe-africa:before{content:"\f57c"}.fa-globe-americas:before{content:"\f57d"}.fa-globe-asia:before{content:"\f57e"}.fa-globe-europe:before{content:"\f7a2"}.fa-gofore:before{content:"\f3a7"}.fa-golf-ball:before{content:"\f450"}.fa-goodreads:before{content:"\f3a8"}.fa-goodreads-g:before{content:"\f3a9"}.fa-google:before{content:"\f1a0"}.fa-google-drive:before{content:"\f3aa"}.fa-google-pay:before{content:"\e079"}.fa-google-play:before{content:"\f3ab"}.fa-google-plus:before{content:"\f2b3"}.fa-google-plus-g:before{content:"\f0d5"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-wallet:before{content:"\f1ee"}.fa-gopuram:before{content:"\f664"}.fa-graduation-cap:before{content:"\f19d"}.fa-gratipay:before{content:"\f184"}.fa-grav:before{content:"\f2d6"}.fa-greater-than:before{content:"\f531"}.fa-greater-than-equal:before{content:"\f532"}.fa-grimace:before{content:"\f57f"}.fa-grin:before{content:"\f580"}.fa-grin-alt:before{content:"\f581"}.fa-grin-beam:before{content:"\f582"}.fa-grin-beam-sweat:before{content:"\f583"}.fa-grin-hearts:before{content:"\f584"}.fa-grin-squint:before{content:"\f585"}.fa-grin-squint-tears:before{content:"\f586"}.fa-grin-stars:before{content:"\f587"}.fa-grin-tears:before{content:"\f588"}.fa-grin-tongue:before{content:"\f589"}.fa-grin-tongue-squint:before{content:"\f58a"}.fa-grin-tongue-wink:before{content:"\f58b"}.fa-grin-wink:before{content:"\f58c"}.fa-grip-horizontal:before{content:"\f58d"}.fa-grip-lines:before{content:"\f7a4"}.fa-grip-lines-vertical:before{content:"\f7a5"}.fa-grip-vertical:before{content:"\f58e"}.fa-gripfire:before{content:"\f3ac"}.fa-grunt:before{content:"\f3ad"}.fa-guitar:before{content:"\f7a6"}.fa-gulp:before{content:"\f3ae"}.fa-h-square:before{content:"\f0fd"}.fa-hacker-news:before{content:"\f1d4"}.fa-hacker-news-square:before{content:"\f3af"}.fa-hackerrank:before{content:"\f5f7"}.fa-hamburger:before{content:"\f805"}.fa-hammer:before{content:"\f6e3"}.fa-hamsa:before{content:"\f665"}.fa-hand-holding:before{content:"\f4bd"}.fa-hand-holding-heart:before{content:"\f4be"}.fa-hand-holding-medical:before{content:"\e05c"}.fa-hand-holding-usd:before{content:"\f4c0"}.fa-hand-holding-water:before{content:"\f4c1"}.fa-hand-lizard:before{content:"\f258"}.fa-hand-middle-finger:before{content:"\f806"}.fa-hand-paper:before{content:"\f256"}.fa-hand-peace:before{content:"\f25b"}.fa-hand-point-down:before{content:"\f0a7"}.fa-hand-point-left:before{content:"\f0a5"}.fa-hand-point-right:before{content:"\f0a4"}.fa-hand-point-up:before{content:"\f0a6"}.fa-hand-pointer:before{content:"\f25a"}.fa-hand-rock:before{content:"\f255"}.fa-hand-scissors:before{content:"\f257"}.fa-hand-sparkles:before{content:"\e05d"}.fa-hand-spock:before{content:"\f259"}.fa-hands:before{content:"\f4c2"}.fa-hands-helping:before{content:"\f4c4"}.fa-hands-wash:before{content:"\e05e"}.fa-handshake:before{content:"\f2b5"}.fa-handshake-alt-slash:before{content:"\e05f"}.fa-handshake-slash:before{content:"\e060"}.fa-hanukiah:before{content:"\f6e6"}.fa-hard-hat:before{content:"\f807"}.fa-hashtag:before{content:"\f292"}.fa-hat-cowboy:before{content:"\f8c0"}.fa-hat-cowboy-side:before{content:"\f8c1"}.fa-hat-wizard:before{content:"\f6e8"}.fa-hdd:before{content:"\f0a0"}.fa-head-side-cough:before{content:"\e061"}.fa-head-side-cough-slash:before{content:"\e062"}.fa-head-side-mask:before{content:"\e063"}.fa-head-side-virus:before{content:"\e064"}.fa-heading:before{content:"\f1dc"}.fa-headphones:before{content:"\f025"}.fa-headphones-alt:before{content:"\f58f"}.fa-headset:before{content:"\f590"}.fa-heart:before{content:"\f004"}.fa-heart-broken:before{content:"\f7a9"}.fa-heartbeat:before{content:"\f21e"}.fa-helicopter:before{content:"\f533"}.fa-highlighter:before{content:"\f591"}.fa-hiking:before{content:"\f6ec"}.fa-hippo:before{content:"\f6ed"}.fa-hips:before{content:"\f452"}.fa-hire-a-helper:before{content:"\f3b0"}.fa-history:before{content:"\f1da"}.fa-hockey-puck:before{content:"\f453"}.fa-holly-berry:before{content:"\f7aa"}.fa-home:before{content:"\f015"}.fa-hooli:before{content:"\f427"}.fa-hornbill:before{content:"\f592"}.fa-horse:before{content:"\f6f0"}.fa-horse-head:before{content:"\f7ab"}.fa-hospital:before{content:"\f0f8"}.fa-hospital-alt:before{content:"\f47d"}.fa-hospital-symbol:before{content:"\f47e"}.fa-hospital-user:before{content:"\f80d"}.fa-hot-tub:before{content:"\f593"}.fa-hotdog:before{content:"\f80f"}.fa-hotel:before{content:"\f594"}.fa-hotjar:before{content:"\f3b1"}.fa-hourglass:before{content:"\f254"}.fa-hourglass-end:before{content:"\f253"}.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-start:before{content:"\f251"}.fa-house-damage:before{content:"\f6f1"}.fa-house-user:before{content:"\e065"}.fa-houzz:before{content:"\f27c"}.fa-hryvnia:before{content:"\f6f2"}.fa-html5:before{content:"\f13b"}.fa-hubspot:before{content:"\f3b2"}.fa-i-cursor:before{content:"\f246"}.fa-ice-cream:before{content:"\f810"}.fa-icicles:before{content:"\f7ad"}.fa-icons:before{content:"\f86d"}.fa-id-badge:before{content:"\f2c1"}.fa-id-card:before{content:"\f2c2"}.fa-id-card-alt:before{content:"\f47f"}.fa-ideal:before{content:"\e013"}.fa-igloo:before{content:"\f7ae"}.fa-image:before{content:"\f03e"}.fa-images:before{content:"\f302"}.fa-imdb:before{content:"\f2d8"}.fa-inbox:before{content:"\f01c"}.fa-indent:before{content:"\f03c"}.fa-industry:before{content:"\f275"}.fa-infinity:before{content:"\f534"}.fa-info:before{content:"\f129"}.fa-info-circle:before{content:"\f05a"}.fa-instagram:before{content:"\f16d"}.fa-instagram-square:before{content:"\e055"}.fa-intercom:before{content:"\f7af"}.fa-internet-explorer:before{content:"\f26b"}.fa-invision:before{content:"\f7b0"}.fa-ioxhost:before{content:"\f208"}.fa-italic:before{content:"\f033"}.fa-itch-io:before{content:"\f83a"}.fa-itunes:before{content:"\f3b4"}.fa-itunes-note:before{content:"\f3b5"}.fa-java:before{content:"\f4e4"}.fa-jedi:before{content:"\f669"}.fa-jedi-order:before{content:"\f50e"}.fa-jenkins:before{content:"\f3b6"}.fa-jira:before{content:"\f7b1"}.fa-joget:before{content:"\f3b7"}.fa-joint:before{content:"\f595"}.fa-joomla:before{content:"\f1aa"}.fa-journal-whills:before{content:"\f66a"}.fa-js:before{content:"\f3b8"}.fa-js-square:before{content:"\f3b9"}.fa-jsfiddle:before{content:"\f1cc"}.fa-kaaba:before{content:"\f66b"}.fa-kaggle:before{content:"\f5fa"}.fa-key:before{content:"\f084"}.fa-keybase:before{content:"\f4f5"}.fa-keyboard:before{content:"\f11c"}.fa-keycdn:before{content:"\f3ba"}.fa-khanda:before{content:"\f66d"}.fa-kickstarter:before{content:"\f3bb"}.fa-kickstarter-k:before{content:"\f3bc"}.fa-kiss:before{content:"\f596"}.fa-kiss-beam:before{content:"\f597"}.fa-kiss-wink-heart:before{content:"\f598"}.fa-kiwi-bird:before{content:"\f535"}.fa-korvue:before{content:"\f42f"}.fa-landmark:before{content:"\f66f"}.fa-language:before{content:"\f1ab"}.fa-laptop:before{content:"\f109"}.fa-laptop-code:before{content:"\f5fc"}.fa-laptop-house:before{content:"\e066"}.fa-laptop-medical:before{content:"\f812"}.fa-laravel:before{content:"\f3bd"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-laugh:before{content:"\f599"}.fa-laugh-beam:before{content:"\f59a"}.fa-laugh-squint:before{content:"\f59b"}.fa-laugh-wink:before{content:"\f59c"}.fa-layer-group:before{content:"\f5fd"}.fa-leaf:before{content:"\f06c"}.fa-leanpub:before{content:"\f212"}.fa-lemon:before{content:"\f094"}.fa-less:before{content:"\f41d"}.fa-less-than:before{content:"\f536"}.fa-less-than-equal:before{content:"\f537"}.fa-level-down-alt:before{content:"\f3be"}.fa-level-up-alt:before{content:"\f3bf"}.fa-life-ring:before{content:"\f1cd"}.fa-lightbulb:before{content:"\f0eb"}.fa-line:before{content:"\f3c0"}.fa-link:before{content:"\f0c1"}.fa-linkedin:before{content:"\f08c"}.fa-linkedin-in:before{content:"\f0e1"}.fa-linode:before{content:"\f2b8"}.fa-linux:before{content:"\f17c"}.fa-lira-sign:before{content:"\f195"}.fa-list:before{content:"\f03a"}.fa-list-alt:before{content:"\f022"}.fa-list-ol:before{content:"\f0cb"}.fa-list-ul:before{content:"\f0ca"}.fa-location-arrow:before{content:"\f124"}.fa-lock:before{content:"\f023"}.fa-lock-open:before{content:"\f3c1"}.fa-long-arrow-alt-down:before{content:"\f309"}.fa-long-arrow-alt-left:before{content:"\f30a"}.fa-long-arrow-alt-right:before{content:"\f30b"}.fa-long-arrow-alt-up:before{content:"\f30c"}.fa-low-vision:before{content:"\f2a8"}.fa-luggage-cart:before{content:"\f59d"}.fa-lungs:before{content:"\f604"}.fa-lungs-virus:before{content:"\e067"}.fa-lyft:before{content:"\f3c3"}.fa-magento:before{content:"\f3c4"}.fa-magic:before{content:"\f0d0"}.fa-magnet:before{content:"\f076"}.fa-mail-bulk:before{content:"\f674"}.fa-mailchimp:before{content:"\f59e"}.fa-male:before{content:"\f183"}.fa-mandalorian:before{content:"\f50f"}.fa-map:before{content:"\f279"}.fa-map-marked:before{content:"\f59f"}.fa-map-marked-alt:before{content:"\f5a0"}.fa-map-marker:before{content:"\f041"}.fa-map-marker-alt:before{content:"\f3c5"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-markdown:before{content:"\f60f"}.fa-marker:before{content:"\f5a1"}.fa-mars:before{content:"\f222"}.fa-mars-double:before{content:"\f227"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mask:before{content:"\f6fa"}.fa-mastodon:before{content:"\f4f6"}.fa-maxcdn:before{content:"\f136"}.fa-mdb:before{content:"\f8ca"}.fa-medal:before{content:"\f5a2"}.fa-medapps:before{content:"\f3c6"}.fa-medium:before{content:"\f23a"}.fa-medium-m:before{content:"\f3c7"}.fa-medkit:before{content:"\f0fa"}.fa-medrt:before{content:"\f3c8"}.fa-meetup:before{content:"\f2e0"}.fa-megaport:before{content:"\f5a3"}.fa-meh:before{content:"\f11a"}.fa-meh-blank:before{content:"\f5a4"}.fa-meh-rolling-eyes:before{content:"\f5a5"}.fa-memory:before{content:"\f538"}.fa-mendeley:before{content:"\f7b3"}.fa-menorah:before{content:"\f676"}.fa-mercury:before{content:"\f223"}.fa-meteor:before{content:"\f753"}.fa-microblog:before{content:"\e01a"}.fa-microchip:before{content:"\f2db"}.fa-microphone:before{content:"\f130"}.fa-microphone-alt:before{content:"\f3c9"}.fa-microphone-alt-slash:before{content:"\f539"}.fa-microphone-slash:before{content:"\f131"}.fa-microscope:before{content:"\f610"}.fa-microsoft:before{content:"\f3ca"}.fa-minus:before{content:"\f068"}.fa-minus-circle:before{content:"\f056"}.fa-minus-square:before{content:"\f146"}.fa-mitten:before{content:"\f7b5"}.fa-mix:before{content:"\f3cb"}.fa-mixcloud:before{content:"\f289"}.fa-mixer:before{content:"\e056"}.fa-mizuni:before{content:"\f3cc"}.fa-mobile:before{content:"\f10b"}.fa-mobile-alt:before{content:"\f3cd"}.fa-modx:before{content:"\f285"}.fa-monero:before{content:"\f3d0"}.fa-money-bill:before{content:"\f0d6"}.fa-money-bill-alt:before{content:"\f3d1"}.fa-money-bill-wave:before{content:"\f53a"}.fa-money-bill-wave-alt:before{content:"\f53b"}.fa-money-check:before{content:"\f53c"}.fa-money-check-alt:before{content:"\f53d"}.fa-monument:before{content:"\f5a6"}.fa-moon:before{content:"\f186"}.fa-mortar-pestle:before{content:"\f5a7"}.fa-mosque:before{content:"\f678"}.fa-motorcycle:before{content:"\f21c"}.fa-mountain:before{content:"\f6fc"}.fa-mouse:before{content:"\f8cc"}.fa-mouse-pointer:before{content:"\f245"}.fa-mug-hot:before{content:"\f7b6"}.fa-music:before{content:"\f001"}.fa-napster:before{content:"\f3d2"}.fa-neos:before{content:"\f612"}.fa-network-wired:before{content:"\f6ff"}.fa-neuter:before{content:"\f22c"}.fa-newspaper:before{content:"\f1ea"}.fa-nimblr:before{content:"\f5a8"}.fa-node:before{content:"\f419"}.fa-node-js:before{content:"\f3d3"}.fa-not-equal:before{content:"\f53e"}.fa-notes-medical:before{content:"\f481"}.fa-npm:before{content:"\f3d4"}.fa-ns8:before{content:"\f3d5"}.fa-nutritionix:before{content:"\f3d6"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-oil-can:before{content:"\f613"}.fa-old-republic:before{content:"\f510"}.fa-om:before{content:"\f679"}.fa-opencart:before{content:"\f23d"}.fa-openid:before{content:"\f19b"}.fa-opera:before{content:"\f26a"}.fa-optin-monster:before{content:"\f23c"}.fa-orcid:before{content:"\f8d2"}.fa-osi:before{content:"\f41a"}.fa-otter:before{content:"\f700"}.fa-outdent:before{content:"\f03b"}.fa-page4:before{content:"\f3d7"}.fa-pagelines:before{content:"\f18c"}.fa-pager:before{content:"\f815"}.fa-paint-brush:before{content:"\f1fc"}.fa-paint-roller:before{content:"\f5aa"}.fa-palette:before{content:"\f53f"}.fa-palfed:before{content:"\f3d8"}.fa-pallet:before{content:"\f482"}.fa-paper-plane:before{content:"\f1d8"}.fa-paperclip:before{content:"\f0c6"}.fa-parachute-box:before{content:"\f4cd"}.fa-paragraph:before{content:"\f1dd"}.fa-parking:before{content:"\f540"}.fa-passport:before{content:"\f5ab"}.fa-pastafarianism:before{content:"\f67b"}.fa-paste:before{content:"\f0ea"}.fa-patreon:before{content:"\f3d9"}.fa-pause:before{content:"\f04c"}.fa-pause-circle:before{content:"\f28b"}.fa-paw:before{content:"\f1b0"}.fa-paypal:before{content:"\f1ed"}.fa-peace:before{content:"\f67c"}.fa-pen:before{content:"\f304"}.fa-pen-alt:before{content:"\f305"}.fa-pen-fancy:before{content:"\f5ac"}.fa-pen-nib:before{content:"\f5ad"}.fa-pen-square:before{content:"\f14b"}.fa-pencil-alt:before{content:"\f303"}.fa-pencil-ruler:before{content:"\f5ae"}.fa-penny-arcade:before{content:"\f704"}.fa-people-arrows:before{content:"\e068"}.fa-people-carry:before{content:"\f4ce"}.fa-pepper-hot:before{content:"\f816"}.fa-percent:before{content:"\f295"}.fa-percentage:before{content:"\f541"}.fa-periscope:before{content:"\f3da"}.fa-person-booth:before{content:"\f756"}.fa-phabricator:before{content:"\f3db"}.fa-phoenix-framework:before{content:"\f3dc"}.fa-phoenix-squadron:before{content:"\f511"}.fa-phone:before{content:"\f095"}.fa-phone-alt:before{content:"\f879"}.fa-phone-slash:before{content:"\f3dd"}.fa-phone-square:before{content:"\f098"}.fa-phone-square-alt:before{content:"\f87b"}.fa-phone-volume:before{content:"\f2a0"}.fa-photo-video:before{content:"\f87c"}.fa-php:before{content:"\f457"}.fa-pied-piper:before{content:"\f2ae"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-pied-piper-hat:before{content:"\f4e5"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-square:before{content:"\e01e"}.fa-piggy-bank:before{content:"\f4d3"}.fa-pills:before{content:"\f484"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-p:before{content:"\f231"}.fa-pinterest-square:before{content:"\f0d3"}.fa-pizza-slice:before{content:"\f818"}.fa-place-of-worship:before{content:"\f67f"}.fa-plane:before{content:"\f072"}.fa-plane-arrival:before{content:"\f5af"}.fa-plane-departure:before{content:"\f5b0"}.fa-plane-slash:before{content:"\e069"}.fa-play:before{content:"\f04b"}.fa-play-circle:before{content:"\f144"}.fa-playstation:before{content:"\f3df"}.fa-plug:before{content:"\f1e6"}.fa-plus:before{content:"\f067"}.fa-plus-circle:before{content:"\f055"}.fa-plus-square:before{content:"\f0fe"}.fa-podcast:before{content:"\f2ce"}.fa-poll:before{content:"\f681"}.fa-poll-h:before{content:"\f682"}.fa-poo:before{content:"\f2fe"}.fa-poo-storm:before{content:"\f75a"}.fa-poop:before{content:"\f619"}.fa-portrait:before{content:"\f3e0"}.fa-pound-sign:before{content:"\f154"}.fa-power-off:before{content:"\f011"}.fa-pray:before{content:"\f683"}.fa-praying-hands:before{content:"\f684"}.fa-prescription:before{content:"\f5b1"}.fa-prescription-bottle:before{content:"\f485"}.fa-prescription-bottle-alt:before{content:"\f486"}.fa-print:before{content:"\f02f"}.fa-procedures:before{content:"\f487"}.fa-product-hunt:before{content:"\f288"}.fa-project-diagram:before{content:"\f542"}.fa-pump-medical:before{content:"\e06a"}.fa-pump-soap:before{content:"\e06b"}.fa-pushed:before{content:"\f3e1"}.fa-puzzle-piece:before{content:"\f12e"}.fa-python:before{content:"\f3e2"}.fa-qq:before{content:"\f1d6"}.fa-qrcode:before{content:"\f029"}.fa-question:before{content:"\f128"}.fa-question-circle:before{content:"\f059"}.fa-quidditch:before{content:"\f458"}.fa-quinscape:before{content:"\f459"}.fa-quora:before{content:"\f2c4"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-quran:before{content:"\f687"}.fa-r-project:before{content:"\f4f7"}.fa-radiation:before{content:"\f7b9"}.fa-radiation-alt:before{content:"\f7ba"}.fa-rainbow:before{content:"\f75b"}.fa-random:before{content:"\f074"}.fa-raspberry-pi:before{content:"\f7bb"}.fa-ravelry:before{content:"\f2d9"}.fa-react:before{content:"\f41b"}.fa-reacteurope:before{content:"\f75d"}.fa-readme:before{content:"\f4d5"}.fa-rebel:before{content:"\f1d0"}.fa-receipt:before{content:"\f543"}.fa-record-vinyl:before{content:"\f8d9"}.fa-recycle:before{content:"\f1b8"}.fa-red-river:before{content:"\f3e3"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-alien:before{content:"\f281"}.fa-reddit-square:before{content:"\f1a2"}.fa-redhat:before{content:"\f7bc"}.fa-redo:before{content:"\f01e"}.fa-redo-alt:before{content:"\f2f9"}.fa-registered:before{content:"\f25d"}.fa-remove-format:before{content:"\f87d"}.fa-renren:before{content:"\f18b"}.fa-reply:before{content:"\f3e5"}.fa-reply-all:before{content:"\f122"}.fa-replyd:before{content:"\f3e6"}.fa-republican:before{content:"\f75e"}.fa-researchgate:before{content:"\f4f8"}.fa-resolving:before{content:"\f3e7"}.fa-restroom:before{content:"\f7bd"}.fa-retweet:before{content:"\f079"}.fa-rev:before{content:"\f5b2"}.fa-ribbon:before{content:"\f4d6"}.fa-ring:before{content:"\f70b"}.fa-road:before{content:"\f018"}.fa-robot:before{content:"\f544"}.fa-rocket:before{content:"\f135"}.fa-rocketchat:before{content:"\f3e8"}.fa-rockrms:before{content:"\f3e9"}.fa-route:before{content:"\f4d7"}.fa-rss:before{content:"\f09e"}.fa-rss-square:before{content:"\f143"}.fa-ruble-sign:before{content:"\f158"}.fa-ruler:before{content:"\f545"}.fa-ruler-combined:before{content:"\f546"}.fa-ruler-horizontal:before{content:"\f547"}.fa-ruler-vertical:before{content:"\f548"}.fa-running:before{content:"\f70c"}.fa-rupee-sign:before{content:"\f156"}.fa-rust:before{content:"\e07a"}.fa-sad-cry:before{content:"\f5b3"}.fa-sad-tear:before{content:"\f5b4"}.fa-safari:before{content:"\f267"}.fa-salesforce:before{content:"\f83b"}.fa-sass:before{content:"\f41e"}.fa-satellite:before{content:"\f7bf"}.fa-satellite-dish:before{content:"\f7c0"}.fa-save:before{content:"\f0c7"}.fa-schlix:before{content:"\f3ea"}.fa-school:before{content:"\f549"}.fa-screwdriver:before{content:"\f54a"}.fa-scribd:before{content:"\f28a"}.fa-scroll:before{content:"\f70e"}.fa-sd-card:before{content:"\f7c2"}.fa-search:before{content:"\f002"}.fa-search-dollar:before{content:"\f688"}.fa-search-location:before{content:"\f689"}.fa-search-minus:before{content:"\f010"}.fa-search-plus:before{content:"\f00e"}.fa-searchengin:before{content:"\f3eb"}.fa-seedling:before{content:"\f4d8"}.fa-sellcast:before{content:"\f2da"}.fa-sellsy:before{content:"\f213"}.fa-server:before{content:"\f233"}.fa-servicestack:before{content:"\f3ec"}.fa-shapes:before{content:"\f61f"}.fa-share:before{content:"\f064"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-share-square:before{content:"\f14d"}.fa-shekel-sign:before{content:"\f20b"}.fa-shield-alt:before{content:"\f3ed"}.fa-shield-virus:before{content:"\e06c"}.fa-ship:before{content:"\f21a"}.fa-shipping-fast:before{content:"\f48b"}.fa-shirtsinbulk:before{content:"\f214"}.fa-shoe-prints:before{content:"\f54b"}.fa-shopify:before{content:"\e057"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-shopping-cart:before{content:"\f07a"}.fa-shopware:before{content:"\f5b5"}.fa-shower:before{content:"\f2cc"}.fa-shuttle-van:before{content:"\f5b6"}.fa-sign:before{content:"\f4d9"}.fa-sign-in-alt:before{content:"\f2f6"}.fa-sign-language:before{content:"\f2a7"}.fa-sign-out-alt:before{content:"\f2f5"}.fa-signal:before{content:"\f012"}.fa-signature:before{content:"\f5b7"}.fa-sim-card:before{content:"\f7c4"}.fa-simplybuilt:before{content:"\f215"}.fa-sink:before{content:"\e06d"}.fa-sistrix:before{content:"\f3ee"}.fa-sitemap:before{content:"\f0e8"}.fa-sith:before{content:"\f512"}.fa-skating:before{content:"\f7c5"}.fa-sketch:before{content:"\f7c6"}.fa-skiing:before{content:"\f7c9"}.fa-skiing-nordic:before{content:"\f7ca"}.fa-skull:before{content:"\f54c"}.fa-skull-crossbones:before{content:"\f714"}.fa-skyatlas:before{content:"\f216"}.fa-skype:before{content:"\f17e"}.fa-slack:before{content:"\f198"}.fa-slack-hash:before{content:"\f3ef"}.fa-slash:before{content:"\f715"}.fa-sleigh:before{content:"\f7cc"}.fa-sliders-h:before{content:"\f1de"}.fa-slideshare:before{content:"\f1e7"}.fa-smile:before{content:"\f118"}.fa-smile-beam:before{content:"\f5b8"}.fa-smile-wink:before{content:"\f4da"}.fa-smog:before{content:"\f75f"}.fa-smoking:before{content:"\f48d"}.fa-smoking-ban:before{content:"\f54d"}.fa-sms:before{content:"\f7cd"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-snowboarding:before{content:"\f7ce"}.fa-snowflake:before{content:"\f2dc"}.fa-snowman:before{content:"\f7d0"}.fa-snowplow:before{content:"\f7d2"}.fa-soap:before{content:"\e06e"}.fa-socks:before{content:"\f696"}.fa-solar-panel:before{content:"\f5ba"}.fa-sort:before{content:"\f0dc"}.fa-sort-alpha-down:before{content:"\f15d"}.fa-sort-alpha-down-alt:before{content:"\f881"}.fa-sort-alpha-up:before{content:"\f15e"}.fa-sort-alpha-up-alt:before{content:"\f882"}.fa-sort-amount-down:before{content:"\f160"}.fa-sort-amount-down-alt:before{content:"\f884"}.fa-sort-amount-up:before{content:"\f161"}.fa-sort-amount-up-alt:before{content:"\f885"}.fa-sort-down:before{content:"\f0dd"}.fa-sort-numeric-down:before{content:"\f162"}.fa-sort-numeric-down-alt:before{content:"\f886"}.fa-sort-numeric-up:before{content:"\f163"}.fa-sort-numeric-up-alt:before{content:"\f887"}.fa-sort-up:before{content:"\f0de"}.fa-soundcloud:before{content:"\f1be"}.fa-sourcetree:before{content:"\f7d3"}.fa-spa:before{content:"\f5bb"}.fa-space-shuttle:before{content:"\f197"}.fa-speakap:before{content:"\f3f3"}.fa-speaker-deck:before{content:"\f83c"}.fa-spell-check:before{content:"\f891"}.fa-spider:before{content:"\f717"}.fa-spinner:before{content:"\f110"}.fa-splotch:before{content:"\f5bc"}.fa-spotify:before{content:"\f1bc"}.fa-spray-can:before{content:"\f5bd"}.fa-square:before{content:"\f0c8"}.fa-square-full:before{content:"\f45c"}.fa-square-root-alt:before{content:"\f698"}.fa-squarespace:before{content:"\f5be"}.fa-stack-exchange:before{content:"\f18d"}.fa-stack-overflow:before{content:"\f16c"}.fa-stackpath:before{content:"\f842"}.fa-stamp:before{content:"\f5bf"}.fa-star:before{content:"\f005"}.fa-star-and-crescent:before{content:"\f699"}.fa-star-half:before{content:"\f089"}.fa-star-half-alt:before{content:"\f5c0"}.fa-star-of-david:before{content:"\f69a"}.fa-star-of-life:before{content:"\f621"}.fa-staylinked:before{content:"\f3f5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-steam-symbol:before{content:"\f3f6"}.fa-step-backward:before{content:"\f048"}.fa-step-forward:before{content:"\f051"}.fa-stethoscope:before{content:"\f0f1"}.fa-sticker-mule:before{content:"\f3f7"}.fa-sticky-note:before{content:"\f249"}.fa-stop:before{content:"\f04d"}.fa-stop-circle:before{content:"\f28d"}.fa-stopwatch:before{content:"\f2f2"}.fa-stopwatch-20:before{content:"\e06f"}.fa-store:before{content:"\f54e"}.fa-store-alt:before{content:"\f54f"}.fa-store-alt-slash:before{content:"\e070"}.fa-store-slash:before{content:"\e071"}.fa-strava:before{content:"\f428"}.fa-stream:before{content:"\f550"}.fa-street-view:before{content:"\f21d"}.fa-strikethrough:before{content:"\f0cc"}.fa-stripe:before{content:"\f429"}.fa-stripe-s:before{content:"\f42a"}.fa-stroopwafel:before{content:"\f551"}.fa-studiovinari:before{content:"\f3f8"}.fa-stumbleupon:before{content:"\f1a4"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-subscript:before{content:"\f12c"}.fa-subway:before{content:"\f239"}.fa-suitcase:before{content:"\f0f2"}.fa-suitcase-rolling:before{content:"\f5c1"}.fa-sun:before{content:"\f185"}.fa-superpowers:before{content:"\f2dd"}.fa-superscript:before{content:"\f12b"}.fa-supple:before{content:"\f3f9"}.fa-surprise:before{content:"\f5c2"}.fa-suse:before{content:"\f7d6"}.fa-swatchbook:before{content:"\f5c3"}.fa-swift:before{content:"\f8e1"}.fa-swimmer:before{content:"\f5c4"}.fa-swimming-pool:before{content:"\f5c5"}.fa-symfony:before{content:"\f83d"}.fa-synagogue:before{content:"\f69b"}.fa-sync:before{content:"\f021"}.fa-sync-alt:before{content:"\f2f1"}.fa-syringe:before{content:"\f48e"}.fa-table:before{content:"\f0ce"}.fa-table-tennis:before{content:"\f45d"}.fa-tablet:before{content:"\f10a"}.fa-tablet-alt:before{content:"\f3fa"}.fa-tablets:before{content:"\f490"}.fa-tachometer-alt:before{content:"\f3fd"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-tape:before{content:"\f4db"}.fa-tasks:before{content:"\f0ae"}.fa-taxi:before{content:"\f1ba"}.fa-teamspeak:before{content:"\f4f9"}.fa-teeth:before{content:"\f62e"}.fa-teeth-open:before{content:"\f62f"}.fa-telegram:before{content:"\f2c6"}.fa-telegram-plane:before{content:"\f3fe"}.fa-temperature-high:before{content:"\f769"}.fa-temperature-low:before{content:"\f76b"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-tenge:before{content:"\f7d7"}.fa-terminal:before{content:"\f120"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-th:before{content:"\f00a"}.fa-th-large:before{content:"\f009"}.fa-th-list:before{content:"\f00b"}.fa-the-red-yeti:before{content:"\f69d"}.fa-theater-masks:before{content:"\f630"}.fa-themeco:before{content:"\f5c6"}.fa-themeisle:before{content:"\f2b2"}.fa-thermometer:before{content:"\f491"}.fa-thermometer-empty:before{content:"\f2cb"}.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-think-peaks:before{content:"\f731"}.fa-thumbs-down:before{content:"\f165"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbtack:before{content:"\f08d"}.fa-ticket-alt:before{content:"\f3ff"}.fa-tiktok:before{content:"\e07b"}.fa-times:before{content:"\f00d"}.fa-times-circle:before{content:"\f057"}.fa-tint:before{content:"\f043"}.fa-tint-slash:before{content:"\f5c7"}.fa-tired:before{content:"\f5c8"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-toilet:before{content:"\f7d8"}.fa-toilet-paper:before{content:"\f71e"}.fa-toilet-paper-slash:before{content:"\e072"}.fa-toolbox:before{content:"\f552"}.fa-tools:before{content:"\f7d9"}.fa-tooth:before{content:"\f5c9"}.fa-torah:before{content:"\f6a0"}.fa-torii-gate:before{content:"\f6a1"}.fa-tractor:before{content:"\f722"}.fa-trade-federation:before{content:"\f513"}.fa-trademark:before{content:"\f25c"}.fa-traffic-light:before{content:"\f637"}.fa-trailer:before{content:"\e041"}.fa-train:before{content:"\f238"}.fa-tram:before{content:"\f7da"}.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-trash:before{content:"\f1f8"}.fa-trash-alt:before{content:"\f2ed"}.fa-trash-restore:before{content:"\f829"}.fa-trash-restore-alt:before{content:"\f82a"}.fa-tree:before{content:"\f1bb"}.fa-trello:before{content:"\f181"}.fa-tripadvisor:before{content:"\f262"}.fa-trophy:before{content:"\f091"}.fa-truck:before{content:"\f0d1"}.fa-truck-loading:before{content:"\f4de"}.fa-truck-monster:before{content:"\f63b"}.fa-truck-moving:before{content:"\f4df"}.fa-truck-pickup:before{content:"\f63c"}.fa-tshirt:before{content:"\f553"}.fa-tty:before{content:"\f1e4"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-tv:before{content:"\f26c"}.fa-twitch:before{content:"\f1e8"}.fa-twitter:before{content:"\f099"}.fa-twitter-square:before{content:"\f081"}.fa-typo3:before{content:"\f42b"}.fa-uber:before{content:"\f402"}.fa-ubuntu:before{content:"\f7df"}.fa-uikit:before{content:"\f403"}.fa-umbraco:before{content:"\f8e8"}.fa-umbrella:before{content:"\f0e9"}.fa-umbrella-beach:before{content:"\f5ca"}.fa-underline:before{content:"\f0cd"}.fa-undo:before{content:"\f0e2"}.fa-undo-alt:before{content:"\f2ea"}.fa-uniregistry:before{content:"\f404"}.fa-unity:before{content:"\e049"}.fa-universal-access:before{content:"\f29a"}.fa-university:before{content:"\f19c"}.fa-unlink:before{content:"\f127"}.fa-unlock:before{content:"\f09c"}.fa-unlock-alt:before{content:"\f13e"}.fa-unsplash:before{content:"\e07c"}.fa-untappd:before{content:"\f405"}.fa-upload:before{content:"\f093"}.fa-ups:before{content:"\f7e0"}.fa-usb:before{content:"\f287"}.fa-user:before{content:"\f007"}.fa-user-alt:before{content:"\f406"}.fa-user-alt-slash:before{content:"\f4fa"}.fa-user-astronaut:before{content:"\f4fb"}.fa-user-check:before{content:"\f4fc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-clock:before{content:"\f4fd"}.fa-user-cog:before{content:"\f4fe"}.fa-user-edit:before{content:"\f4ff"}.fa-user-friends:before{content:"\f500"}.fa-user-graduate:before{content:"\f501"}.fa-user-injured:before{content:"\f728"}.fa-user-lock:before{content:"\f502"}.fa-user-md:before{content:"\f0f0"}.fa-user-minus:before{content:"\f503"}.fa-user-ninja:before{content:"\f504"}.fa-user-nurse:before{content:"\f82f"}.fa-user-plus:before{content:"\f234"}.fa-user-secret:before{content:"\f21b"}.fa-user-shield:before{content:"\f505"}.fa-user-slash:before{content:"\f506"}.fa-user-tag:before{content:"\f507"}.fa-user-tie:before{content:"\f508"}.fa-user-times:before{content:"\f235"}.fa-users:before{content:"\f0c0"}.fa-users-cog:before{content:"\f509"}.fa-users-slash:before{content:"\e073"}.fa-usps:before{content:"\f7e1"}.fa-ussunnah:before{content:"\f407"}.fa-utensil-spoon:before{content:"\f2e5"}.fa-utensils:before{content:"\f2e7"}.fa-vaadin:before{content:"\f408"}.fa-vector-square:before{content:"\f5cb"}.fa-venus:before{content:"\f221"}.fa-venus-double:before{content:"\f226"}.fa-venus-mars:before{content:"\f228"}.fa-viacoin:before{content:"\f237"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-vial:before{content:"\f492"}.fa-vials:before{content:"\f493"}.fa-viber:before{content:"\f409"}.fa-video:before{content:"\f03d"}.fa-video-slash:before{content:"\f4e2"}.fa-vihara:before{content:"\f6a7"}.fa-vimeo:before{content:"\f40a"}.fa-vimeo-square:before{content:"\f194"}.fa-vimeo-v:before{content:"\f27d"}.fa-vine:before{content:"\f1ca"}.fa-virus:before{content:"\e074"}.fa-virus-slash:before{content:"\e075"}.fa-viruses:before{content:"\e076"}.fa-vk:before{content:"\f189"}.fa-vnv:before{content:"\f40b"}.fa-voicemail:before{content:"\f897"}.fa-volleyball-ball:before{content:"\f45f"}.fa-volume-down:before{content:"\f027"}.fa-volume-mute:before{content:"\f6a9"}.fa-volume-off:before{content:"\f026"}.fa-volume-up:before{content:"\f028"}.fa-vote-yea:before{content:"\f772"}.fa-vr-cardboard:before{content:"\f729"}.fa-vuejs:before{content:"\f41f"}.fa-walking:before{content:"\f554"}.fa-wallet:before{content:"\f555"}.fa-warehouse:before{content:"\f494"}.fa-water:before{content:"\f773"}.fa-wave-square:before{content:"\f83e"}.fa-waze:before{content:"\f83f"}.fa-weebly:before{content:"\f5cc"}.fa-weibo:before{content:"\f18a"}.fa-weight:before{content:"\f496"}.fa-weight-hanging:before{content:"\f5cd"}.fa-weixin:before{content:"\f1d7"}.fa-whatsapp:before{content:"\f232"}.fa-whatsapp-square:before{content:"\f40c"}.fa-wheelchair:before{content:"\f193"}.fa-whmcs:before{content:"\f40d"}.fa-wifi:before{content:"\f1eb"}.fa-wikipedia-w:before{content:"\f266"}.fa-wind:before{content:"\f72e"}.fa-window-close:before{content:"\f410"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-windows:before{content:"\f17a"}.fa-wine-bottle:before{content:"\f72f"}.fa-wine-glass:before{content:"\f4e3"}.fa-wine-glass-alt:before{content:"\f5ce"}.fa-wix:before{content:"\f5cf"}.fa-wizards-of-the-coast:before{content:"\f730"}.fa-wolf-pack-battalion:before{content:"\f514"}.fa-won-sign:before{content:"\f159"}.fa-wordpress:before{content:"\f19a"}.fa-wordpress-simple:before{content:"\f411"}.fa-wpbeginner:before{content:"\f297"}.fa-wpexplorer:before{content:"\f2de"}.fa-wpforms:before{content:"\f298"}.fa-wpressr:before{content:"\f3e4"}.fa-wrench:before{content:"\f0ad"}.fa-x-ray:before{content:"\f497"}.fa-xbox:before{content:"\f412"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-y-combinator:before{content:"\f23b"}.fa-yahoo:before{content:"\f19e"}.fa-yammer:before{content:"\f840"}.fa-yandex:before{content:"\f413"}.fa-yandex-international:before{content:"\f414"}.fa-yarn:before{content:"\f7e3"}.fa-yelp:before{content:"\f1e9"}.fa-yen-sign:before{content:"\f157"}.fa-yin-yang:before{content:"\f6ad"}.fa-yoast:before{content:"\f2b1"}.fa-youtube:before{content:"\f167"}.fa-youtube-square:before{content:"\f431"}.fa-zhihu:before{content:"\f63f"}.sr-only{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.sr-only-focusable:active,.sr-only-focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}@font-face{font-family:"Font Awesome 5 Brands";font-style:normal;font-weight:400;font-display:block;src:url(../webfonts/fa-brands-400.eot);src:url(../webfonts/fa-brands-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.woff) format("woff"),url(../webfonts/fa-brands-400.ttf) format("truetype"),url(../webfonts/fa-brands-400.svg#fontawesome) format("svg")}.fab{font-family:"Font Awesome 5 Brands"}@font-face{font-family:"Font Awesome 5 Free";font-style:normal;font-weight:400;font-display:block;src:url(../webfonts/fa-regular-400.eot);src:url(../webfonts/fa-regular-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.woff) format("woff"),url(../webfonts/fa-regular-400.ttf) format("truetype"),url(../webfonts/fa-regular-400.svg#fontawesome) format("svg")}.fab,.far{font-weight:400}@font-face{font-family:"Font Awesome 5 Free";font-style:normal;font-weight:900;font-display:block;src:url(../webfonts/fa-solid-900.eot);src:url(../webfonts/fa-solid-900.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.woff) format("woff"),url(../webfonts/fa-solid-900.ttf) format("truetype"),url(../webfonts/fa-solid-900.svg#fontawesome) format("svg")}.fa,.far,.fas{font-family:"Font Awesome 5 Free"}.fa,.fas{font-weight:900} \ No newline at end of file diff --git a/docs/assets/fontawesome-free-5.14.0-web/webfonts/fa-brands-400.eot b/docs/assets/fontawesome-free-5.14.0-web/webfonts/fa-brands-400.eot deleted file mode 100644 index 54ad8d72dc..0000000000 Binary files a/docs/assets/fontawesome-free-5.14.0-web/webfonts/fa-brands-400.eot and /dev/null differ diff --git a/docs/assets/fontawesome-free-5.14.0-web/webfonts/fa-brands-400.ttf b/docs/assets/fontawesome-free-5.14.0-web/webfonts/fa-brands-400.ttf deleted file mode 100644 index 16852bfd05..0000000000 Binary files a/docs/assets/fontawesome-free-5.14.0-web/webfonts/fa-brands-400.ttf and /dev/null differ diff --git a/docs/assets/fontawesome-free-5.14.0-web/webfonts/fa-brands-400.woff b/docs/assets/fontawesome-free-5.14.0-web/webfonts/fa-brands-400.woff deleted file mode 100644 index 6cf6fb3870..0000000000 Binary files a/docs/assets/fontawesome-free-5.14.0-web/webfonts/fa-brands-400.woff and /dev/null differ diff --git a/docs/assets/fontawesome-free-5.14.0-web/webfonts/fa-brands-400.woff2 b/docs/assets/fontawesome-free-5.14.0-web/webfonts/fa-brands-400.woff2 deleted file mode 100644 index f2a4e36f18..0000000000 Binary files a/docs/assets/fontawesome-free-5.14.0-web/webfonts/fa-brands-400.woff2 and /dev/null differ diff --git a/docs/assets/fontawesome-free-5.14.0-web/webfonts/fa-regular-400.eot b/docs/assets/fontawesome-free-5.14.0-web/webfonts/fa-regular-400.eot deleted file mode 100644 index 479b32cecc..0000000000 Binary files a/docs/assets/fontawesome-free-5.14.0-web/webfonts/fa-regular-400.eot and /dev/null differ diff --git a/docs/assets/fontawesome-free-5.14.0-web/webfonts/fa-regular-400.ttf b/docs/assets/fontawesome-free-5.14.0-web/webfonts/fa-regular-400.ttf deleted file mode 100644 index 42a04fde4e..0000000000 Binary files a/docs/assets/fontawesome-free-5.14.0-web/webfonts/fa-regular-400.ttf and /dev/null differ diff --git a/docs/assets/fontawesome-free-5.14.0-web/webfonts/fa-regular-400.woff b/docs/assets/fontawesome-free-5.14.0-web/webfonts/fa-regular-400.woff deleted file mode 100644 index c390c60e2b..0000000000 Binary files a/docs/assets/fontawesome-free-5.14.0-web/webfonts/fa-regular-400.woff and /dev/null differ diff --git a/docs/assets/fontawesome-free-5.14.0-web/webfonts/fa-regular-400.woff2 b/docs/assets/fontawesome-free-5.14.0-web/webfonts/fa-regular-400.woff2 deleted file mode 100644 index 11c71d28cf..0000000000 Binary files a/docs/assets/fontawesome-free-5.14.0-web/webfonts/fa-regular-400.woff2 and /dev/null differ diff --git a/docs/assets/fontawesome-free-5.14.0-web/webfonts/fa-solid-900.eot b/docs/assets/fontawesome-free-5.14.0-web/webfonts/fa-solid-900.eot deleted file mode 100644 index 52883b93c8..0000000000 Binary files a/docs/assets/fontawesome-free-5.14.0-web/webfonts/fa-solid-900.eot and /dev/null differ diff --git a/docs/assets/fontawesome-free-5.14.0-web/webfonts/fa-solid-900.ttf b/docs/assets/fontawesome-free-5.14.0-web/webfonts/fa-solid-900.ttf deleted file mode 100644 index 7c59512f3c..0000000000 Binary files a/docs/assets/fontawesome-free-5.14.0-web/webfonts/fa-solid-900.ttf and /dev/null differ diff --git a/docs/assets/fontawesome-free-5.14.0-web/webfonts/fa-solid-900.woff b/docs/assets/fontawesome-free-5.14.0-web/webfonts/fa-solid-900.woff deleted file mode 100644 index aff125d658..0000000000 Binary files a/docs/assets/fontawesome-free-5.14.0-web/webfonts/fa-solid-900.woff and /dev/null differ diff --git a/docs/assets/fontawesome-free-5.14.0-web/webfonts/fa-solid-900.woff2 b/docs/assets/fontawesome-free-5.14.0-web/webfonts/fa-solid-900.woff2 deleted file mode 100644 index aa2b79109e..0000000000 Binary files a/docs/assets/fontawesome-free-5.14.0-web/webfonts/fa-solid-900.woff2 and /dev/null differ diff --git a/docs/assets/fontawesome-free-5.14.0-web/LICENSE.txt b/docs/assets/fontawesome-free-5.15.4-web/LICENSE.txt similarity index 100% rename from docs/assets/fontawesome-free-5.14.0-web/LICENSE.txt rename to docs/assets/fontawesome-free-5.15.4-web/LICENSE.txt diff --git a/docs/assets/fontawesome-free-5.15.4-web/css/all.min.css b/docs/assets/fontawesome-free-5.15.4-web/css/all.min.css new file mode 100644 index 0000000000..ac76ff191e --- /dev/null +++ b/docs/assets/fontawesome-free-5.15.4-web/css/all.min.css @@ -0,0 +1,5 @@ +/*! + * Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + */ +.fa,.fab,.fad,.fal,.far,.fas{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-.0667em}.fa-xs{font-size:.75em}.fa-sm{font-size:.875em}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-6x{font-size:6em}.fa-7x{font-size:7em}.fa-8x{font-size:8em}.fa-9x{font-size:9em}.fa-10x{font-size:10em}.fa-fw{text-align:center;width:1.25em}.fa-ul{list-style-type:none;margin-left:2.5em;padding-left:0}.fa-ul>li{position:relative}.fa-li{left:-2em;position:absolute;text-align:center;width:2em;line-height:inherit}.fa-border{border:.08em solid #eee;border-radius:.1em;padding:.2em .25em .15em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left,.fab.fa-pull-left,.fal.fa-pull-left,.far.fa-pull-left,.fas.fa-pull-left{margin-right:.3em}.fa.fa-pull-right,.fab.fa-pull-right,.fal.fa-pull-right,.far.fa-pull-right,.fas.fa-pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s linear infinite;animation:fa-spin 2s linear infinite}.fa-pulse{-webkit-animation:fa-spin 1s steps(8) infinite;animation:fa-spin 1s steps(8) infinite}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-webkit-transform:scaleY(-1);transform:scaleY(-1)}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical,.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical{-webkit-transform:scale(-1);transform:scale(-1)}:root .fa-flip-both,:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{-webkit-filter:none;filter:none}.fa-stack{display:inline-block;height:2em;line-height:2em;position:relative;vertical-align:middle;width:2.5em}.fa-stack-1x,.fa-stack-2x{left:0;position:absolute;text-align:center;width:100%}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-500px:before{content:"\f26e"}.fa-accessible-icon:before{content:"\f368"}.fa-accusoft:before{content:"\f369"}.fa-acquisitions-incorporated:before{content:"\f6af"}.fa-ad:before{content:"\f641"}.fa-address-book:before{content:"\f2b9"}.fa-address-card:before{content:"\f2bb"}.fa-adjust:before{content:"\f042"}.fa-adn:before{content:"\f170"}.fa-adversal:before{content:"\f36a"}.fa-affiliatetheme:before{content:"\f36b"}.fa-air-freshener:before{content:"\f5d0"}.fa-airbnb:before{content:"\f834"}.fa-algolia:before{content:"\f36c"}.fa-align-center:before{content:"\f037"}.fa-align-justify:before{content:"\f039"}.fa-align-left:before{content:"\f036"}.fa-align-right:before{content:"\f038"}.fa-alipay:before{content:"\f642"}.fa-allergies:before{content:"\f461"}.fa-amazon:before{content:"\f270"}.fa-amazon-pay:before{content:"\f42c"}.fa-ambulance:before{content:"\f0f9"}.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-amilia:before{content:"\f36d"}.fa-anchor:before{content:"\f13d"}.fa-android:before{content:"\f17b"}.fa-angellist:before{content:"\f209"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-down:before{content:"\f107"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angry:before{content:"\f556"}.fa-angrycreative:before{content:"\f36e"}.fa-angular:before{content:"\f420"}.fa-ankh:before{content:"\f644"}.fa-app-store:before{content:"\f36f"}.fa-app-store-ios:before{content:"\f370"}.fa-apper:before{content:"\f371"}.fa-apple:before{content:"\f179"}.fa-apple-alt:before{content:"\f5d1"}.fa-apple-pay:before{content:"\f415"}.fa-archive:before{content:"\f187"}.fa-archway:before{content:"\f557"}.fa-arrow-alt-circle-down:before{content:"\f358"}.fa-arrow-alt-circle-left:before{content:"\f359"}.fa-arrow-alt-circle-right:before{content:"\f35a"}.fa-arrow-alt-circle-up:before{content:"\f35b"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-down:before{content:"\f063"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrows-alt:before{content:"\f0b2"}.fa-arrows-alt-h:before{content:"\f337"}.fa-arrows-alt-v:before{content:"\f338"}.fa-artstation:before{content:"\f77a"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asterisk:before{content:"\f069"}.fa-asymmetrik:before{content:"\f372"}.fa-at:before{content:"\f1fa"}.fa-atlas:before{content:"\f558"}.fa-atlassian:before{content:"\f77b"}.fa-atom:before{content:"\f5d2"}.fa-audible:before{content:"\f373"}.fa-audio-description:before{content:"\f29e"}.fa-autoprefixer:before{content:"\f41c"}.fa-avianex:before{content:"\f374"}.fa-aviato:before{content:"\f421"}.fa-award:before{content:"\f559"}.fa-aws:before{content:"\f375"}.fa-baby:before{content:"\f77c"}.fa-baby-carriage:before{content:"\f77d"}.fa-backspace:before{content:"\f55a"}.fa-backward:before{content:"\f04a"}.fa-bacon:before{content:"\f7e5"}.fa-bacteria:before{content:"\e059"}.fa-bacterium:before{content:"\e05a"}.fa-bahai:before{content:"\f666"}.fa-balance-scale:before{content:"\f24e"}.fa-balance-scale-left:before{content:"\f515"}.fa-balance-scale-right:before{content:"\f516"}.fa-ban:before{content:"\f05e"}.fa-band-aid:before{content:"\f462"}.fa-bandcamp:before{content:"\f2d5"}.fa-barcode:before{content:"\f02a"}.fa-bars:before{content:"\f0c9"}.fa-baseball-ball:before{content:"\f433"}.fa-basketball-ball:before{content:"\f434"}.fa-bath:before{content:"\f2cd"}.fa-battery-empty:before{content:"\f244"}.fa-battery-full:before{content:"\f240"}.fa-battery-half:before{content:"\f242"}.fa-battery-quarter:before{content:"\f243"}.fa-battery-three-quarters:before{content:"\f241"}.fa-battle-net:before{content:"\f835"}.fa-bed:before{content:"\f236"}.fa-beer:before{content:"\f0fc"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-bell:before{content:"\f0f3"}.fa-bell-slash:before{content:"\f1f6"}.fa-bezier-curve:before{content:"\f55b"}.fa-bible:before{content:"\f647"}.fa-bicycle:before{content:"\f206"}.fa-biking:before{content:"\f84a"}.fa-bimobject:before{content:"\f378"}.fa-binoculars:before{content:"\f1e5"}.fa-biohazard:before{content:"\f780"}.fa-birthday-cake:before{content:"\f1fd"}.fa-bitbucket:before{content:"\f171"}.fa-bitcoin:before{content:"\f379"}.fa-bity:before{content:"\f37a"}.fa-black-tie:before{content:"\f27e"}.fa-blackberry:before{content:"\f37b"}.fa-blender:before{content:"\f517"}.fa-blender-phone:before{content:"\f6b6"}.fa-blind:before{content:"\f29d"}.fa-blog:before{content:"\f781"}.fa-blogger:before{content:"\f37c"}.fa-blogger-b:before{content:"\f37d"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-bold:before{content:"\f032"}.fa-bolt:before{content:"\f0e7"}.fa-bomb:before{content:"\f1e2"}.fa-bone:before{content:"\f5d7"}.fa-bong:before{content:"\f55c"}.fa-book:before{content:"\f02d"}.fa-book-dead:before{content:"\f6b7"}.fa-book-medical:before{content:"\f7e6"}.fa-book-open:before{content:"\f518"}.fa-book-reader:before{content:"\f5da"}.fa-bookmark:before{content:"\f02e"}.fa-bootstrap:before{content:"\f836"}.fa-border-all:before{content:"\f84c"}.fa-border-none:before{content:"\f850"}.fa-border-style:before{content:"\f853"}.fa-bowling-ball:before{content:"\f436"}.fa-box:before{content:"\f466"}.fa-box-open:before{content:"\f49e"}.fa-box-tissue:before{content:"\e05b"}.fa-boxes:before{content:"\f468"}.fa-braille:before{content:"\f2a1"}.fa-brain:before{content:"\f5dc"}.fa-bread-slice:before{content:"\f7ec"}.fa-briefcase:before{content:"\f0b1"}.fa-briefcase-medical:before{content:"\f469"}.fa-broadcast-tower:before{content:"\f519"}.fa-broom:before{content:"\f51a"}.fa-brush:before{content:"\f55d"}.fa-btc:before{content:"\f15a"}.fa-buffer:before{content:"\f837"}.fa-bug:before{content:"\f188"}.fa-building:before{content:"\f1ad"}.fa-bullhorn:before{content:"\f0a1"}.fa-bullseye:before{content:"\f140"}.fa-burn:before{content:"\f46a"}.fa-buromobelexperte:before{content:"\f37f"}.fa-bus:before{content:"\f207"}.fa-bus-alt:before{content:"\f55e"}.fa-business-time:before{content:"\f64a"}.fa-buy-n-large:before{content:"\f8a6"}.fa-buysellads:before{content:"\f20d"}.fa-calculator:before{content:"\f1ec"}.fa-calendar:before{content:"\f133"}.fa-calendar-alt:before{content:"\f073"}.fa-calendar-check:before{content:"\f274"}.fa-calendar-day:before{content:"\f783"}.fa-calendar-minus:before{content:"\f272"}.fa-calendar-plus:before{content:"\f271"}.fa-calendar-times:before{content:"\f273"}.fa-calendar-week:before{content:"\f784"}.fa-camera:before{content:"\f030"}.fa-camera-retro:before{content:"\f083"}.fa-campground:before{content:"\f6bb"}.fa-canadian-maple-leaf:before{content:"\f785"}.fa-candy-cane:before{content:"\f786"}.fa-cannabis:before{content:"\f55f"}.fa-capsules:before{content:"\f46b"}.fa-car:before{content:"\f1b9"}.fa-car-alt:before{content:"\f5de"}.fa-car-battery:before{content:"\f5df"}.fa-car-crash:before{content:"\f5e1"}.fa-car-side:before{content:"\f5e4"}.fa-caravan:before{content:"\f8ff"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-caret-square-down:before{content:"\f150"}.fa-caret-square-left:before{content:"\f191"}.fa-caret-square-right:before{content:"\f152"}.fa-caret-square-up:before{content:"\f151"}.fa-caret-up:before{content:"\f0d8"}.fa-carrot:before{content:"\f787"}.fa-cart-arrow-down:before{content:"\f218"}.fa-cart-plus:before{content:"\f217"}.fa-cash-register:before{content:"\f788"}.fa-cat:before{content:"\f6be"}.fa-cc-amazon-pay:before{content:"\f42d"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-apple-pay:before{content:"\f416"}.fa-cc-diners-club:before{content:"\f24c"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-cc-visa:before{content:"\f1f0"}.fa-centercode:before{content:"\f380"}.fa-centos:before{content:"\f789"}.fa-certificate:before{content:"\f0a3"}.fa-chair:before{content:"\f6c0"}.fa-chalkboard:before{content:"\f51b"}.fa-chalkboard-teacher:before{content:"\f51c"}.fa-charging-station:before{content:"\f5e7"}.fa-chart-area:before{content:"\f1fe"}.fa-chart-bar:before{content:"\f080"}.fa-chart-line:before{content:"\f201"}.fa-chart-pie:before{content:"\f200"}.fa-check:before{content:"\f00c"}.fa-check-circle:before{content:"\f058"}.fa-check-double:before{content:"\f560"}.fa-check-square:before{content:"\f14a"}.fa-cheese:before{content:"\f7ef"}.fa-chess:before{content:"\f439"}.fa-chess-bishop:before{content:"\f43a"}.fa-chess-board:before{content:"\f43c"}.fa-chess-king:before{content:"\f43f"}.fa-chess-knight:before{content:"\f441"}.fa-chess-pawn:before{content:"\f443"}.fa-chess-queen:before{content:"\f445"}.fa-chess-rook:before{content:"\f447"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-down:before{content:"\f078"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-chevron-up:before{content:"\f077"}.fa-child:before{content:"\f1ae"}.fa-chrome:before{content:"\f268"}.fa-chromecast:before{content:"\f838"}.fa-church:before{content:"\f51d"}.fa-circle:before{content:"\f111"}.fa-circle-notch:before{content:"\f1ce"}.fa-city:before{content:"\f64f"}.fa-clinic-medical:before{content:"\f7f2"}.fa-clipboard:before{content:"\f328"}.fa-clipboard-check:before{content:"\f46c"}.fa-clipboard-list:before{content:"\f46d"}.fa-clock:before{content:"\f017"}.fa-clone:before{content:"\f24d"}.fa-closed-captioning:before{content:"\f20a"}.fa-cloud:before{content:"\f0c2"}.fa-cloud-download-alt:before{content:"\f381"}.fa-cloud-meatball:before{content:"\f73b"}.fa-cloud-moon:before{content:"\f6c3"}.fa-cloud-moon-rain:before{content:"\f73c"}.fa-cloud-rain:before{content:"\f73d"}.fa-cloud-showers-heavy:before{content:"\f740"}.fa-cloud-sun:before{content:"\f6c4"}.fa-cloud-sun-rain:before{content:"\f743"}.fa-cloud-upload-alt:before{content:"\f382"}.fa-cloudflare:before{content:"\e07d"}.fa-cloudscale:before{content:"\f383"}.fa-cloudsmith:before{content:"\f384"}.fa-cloudversify:before{content:"\f385"}.fa-cocktail:before{content:"\f561"}.fa-code:before{content:"\f121"}.fa-code-branch:before{content:"\f126"}.fa-codepen:before{content:"\f1cb"}.fa-codiepie:before{content:"\f284"}.fa-coffee:before{content:"\f0f4"}.fa-cog:before{content:"\f013"}.fa-cogs:before{content:"\f085"}.fa-coins:before{content:"\f51e"}.fa-columns:before{content:"\f0db"}.fa-comment:before{content:"\f075"}.fa-comment-alt:before{content:"\f27a"}.fa-comment-dollar:before{content:"\f651"}.fa-comment-dots:before{content:"\f4ad"}.fa-comment-medical:before{content:"\f7f5"}.fa-comment-slash:before{content:"\f4b3"}.fa-comments:before{content:"\f086"}.fa-comments-dollar:before{content:"\f653"}.fa-compact-disc:before{content:"\f51f"}.fa-compass:before{content:"\f14e"}.fa-compress:before{content:"\f066"}.fa-compress-alt:before{content:"\f422"}.fa-compress-arrows-alt:before{content:"\f78c"}.fa-concierge-bell:before{content:"\f562"}.fa-confluence:before{content:"\f78d"}.fa-connectdevelop:before{content:"\f20e"}.fa-contao:before{content:"\f26d"}.fa-cookie:before{content:"\f563"}.fa-cookie-bite:before{content:"\f564"}.fa-copy:before{content:"\f0c5"}.fa-copyright:before{content:"\f1f9"}.fa-cotton-bureau:before{content:"\f89e"}.fa-couch:before{content:"\f4b8"}.fa-cpanel:before{content:"\f388"}.fa-creative-commons:before{content:"\f25e"}.fa-creative-commons-by:before{content:"\f4e7"}.fa-creative-commons-nc:before{content:"\f4e8"}.fa-creative-commons-nc-eu:before{content:"\f4e9"}.fa-creative-commons-nc-jp:before{content:"\f4ea"}.fa-creative-commons-nd:before{content:"\f4eb"}.fa-creative-commons-pd:before{content:"\f4ec"}.fa-creative-commons-pd-alt:before{content:"\f4ed"}.fa-creative-commons-remix:before{content:"\f4ee"}.fa-creative-commons-sa:before{content:"\f4ef"}.fa-creative-commons-sampling:before{content:"\f4f0"}.fa-creative-commons-sampling-plus:before{content:"\f4f1"}.fa-creative-commons-share:before{content:"\f4f2"}.fa-creative-commons-zero:before{content:"\f4f3"}.fa-credit-card:before{content:"\f09d"}.fa-critical-role:before{content:"\f6c9"}.fa-crop:before{content:"\f125"}.fa-crop-alt:before{content:"\f565"}.fa-cross:before{content:"\f654"}.fa-crosshairs:before{content:"\f05b"}.fa-crow:before{content:"\f520"}.fa-crown:before{content:"\f521"}.fa-crutch:before{content:"\f7f7"}.fa-css3:before{content:"\f13c"}.fa-css3-alt:before{content:"\f38b"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-cut:before{content:"\f0c4"}.fa-cuttlefish:before{content:"\f38c"}.fa-d-and-d:before{content:"\f38d"}.fa-d-and-d-beyond:before{content:"\f6ca"}.fa-dailymotion:before{content:"\e052"}.fa-dashcube:before{content:"\f210"}.fa-database:before{content:"\f1c0"}.fa-deaf:before{content:"\f2a4"}.fa-deezer:before{content:"\e077"}.fa-delicious:before{content:"\f1a5"}.fa-democrat:before{content:"\f747"}.fa-deploydog:before{content:"\f38e"}.fa-deskpro:before{content:"\f38f"}.fa-desktop:before{content:"\f108"}.fa-dev:before{content:"\f6cc"}.fa-deviantart:before{content:"\f1bd"}.fa-dharmachakra:before{content:"\f655"}.fa-dhl:before{content:"\f790"}.fa-diagnoses:before{content:"\f470"}.fa-diaspora:before{content:"\f791"}.fa-dice:before{content:"\f522"}.fa-dice-d20:before{content:"\f6cf"}.fa-dice-d6:before{content:"\f6d1"}.fa-dice-five:before{content:"\f523"}.fa-dice-four:before{content:"\f524"}.fa-dice-one:before{content:"\f525"}.fa-dice-six:before{content:"\f526"}.fa-dice-three:before{content:"\f527"}.fa-dice-two:before{content:"\f528"}.fa-digg:before{content:"\f1a6"}.fa-digital-ocean:before{content:"\f391"}.fa-digital-tachograph:before{content:"\f566"}.fa-directions:before{content:"\f5eb"}.fa-discord:before{content:"\f392"}.fa-discourse:before{content:"\f393"}.fa-disease:before{content:"\f7fa"}.fa-divide:before{content:"\f529"}.fa-dizzy:before{content:"\f567"}.fa-dna:before{content:"\f471"}.fa-dochub:before{content:"\f394"}.fa-docker:before{content:"\f395"}.fa-dog:before{content:"\f6d3"}.fa-dollar-sign:before{content:"\f155"}.fa-dolly:before{content:"\f472"}.fa-dolly-flatbed:before{content:"\f474"}.fa-donate:before{content:"\f4b9"}.fa-door-closed:before{content:"\f52a"}.fa-door-open:before{content:"\f52b"}.fa-dot-circle:before{content:"\f192"}.fa-dove:before{content:"\f4ba"}.fa-download:before{content:"\f019"}.fa-draft2digital:before{content:"\f396"}.fa-drafting-compass:before{content:"\f568"}.fa-dragon:before{content:"\f6d5"}.fa-draw-polygon:before{content:"\f5ee"}.fa-dribbble:before{content:"\f17d"}.fa-dribbble-square:before{content:"\f397"}.fa-dropbox:before{content:"\f16b"}.fa-drum:before{content:"\f569"}.fa-drum-steelpan:before{content:"\f56a"}.fa-drumstick-bite:before{content:"\f6d7"}.fa-drupal:before{content:"\f1a9"}.fa-dumbbell:before{content:"\f44b"}.fa-dumpster:before{content:"\f793"}.fa-dumpster-fire:before{content:"\f794"}.fa-dungeon:before{content:"\f6d9"}.fa-dyalog:before{content:"\f399"}.fa-earlybirds:before{content:"\f39a"}.fa-ebay:before{content:"\f4f4"}.fa-edge:before{content:"\f282"}.fa-edge-legacy:before{content:"\e078"}.fa-edit:before{content:"\f044"}.fa-egg:before{content:"\f7fb"}.fa-eject:before{content:"\f052"}.fa-elementor:before{content:"\f430"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-ello:before{content:"\f5f1"}.fa-ember:before{content:"\f423"}.fa-empire:before{content:"\f1d1"}.fa-envelope:before{content:"\f0e0"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-text:before{content:"\f658"}.fa-envelope-square:before{content:"\f199"}.fa-envira:before{content:"\f299"}.fa-equals:before{content:"\f52c"}.fa-eraser:before{content:"\f12d"}.fa-erlang:before{content:"\f39d"}.fa-ethereum:before{content:"\f42e"}.fa-ethernet:before{content:"\f796"}.fa-etsy:before{content:"\f2d7"}.fa-euro-sign:before{content:"\f153"}.fa-evernote:before{content:"\f839"}.fa-exchange-alt:before{content:"\f362"}.fa-exclamation:before{content:"\f12a"}.fa-exclamation-circle:before{content:"\f06a"}.fa-exclamation-triangle:before{content:"\f071"}.fa-expand:before{content:"\f065"}.fa-expand-alt:before{content:"\f424"}.fa-expand-arrows-alt:before{content:"\f31e"}.fa-expeditedssl:before{content:"\f23e"}.fa-external-link-alt:before{content:"\f35d"}.fa-external-link-square-alt:before{content:"\f360"}.fa-eye:before{content:"\f06e"}.fa-eye-dropper:before{content:"\f1fb"}.fa-eye-slash:before{content:"\f070"}.fa-facebook:before{content:"\f09a"}.fa-facebook-f:before{content:"\f39e"}.fa-facebook-messenger:before{content:"\f39f"}.fa-facebook-square:before{content:"\f082"}.fa-fan:before{content:"\f863"}.fa-fantasy-flight-games:before{content:"\f6dc"}.fa-fast-backward:before{content:"\f049"}.fa-fast-forward:before{content:"\f050"}.fa-faucet:before{content:"\e005"}.fa-fax:before{content:"\f1ac"}.fa-feather:before{content:"\f52d"}.fa-feather-alt:before{content:"\f56b"}.fa-fedex:before{content:"\f797"}.fa-fedora:before{content:"\f798"}.fa-female:before{content:"\f182"}.fa-fighter-jet:before{content:"\f0fb"}.fa-figma:before{content:"\f799"}.fa-file:before{content:"\f15b"}.fa-file-alt:before{content:"\f15c"}.fa-file-archive:before{content:"\f1c6"}.fa-file-audio:before{content:"\f1c7"}.fa-file-code:before{content:"\f1c9"}.fa-file-contract:before{content:"\f56c"}.fa-file-csv:before{content:"\f6dd"}.fa-file-download:before{content:"\f56d"}.fa-file-excel:before{content:"\f1c3"}.fa-file-export:before{content:"\f56e"}.fa-file-image:before{content:"\f1c5"}.fa-file-import:before{content:"\f56f"}.fa-file-invoice:before{content:"\f570"}.fa-file-invoice-dollar:before{content:"\f571"}.fa-file-medical:before{content:"\f477"}.fa-file-medical-alt:before{content:"\f478"}.fa-file-pdf:before{content:"\f1c1"}.fa-file-powerpoint:before{content:"\f1c4"}.fa-file-prescription:before{content:"\f572"}.fa-file-signature:before{content:"\f573"}.fa-file-upload:before{content:"\f574"}.fa-file-video:before{content:"\f1c8"}.fa-file-word:before{content:"\f1c2"}.fa-fill:before{content:"\f575"}.fa-fill-drip:before{content:"\f576"}.fa-film:before{content:"\f008"}.fa-filter:before{content:"\f0b0"}.fa-fingerprint:before{content:"\f577"}.fa-fire:before{content:"\f06d"}.fa-fire-alt:before{content:"\f7e4"}.fa-fire-extinguisher:before{content:"\f134"}.fa-firefox:before{content:"\f269"}.fa-firefox-browser:before{content:"\e007"}.fa-first-aid:before{content:"\f479"}.fa-first-order:before{content:"\f2b0"}.fa-first-order-alt:before{content:"\f50a"}.fa-firstdraft:before{content:"\f3a1"}.fa-fish:before{content:"\f578"}.fa-fist-raised:before{content:"\f6de"}.fa-flag:before{content:"\f024"}.fa-flag-checkered:before{content:"\f11e"}.fa-flag-usa:before{content:"\f74d"}.fa-flask:before{content:"\f0c3"}.fa-flickr:before{content:"\f16e"}.fa-flipboard:before{content:"\f44d"}.fa-flushed:before{content:"\f579"}.fa-fly:before{content:"\f417"}.fa-folder:before{content:"\f07b"}.fa-folder-minus:before{content:"\f65d"}.fa-folder-open:before{content:"\f07c"}.fa-folder-plus:before{content:"\f65e"}.fa-font:before{content:"\f031"}.fa-font-awesome:before{content:"\f2b4"}.fa-font-awesome-alt:before{content:"\f35c"}.fa-font-awesome-flag:before{content:"\f425"}.fa-font-awesome-logo-full:before{content:"\f4e6"}.fa-fonticons:before{content:"\f280"}.fa-fonticons-fi:before{content:"\f3a2"}.fa-football-ball:before{content:"\f44e"}.fa-fort-awesome:before{content:"\f286"}.fa-fort-awesome-alt:before{content:"\f3a3"}.fa-forumbee:before{content:"\f211"}.fa-forward:before{content:"\f04e"}.fa-foursquare:before{content:"\f180"}.fa-free-code-camp:before{content:"\f2c5"}.fa-freebsd:before{content:"\f3a4"}.fa-frog:before{content:"\f52e"}.fa-frown:before{content:"\f119"}.fa-frown-open:before{content:"\f57a"}.fa-fulcrum:before{content:"\f50b"}.fa-funnel-dollar:before{content:"\f662"}.fa-futbol:before{content:"\f1e3"}.fa-galactic-republic:before{content:"\f50c"}.fa-galactic-senate:before{content:"\f50d"}.fa-gamepad:before{content:"\f11b"}.fa-gas-pump:before{content:"\f52f"}.fa-gavel:before{content:"\f0e3"}.fa-gem:before{content:"\f3a5"}.fa-genderless:before{content:"\f22d"}.fa-get-pocket:before{content:"\f265"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-ghost:before{content:"\f6e2"}.fa-gift:before{content:"\f06b"}.fa-gifts:before{content:"\f79c"}.fa-git:before{content:"\f1d3"}.fa-git-alt:before{content:"\f841"}.fa-git-square:before{content:"\f1d2"}.fa-github:before{content:"\f09b"}.fa-github-alt:before{content:"\f113"}.fa-github-square:before{content:"\f092"}.fa-gitkraken:before{content:"\f3a6"}.fa-gitlab:before{content:"\f296"}.fa-gitter:before{content:"\f426"}.fa-glass-cheers:before{content:"\f79f"}.fa-glass-martini:before{content:"\f000"}.fa-glass-martini-alt:before{content:"\f57b"}.fa-glass-whiskey:before{content:"\f7a0"}.fa-glasses:before{content:"\f530"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-globe:before{content:"\f0ac"}.fa-globe-africa:before{content:"\f57c"}.fa-globe-americas:before{content:"\f57d"}.fa-globe-asia:before{content:"\f57e"}.fa-globe-europe:before{content:"\f7a2"}.fa-gofore:before{content:"\f3a7"}.fa-golf-ball:before{content:"\f450"}.fa-goodreads:before{content:"\f3a8"}.fa-goodreads-g:before{content:"\f3a9"}.fa-google:before{content:"\f1a0"}.fa-google-drive:before{content:"\f3aa"}.fa-google-pay:before{content:"\e079"}.fa-google-play:before{content:"\f3ab"}.fa-google-plus:before{content:"\f2b3"}.fa-google-plus-g:before{content:"\f0d5"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-wallet:before{content:"\f1ee"}.fa-gopuram:before{content:"\f664"}.fa-graduation-cap:before{content:"\f19d"}.fa-gratipay:before{content:"\f184"}.fa-grav:before{content:"\f2d6"}.fa-greater-than:before{content:"\f531"}.fa-greater-than-equal:before{content:"\f532"}.fa-grimace:before{content:"\f57f"}.fa-grin:before{content:"\f580"}.fa-grin-alt:before{content:"\f581"}.fa-grin-beam:before{content:"\f582"}.fa-grin-beam-sweat:before{content:"\f583"}.fa-grin-hearts:before{content:"\f584"}.fa-grin-squint:before{content:"\f585"}.fa-grin-squint-tears:before{content:"\f586"}.fa-grin-stars:before{content:"\f587"}.fa-grin-tears:before{content:"\f588"}.fa-grin-tongue:before{content:"\f589"}.fa-grin-tongue-squint:before{content:"\f58a"}.fa-grin-tongue-wink:before{content:"\f58b"}.fa-grin-wink:before{content:"\f58c"}.fa-grip-horizontal:before{content:"\f58d"}.fa-grip-lines:before{content:"\f7a4"}.fa-grip-lines-vertical:before{content:"\f7a5"}.fa-grip-vertical:before{content:"\f58e"}.fa-gripfire:before{content:"\f3ac"}.fa-grunt:before{content:"\f3ad"}.fa-guilded:before{content:"\e07e"}.fa-guitar:before{content:"\f7a6"}.fa-gulp:before{content:"\f3ae"}.fa-h-square:before{content:"\f0fd"}.fa-hacker-news:before{content:"\f1d4"}.fa-hacker-news-square:before{content:"\f3af"}.fa-hackerrank:before{content:"\f5f7"}.fa-hamburger:before{content:"\f805"}.fa-hammer:before{content:"\f6e3"}.fa-hamsa:before{content:"\f665"}.fa-hand-holding:before{content:"\f4bd"}.fa-hand-holding-heart:before{content:"\f4be"}.fa-hand-holding-medical:before{content:"\e05c"}.fa-hand-holding-usd:before{content:"\f4c0"}.fa-hand-holding-water:before{content:"\f4c1"}.fa-hand-lizard:before{content:"\f258"}.fa-hand-middle-finger:before{content:"\f806"}.fa-hand-paper:before{content:"\f256"}.fa-hand-peace:before{content:"\f25b"}.fa-hand-point-down:before{content:"\f0a7"}.fa-hand-point-left:before{content:"\f0a5"}.fa-hand-point-right:before{content:"\f0a4"}.fa-hand-point-up:before{content:"\f0a6"}.fa-hand-pointer:before{content:"\f25a"}.fa-hand-rock:before{content:"\f255"}.fa-hand-scissors:before{content:"\f257"}.fa-hand-sparkles:before{content:"\e05d"}.fa-hand-spock:before{content:"\f259"}.fa-hands:before{content:"\f4c2"}.fa-hands-helping:before{content:"\f4c4"}.fa-hands-wash:before{content:"\e05e"}.fa-handshake:before{content:"\f2b5"}.fa-handshake-alt-slash:before{content:"\e05f"}.fa-handshake-slash:before{content:"\e060"}.fa-hanukiah:before{content:"\f6e6"}.fa-hard-hat:before{content:"\f807"}.fa-hashtag:before{content:"\f292"}.fa-hat-cowboy:before{content:"\f8c0"}.fa-hat-cowboy-side:before{content:"\f8c1"}.fa-hat-wizard:before{content:"\f6e8"}.fa-hdd:before{content:"\f0a0"}.fa-head-side-cough:before{content:"\e061"}.fa-head-side-cough-slash:before{content:"\e062"}.fa-head-side-mask:before{content:"\e063"}.fa-head-side-virus:before{content:"\e064"}.fa-heading:before{content:"\f1dc"}.fa-headphones:before{content:"\f025"}.fa-headphones-alt:before{content:"\f58f"}.fa-headset:before{content:"\f590"}.fa-heart:before{content:"\f004"}.fa-heart-broken:before{content:"\f7a9"}.fa-heartbeat:before{content:"\f21e"}.fa-helicopter:before{content:"\f533"}.fa-highlighter:before{content:"\f591"}.fa-hiking:before{content:"\f6ec"}.fa-hippo:before{content:"\f6ed"}.fa-hips:before{content:"\f452"}.fa-hire-a-helper:before{content:"\f3b0"}.fa-history:before{content:"\f1da"}.fa-hive:before{content:"\e07f"}.fa-hockey-puck:before{content:"\f453"}.fa-holly-berry:before{content:"\f7aa"}.fa-home:before{content:"\f015"}.fa-hooli:before{content:"\f427"}.fa-hornbill:before{content:"\f592"}.fa-horse:before{content:"\f6f0"}.fa-horse-head:before{content:"\f7ab"}.fa-hospital:before{content:"\f0f8"}.fa-hospital-alt:before{content:"\f47d"}.fa-hospital-symbol:before{content:"\f47e"}.fa-hospital-user:before{content:"\f80d"}.fa-hot-tub:before{content:"\f593"}.fa-hotdog:before{content:"\f80f"}.fa-hotel:before{content:"\f594"}.fa-hotjar:before{content:"\f3b1"}.fa-hourglass:before{content:"\f254"}.fa-hourglass-end:before{content:"\f253"}.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-start:before{content:"\f251"}.fa-house-damage:before{content:"\f6f1"}.fa-house-user:before{content:"\e065"}.fa-houzz:before{content:"\f27c"}.fa-hryvnia:before{content:"\f6f2"}.fa-html5:before{content:"\f13b"}.fa-hubspot:before{content:"\f3b2"}.fa-i-cursor:before{content:"\f246"}.fa-ice-cream:before{content:"\f810"}.fa-icicles:before{content:"\f7ad"}.fa-icons:before{content:"\f86d"}.fa-id-badge:before{content:"\f2c1"}.fa-id-card:before{content:"\f2c2"}.fa-id-card-alt:before{content:"\f47f"}.fa-ideal:before{content:"\e013"}.fa-igloo:before{content:"\f7ae"}.fa-image:before{content:"\f03e"}.fa-images:before{content:"\f302"}.fa-imdb:before{content:"\f2d8"}.fa-inbox:before{content:"\f01c"}.fa-indent:before{content:"\f03c"}.fa-industry:before{content:"\f275"}.fa-infinity:before{content:"\f534"}.fa-info:before{content:"\f129"}.fa-info-circle:before{content:"\f05a"}.fa-innosoft:before{content:"\e080"}.fa-instagram:before{content:"\f16d"}.fa-instagram-square:before{content:"\e055"}.fa-instalod:before{content:"\e081"}.fa-intercom:before{content:"\f7af"}.fa-internet-explorer:before{content:"\f26b"}.fa-invision:before{content:"\f7b0"}.fa-ioxhost:before{content:"\f208"}.fa-italic:before{content:"\f033"}.fa-itch-io:before{content:"\f83a"}.fa-itunes:before{content:"\f3b4"}.fa-itunes-note:before{content:"\f3b5"}.fa-java:before{content:"\f4e4"}.fa-jedi:before{content:"\f669"}.fa-jedi-order:before{content:"\f50e"}.fa-jenkins:before{content:"\f3b6"}.fa-jira:before{content:"\f7b1"}.fa-joget:before{content:"\f3b7"}.fa-joint:before{content:"\f595"}.fa-joomla:before{content:"\f1aa"}.fa-journal-whills:before{content:"\f66a"}.fa-js:before{content:"\f3b8"}.fa-js-square:before{content:"\f3b9"}.fa-jsfiddle:before{content:"\f1cc"}.fa-kaaba:before{content:"\f66b"}.fa-kaggle:before{content:"\f5fa"}.fa-key:before{content:"\f084"}.fa-keybase:before{content:"\f4f5"}.fa-keyboard:before{content:"\f11c"}.fa-keycdn:before{content:"\f3ba"}.fa-khanda:before{content:"\f66d"}.fa-kickstarter:before{content:"\f3bb"}.fa-kickstarter-k:before{content:"\f3bc"}.fa-kiss:before{content:"\f596"}.fa-kiss-beam:before{content:"\f597"}.fa-kiss-wink-heart:before{content:"\f598"}.fa-kiwi-bird:before{content:"\f535"}.fa-korvue:before{content:"\f42f"}.fa-landmark:before{content:"\f66f"}.fa-language:before{content:"\f1ab"}.fa-laptop:before{content:"\f109"}.fa-laptop-code:before{content:"\f5fc"}.fa-laptop-house:before{content:"\e066"}.fa-laptop-medical:before{content:"\f812"}.fa-laravel:before{content:"\f3bd"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-laugh:before{content:"\f599"}.fa-laugh-beam:before{content:"\f59a"}.fa-laugh-squint:before{content:"\f59b"}.fa-laugh-wink:before{content:"\f59c"}.fa-layer-group:before{content:"\f5fd"}.fa-leaf:before{content:"\f06c"}.fa-leanpub:before{content:"\f212"}.fa-lemon:before{content:"\f094"}.fa-less:before{content:"\f41d"}.fa-less-than:before{content:"\f536"}.fa-less-than-equal:before{content:"\f537"}.fa-level-down-alt:before{content:"\f3be"}.fa-level-up-alt:before{content:"\f3bf"}.fa-life-ring:before{content:"\f1cd"}.fa-lightbulb:before{content:"\f0eb"}.fa-line:before{content:"\f3c0"}.fa-link:before{content:"\f0c1"}.fa-linkedin:before{content:"\f08c"}.fa-linkedin-in:before{content:"\f0e1"}.fa-linode:before{content:"\f2b8"}.fa-linux:before{content:"\f17c"}.fa-lira-sign:before{content:"\f195"}.fa-list:before{content:"\f03a"}.fa-list-alt:before{content:"\f022"}.fa-list-ol:before{content:"\f0cb"}.fa-list-ul:before{content:"\f0ca"}.fa-location-arrow:before{content:"\f124"}.fa-lock:before{content:"\f023"}.fa-lock-open:before{content:"\f3c1"}.fa-long-arrow-alt-down:before{content:"\f309"}.fa-long-arrow-alt-left:before{content:"\f30a"}.fa-long-arrow-alt-right:before{content:"\f30b"}.fa-long-arrow-alt-up:before{content:"\f30c"}.fa-low-vision:before{content:"\f2a8"}.fa-luggage-cart:before{content:"\f59d"}.fa-lungs:before{content:"\f604"}.fa-lungs-virus:before{content:"\e067"}.fa-lyft:before{content:"\f3c3"}.fa-magento:before{content:"\f3c4"}.fa-magic:before{content:"\f0d0"}.fa-magnet:before{content:"\f076"}.fa-mail-bulk:before{content:"\f674"}.fa-mailchimp:before{content:"\f59e"}.fa-male:before{content:"\f183"}.fa-mandalorian:before{content:"\f50f"}.fa-map:before{content:"\f279"}.fa-map-marked:before{content:"\f59f"}.fa-map-marked-alt:before{content:"\f5a0"}.fa-map-marker:before{content:"\f041"}.fa-map-marker-alt:before{content:"\f3c5"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-markdown:before{content:"\f60f"}.fa-marker:before{content:"\f5a1"}.fa-mars:before{content:"\f222"}.fa-mars-double:before{content:"\f227"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mask:before{content:"\f6fa"}.fa-mastodon:before{content:"\f4f6"}.fa-maxcdn:before{content:"\f136"}.fa-mdb:before{content:"\f8ca"}.fa-medal:before{content:"\f5a2"}.fa-medapps:before{content:"\f3c6"}.fa-medium:before{content:"\f23a"}.fa-medium-m:before{content:"\f3c7"}.fa-medkit:before{content:"\f0fa"}.fa-medrt:before{content:"\f3c8"}.fa-meetup:before{content:"\f2e0"}.fa-megaport:before{content:"\f5a3"}.fa-meh:before{content:"\f11a"}.fa-meh-blank:before{content:"\f5a4"}.fa-meh-rolling-eyes:before{content:"\f5a5"}.fa-memory:before{content:"\f538"}.fa-mendeley:before{content:"\f7b3"}.fa-menorah:before{content:"\f676"}.fa-mercury:before{content:"\f223"}.fa-meteor:before{content:"\f753"}.fa-microblog:before{content:"\e01a"}.fa-microchip:before{content:"\f2db"}.fa-microphone:before{content:"\f130"}.fa-microphone-alt:before{content:"\f3c9"}.fa-microphone-alt-slash:before{content:"\f539"}.fa-microphone-slash:before{content:"\f131"}.fa-microscope:before{content:"\f610"}.fa-microsoft:before{content:"\f3ca"}.fa-minus:before{content:"\f068"}.fa-minus-circle:before{content:"\f056"}.fa-minus-square:before{content:"\f146"}.fa-mitten:before{content:"\f7b5"}.fa-mix:before{content:"\f3cb"}.fa-mixcloud:before{content:"\f289"}.fa-mixer:before{content:"\e056"}.fa-mizuni:before{content:"\f3cc"}.fa-mobile:before{content:"\f10b"}.fa-mobile-alt:before{content:"\f3cd"}.fa-modx:before{content:"\f285"}.fa-monero:before{content:"\f3d0"}.fa-money-bill:before{content:"\f0d6"}.fa-money-bill-alt:before{content:"\f3d1"}.fa-money-bill-wave:before{content:"\f53a"}.fa-money-bill-wave-alt:before{content:"\f53b"}.fa-money-check:before{content:"\f53c"}.fa-money-check-alt:before{content:"\f53d"}.fa-monument:before{content:"\f5a6"}.fa-moon:before{content:"\f186"}.fa-mortar-pestle:before{content:"\f5a7"}.fa-mosque:before{content:"\f678"}.fa-motorcycle:before{content:"\f21c"}.fa-mountain:before{content:"\f6fc"}.fa-mouse:before{content:"\f8cc"}.fa-mouse-pointer:before{content:"\f245"}.fa-mug-hot:before{content:"\f7b6"}.fa-music:before{content:"\f001"}.fa-napster:before{content:"\f3d2"}.fa-neos:before{content:"\f612"}.fa-network-wired:before{content:"\f6ff"}.fa-neuter:before{content:"\f22c"}.fa-newspaper:before{content:"\f1ea"}.fa-nimblr:before{content:"\f5a8"}.fa-node:before{content:"\f419"}.fa-node-js:before{content:"\f3d3"}.fa-not-equal:before{content:"\f53e"}.fa-notes-medical:before{content:"\f481"}.fa-npm:before{content:"\f3d4"}.fa-ns8:before{content:"\f3d5"}.fa-nutritionix:before{content:"\f3d6"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-octopus-deploy:before{content:"\e082"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-oil-can:before{content:"\f613"}.fa-old-republic:before{content:"\f510"}.fa-om:before{content:"\f679"}.fa-opencart:before{content:"\f23d"}.fa-openid:before{content:"\f19b"}.fa-opera:before{content:"\f26a"}.fa-optin-monster:before{content:"\f23c"}.fa-orcid:before{content:"\f8d2"}.fa-osi:before{content:"\f41a"}.fa-otter:before{content:"\f700"}.fa-outdent:before{content:"\f03b"}.fa-page4:before{content:"\f3d7"}.fa-pagelines:before{content:"\f18c"}.fa-pager:before{content:"\f815"}.fa-paint-brush:before{content:"\f1fc"}.fa-paint-roller:before{content:"\f5aa"}.fa-palette:before{content:"\f53f"}.fa-palfed:before{content:"\f3d8"}.fa-pallet:before{content:"\f482"}.fa-paper-plane:before{content:"\f1d8"}.fa-paperclip:before{content:"\f0c6"}.fa-parachute-box:before{content:"\f4cd"}.fa-paragraph:before{content:"\f1dd"}.fa-parking:before{content:"\f540"}.fa-passport:before{content:"\f5ab"}.fa-pastafarianism:before{content:"\f67b"}.fa-paste:before{content:"\f0ea"}.fa-patreon:before{content:"\f3d9"}.fa-pause:before{content:"\f04c"}.fa-pause-circle:before{content:"\f28b"}.fa-paw:before{content:"\f1b0"}.fa-paypal:before{content:"\f1ed"}.fa-peace:before{content:"\f67c"}.fa-pen:before{content:"\f304"}.fa-pen-alt:before{content:"\f305"}.fa-pen-fancy:before{content:"\f5ac"}.fa-pen-nib:before{content:"\f5ad"}.fa-pen-square:before{content:"\f14b"}.fa-pencil-alt:before{content:"\f303"}.fa-pencil-ruler:before{content:"\f5ae"}.fa-penny-arcade:before{content:"\f704"}.fa-people-arrows:before{content:"\e068"}.fa-people-carry:before{content:"\f4ce"}.fa-pepper-hot:before{content:"\f816"}.fa-perbyte:before{content:"\e083"}.fa-percent:before{content:"\f295"}.fa-percentage:before{content:"\f541"}.fa-periscope:before{content:"\f3da"}.fa-person-booth:before{content:"\f756"}.fa-phabricator:before{content:"\f3db"}.fa-phoenix-framework:before{content:"\f3dc"}.fa-phoenix-squadron:before{content:"\f511"}.fa-phone:before{content:"\f095"}.fa-phone-alt:before{content:"\f879"}.fa-phone-slash:before{content:"\f3dd"}.fa-phone-square:before{content:"\f098"}.fa-phone-square-alt:before{content:"\f87b"}.fa-phone-volume:before{content:"\f2a0"}.fa-photo-video:before{content:"\f87c"}.fa-php:before{content:"\f457"}.fa-pied-piper:before{content:"\f2ae"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-pied-piper-hat:before{content:"\f4e5"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-square:before{content:"\e01e"}.fa-piggy-bank:before{content:"\f4d3"}.fa-pills:before{content:"\f484"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-p:before{content:"\f231"}.fa-pinterest-square:before{content:"\f0d3"}.fa-pizza-slice:before{content:"\f818"}.fa-place-of-worship:before{content:"\f67f"}.fa-plane:before{content:"\f072"}.fa-plane-arrival:before{content:"\f5af"}.fa-plane-departure:before{content:"\f5b0"}.fa-plane-slash:before{content:"\e069"}.fa-play:before{content:"\f04b"}.fa-play-circle:before{content:"\f144"}.fa-playstation:before{content:"\f3df"}.fa-plug:before{content:"\f1e6"}.fa-plus:before{content:"\f067"}.fa-plus-circle:before{content:"\f055"}.fa-plus-square:before{content:"\f0fe"}.fa-podcast:before{content:"\f2ce"}.fa-poll:before{content:"\f681"}.fa-poll-h:before{content:"\f682"}.fa-poo:before{content:"\f2fe"}.fa-poo-storm:before{content:"\f75a"}.fa-poop:before{content:"\f619"}.fa-portrait:before{content:"\f3e0"}.fa-pound-sign:before{content:"\f154"}.fa-power-off:before{content:"\f011"}.fa-pray:before{content:"\f683"}.fa-praying-hands:before{content:"\f684"}.fa-prescription:before{content:"\f5b1"}.fa-prescription-bottle:before{content:"\f485"}.fa-prescription-bottle-alt:before{content:"\f486"}.fa-print:before{content:"\f02f"}.fa-procedures:before{content:"\f487"}.fa-product-hunt:before{content:"\f288"}.fa-project-diagram:before{content:"\f542"}.fa-pump-medical:before{content:"\e06a"}.fa-pump-soap:before{content:"\e06b"}.fa-pushed:before{content:"\f3e1"}.fa-puzzle-piece:before{content:"\f12e"}.fa-python:before{content:"\f3e2"}.fa-qq:before{content:"\f1d6"}.fa-qrcode:before{content:"\f029"}.fa-question:before{content:"\f128"}.fa-question-circle:before{content:"\f059"}.fa-quidditch:before{content:"\f458"}.fa-quinscape:before{content:"\f459"}.fa-quora:before{content:"\f2c4"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-quran:before{content:"\f687"}.fa-r-project:before{content:"\f4f7"}.fa-radiation:before{content:"\f7b9"}.fa-radiation-alt:before{content:"\f7ba"}.fa-rainbow:before{content:"\f75b"}.fa-random:before{content:"\f074"}.fa-raspberry-pi:before{content:"\f7bb"}.fa-ravelry:before{content:"\f2d9"}.fa-react:before{content:"\f41b"}.fa-reacteurope:before{content:"\f75d"}.fa-readme:before{content:"\f4d5"}.fa-rebel:before{content:"\f1d0"}.fa-receipt:before{content:"\f543"}.fa-record-vinyl:before{content:"\f8d9"}.fa-recycle:before{content:"\f1b8"}.fa-red-river:before{content:"\f3e3"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-alien:before{content:"\f281"}.fa-reddit-square:before{content:"\f1a2"}.fa-redhat:before{content:"\f7bc"}.fa-redo:before{content:"\f01e"}.fa-redo-alt:before{content:"\f2f9"}.fa-registered:before{content:"\f25d"}.fa-remove-format:before{content:"\f87d"}.fa-renren:before{content:"\f18b"}.fa-reply:before{content:"\f3e5"}.fa-reply-all:before{content:"\f122"}.fa-replyd:before{content:"\f3e6"}.fa-republican:before{content:"\f75e"}.fa-researchgate:before{content:"\f4f8"}.fa-resolving:before{content:"\f3e7"}.fa-restroom:before{content:"\f7bd"}.fa-retweet:before{content:"\f079"}.fa-rev:before{content:"\f5b2"}.fa-ribbon:before{content:"\f4d6"}.fa-ring:before{content:"\f70b"}.fa-road:before{content:"\f018"}.fa-robot:before{content:"\f544"}.fa-rocket:before{content:"\f135"}.fa-rocketchat:before{content:"\f3e8"}.fa-rockrms:before{content:"\f3e9"}.fa-route:before{content:"\f4d7"}.fa-rss:before{content:"\f09e"}.fa-rss-square:before{content:"\f143"}.fa-ruble-sign:before{content:"\f158"}.fa-ruler:before{content:"\f545"}.fa-ruler-combined:before{content:"\f546"}.fa-ruler-horizontal:before{content:"\f547"}.fa-ruler-vertical:before{content:"\f548"}.fa-running:before{content:"\f70c"}.fa-rupee-sign:before{content:"\f156"}.fa-rust:before{content:"\e07a"}.fa-sad-cry:before{content:"\f5b3"}.fa-sad-tear:before{content:"\f5b4"}.fa-safari:before{content:"\f267"}.fa-salesforce:before{content:"\f83b"}.fa-sass:before{content:"\f41e"}.fa-satellite:before{content:"\f7bf"}.fa-satellite-dish:before{content:"\f7c0"}.fa-save:before{content:"\f0c7"}.fa-schlix:before{content:"\f3ea"}.fa-school:before{content:"\f549"}.fa-screwdriver:before{content:"\f54a"}.fa-scribd:before{content:"\f28a"}.fa-scroll:before{content:"\f70e"}.fa-sd-card:before{content:"\f7c2"}.fa-search:before{content:"\f002"}.fa-search-dollar:before{content:"\f688"}.fa-search-location:before{content:"\f689"}.fa-search-minus:before{content:"\f010"}.fa-search-plus:before{content:"\f00e"}.fa-searchengin:before{content:"\f3eb"}.fa-seedling:before{content:"\f4d8"}.fa-sellcast:before{content:"\f2da"}.fa-sellsy:before{content:"\f213"}.fa-server:before{content:"\f233"}.fa-servicestack:before{content:"\f3ec"}.fa-shapes:before{content:"\f61f"}.fa-share:before{content:"\f064"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-share-square:before{content:"\f14d"}.fa-shekel-sign:before{content:"\f20b"}.fa-shield-alt:before{content:"\f3ed"}.fa-shield-virus:before{content:"\e06c"}.fa-ship:before{content:"\f21a"}.fa-shipping-fast:before{content:"\f48b"}.fa-shirtsinbulk:before{content:"\f214"}.fa-shoe-prints:before{content:"\f54b"}.fa-shopify:before{content:"\e057"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-shopping-cart:before{content:"\f07a"}.fa-shopware:before{content:"\f5b5"}.fa-shower:before{content:"\f2cc"}.fa-shuttle-van:before{content:"\f5b6"}.fa-sign:before{content:"\f4d9"}.fa-sign-in-alt:before{content:"\f2f6"}.fa-sign-language:before{content:"\f2a7"}.fa-sign-out-alt:before{content:"\f2f5"}.fa-signal:before{content:"\f012"}.fa-signature:before{content:"\f5b7"}.fa-sim-card:before{content:"\f7c4"}.fa-simplybuilt:before{content:"\f215"}.fa-sink:before{content:"\e06d"}.fa-sistrix:before{content:"\f3ee"}.fa-sitemap:before{content:"\f0e8"}.fa-sith:before{content:"\f512"}.fa-skating:before{content:"\f7c5"}.fa-sketch:before{content:"\f7c6"}.fa-skiing:before{content:"\f7c9"}.fa-skiing-nordic:before{content:"\f7ca"}.fa-skull:before{content:"\f54c"}.fa-skull-crossbones:before{content:"\f714"}.fa-skyatlas:before{content:"\f216"}.fa-skype:before{content:"\f17e"}.fa-slack:before{content:"\f198"}.fa-slack-hash:before{content:"\f3ef"}.fa-slash:before{content:"\f715"}.fa-sleigh:before{content:"\f7cc"}.fa-sliders-h:before{content:"\f1de"}.fa-slideshare:before{content:"\f1e7"}.fa-smile:before{content:"\f118"}.fa-smile-beam:before{content:"\f5b8"}.fa-smile-wink:before{content:"\f4da"}.fa-smog:before{content:"\f75f"}.fa-smoking:before{content:"\f48d"}.fa-smoking-ban:before{content:"\f54d"}.fa-sms:before{content:"\f7cd"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-snowboarding:before{content:"\f7ce"}.fa-snowflake:before{content:"\f2dc"}.fa-snowman:before{content:"\f7d0"}.fa-snowplow:before{content:"\f7d2"}.fa-soap:before{content:"\e06e"}.fa-socks:before{content:"\f696"}.fa-solar-panel:before{content:"\f5ba"}.fa-sort:before{content:"\f0dc"}.fa-sort-alpha-down:before{content:"\f15d"}.fa-sort-alpha-down-alt:before{content:"\f881"}.fa-sort-alpha-up:before{content:"\f15e"}.fa-sort-alpha-up-alt:before{content:"\f882"}.fa-sort-amount-down:before{content:"\f160"}.fa-sort-amount-down-alt:before{content:"\f884"}.fa-sort-amount-up:before{content:"\f161"}.fa-sort-amount-up-alt:before{content:"\f885"}.fa-sort-down:before{content:"\f0dd"}.fa-sort-numeric-down:before{content:"\f162"}.fa-sort-numeric-down-alt:before{content:"\f886"}.fa-sort-numeric-up:before{content:"\f163"}.fa-sort-numeric-up-alt:before{content:"\f887"}.fa-sort-up:before{content:"\f0de"}.fa-soundcloud:before{content:"\f1be"}.fa-sourcetree:before{content:"\f7d3"}.fa-spa:before{content:"\f5bb"}.fa-space-shuttle:before{content:"\f197"}.fa-speakap:before{content:"\f3f3"}.fa-speaker-deck:before{content:"\f83c"}.fa-spell-check:before{content:"\f891"}.fa-spider:before{content:"\f717"}.fa-spinner:before{content:"\f110"}.fa-splotch:before{content:"\f5bc"}.fa-spotify:before{content:"\f1bc"}.fa-spray-can:before{content:"\f5bd"}.fa-square:before{content:"\f0c8"}.fa-square-full:before{content:"\f45c"}.fa-square-root-alt:before{content:"\f698"}.fa-squarespace:before{content:"\f5be"}.fa-stack-exchange:before{content:"\f18d"}.fa-stack-overflow:before{content:"\f16c"}.fa-stackpath:before{content:"\f842"}.fa-stamp:before{content:"\f5bf"}.fa-star:before{content:"\f005"}.fa-star-and-crescent:before{content:"\f699"}.fa-star-half:before{content:"\f089"}.fa-star-half-alt:before{content:"\f5c0"}.fa-star-of-david:before{content:"\f69a"}.fa-star-of-life:before{content:"\f621"}.fa-staylinked:before{content:"\f3f5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-steam-symbol:before{content:"\f3f6"}.fa-step-backward:before{content:"\f048"}.fa-step-forward:before{content:"\f051"}.fa-stethoscope:before{content:"\f0f1"}.fa-sticker-mule:before{content:"\f3f7"}.fa-sticky-note:before{content:"\f249"}.fa-stop:before{content:"\f04d"}.fa-stop-circle:before{content:"\f28d"}.fa-stopwatch:before{content:"\f2f2"}.fa-stopwatch-20:before{content:"\e06f"}.fa-store:before{content:"\f54e"}.fa-store-alt:before{content:"\f54f"}.fa-store-alt-slash:before{content:"\e070"}.fa-store-slash:before{content:"\e071"}.fa-strava:before{content:"\f428"}.fa-stream:before{content:"\f550"}.fa-street-view:before{content:"\f21d"}.fa-strikethrough:before{content:"\f0cc"}.fa-stripe:before{content:"\f429"}.fa-stripe-s:before{content:"\f42a"}.fa-stroopwafel:before{content:"\f551"}.fa-studiovinari:before{content:"\f3f8"}.fa-stumbleupon:before{content:"\f1a4"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-subscript:before{content:"\f12c"}.fa-subway:before{content:"\f239"}.fa-suitcase:before{content:"\f0f2"}.fa-suitcase-rolling:before{content:"\f5c1"}.fa-sun:before{content:"\f185"}.fa-superpowers:before{content:"\f2dd"}.fa-superscript:before{content:"\f12b"}.fa-supple:before{content:"\f3f9"}.fa-surprise:before{content:"\f5c2"}.fa-suse:before{content:"\f7d6"}.fa-swatchbook:before{content:"\f5c3"}.fa-swift:before{content:"\f8e1"}.fa-swimmer:before{content:"\f5c4"}.fa-swimming-pool:before{content:"\f5c5"}.fa-symfony:before{content:"\f83d"}.fa-synagogue:before{content:"\f69b"}.fa-sync:before{content:"\f021"}.fa-sync-alt:before{content:"\f2f1"}.fa-syringe:before{content:"\f48e"}.fa-table:before{content:"\f0ce"}.fa-table-tennis:before{content:"\f45d"}.fa-tablet:before{content:"\f10a"}.fa-tablet-alt:before{content:"\f3fa"}.fa-tablets:before{content:"\f490"}.fa-tachometer-alt:before{content:"\f3fd"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-tape:before{content:"\f4db"}.fa-tasks:before{content:"\f0ae"}.fa-taxi:before{content:"\f1ba"}.fa-teamspeak:before{content:"\f4f9"}.fa-teeth:before{content:"\f62e"}.fa-teeth-open:before{content:"\f62f"}.fa-telegram:before{content:"\f2c6"}.fa-telegram-plane:before{content:"\f3fe"}.fa-temperature-high:before{content:"\f769"}.fa-temperature-low:before{content:"\f76b"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-tenge:before{content:"\f7d7"}.fa-terminal:before{content:"\f120"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-th:before{content:"\f00a"}.fa-th-large:before{content:"\f009"}.fa-th-list:before{content:"\f00b"}.fa-the-red-yeti:before{content:"\f69d"}.fa-theater-masks:before{content:"\f630"}.fa-themeco:before{content:"\f5c6"}.fa-themeisle:before{content:"\f2b2"}.fa-thermometer:before{content:"\f491"}.fa-thermometer-empty:before{content:"\f2cb"}.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-think-peaks:before{content:"\f731"}.fa-thumbs-down:before{content:"\f165"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbtack:before{content:"\f08d"}.fa-ticket-alt:before{content:"\f3ff"}.fa-tiktok:before{content:"\e07b"}.fa-times:before{content:"\f00d"}.fa-times-circle:before{content:"\f057"}.fa-tint:before{content:"\f043"}.fa-tint-slash:before{content:"\f5c7"}.fa-tired:before{content:"\f5c8"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-toilet:before{content:"\f7d8"}.fa-toilet-paper:before{content:"\f71e"}.fa-toilet-paper-slash:before{content:"\e072"}.fa-toolbox:before{content:"\f552"}.fa-tools:before{content:"\f7d9"}.fa-tooth:before{content:"\f5c9"}.fa-torah:before{content:"\f6a0"}.fa-torii-gate:before{content:"\f6a1"}.fa-tractor:before{content:"\f722"}.fa-trade-federation:before{content:"\f513"}.fa-trademark:before{content:"\f25c"}.fa-traffic-light:before{content:"\f637"}.fa-trailer:before{content:"\e041"}.fa-train:before{content:"\f238"}.fa-tram:before{content:"\f7da"}.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-trash:before{content:"\f1f8"}.fa-trash-alt:before{content:"\f2ed"}.fa-trash-restore:before{content:"\f829"}.fa-trash-restore-alt:before{content:"\f82a"}.fa-tree:before{content:"\f1bb"}.fa-trello:before{content:"\f181"}.fa-trophy:before{content:"\f091"}.fa-truck:before{content:"\f0d1"}.fa-truck-loading:before{content:"\f4de"}.fa-truck-monster:before{content:"\f63b"}.fa-truck-moving:before{content:"\f4df"}.fa-truck-pickup:before{content:"\f63c"}.fa-tshirt:before{content:"\f553"}.fa-tty:before{content:"\f1e4"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-tv:before{content:"\f26c"}.fa-twitch:before{content:"\f1e8"}.fa-twitter:before{content:"\f099"}.fa-twitter-square:before{content:"\f081"}.fa-typo3:before{content:"\f42b"}.fa-uber:before{content:"\f402"}.fa-ubuntu:before{content:"\f7df"}.fa-uikit:before{content:"\f403"}.fa-umbraco:before{content:"\f8e8"}.fa-umbrella:before{content:"\f0e9"}.fa-umbrella-beach:before{content:"\f5ca"}.fa-uncharted:before{content:"\e084"}.fa-underline:before{content:"\f0cd"}.fa-undo:before{content:"\f0e2"}.fa-undo-alt:before{content:"\f2ea"}.fa-uniregistry:before{content:"\f404"}.fa-unity:before{content:"\e049"}.fa-universal-access:before{content:"\f29a"}.fa-university:before{content:"\f19c"}.fa-unlink:before{content:"\f127"}.fa-unlock:before{content:"\f09c"}.fa-unlock-alt:before{content:"\f13e"}.fa-unsplash:before{content:"\e07c"}.fa-untappd:before{content:"\f405"}.fa-upload:before{content:"\f093"}.fa-ups:before{content:"\f7e0"}.fa-usb:before{content:"\f287"}.fa-user:before{content:"\f007"}.fa-user-alt:before{content:"\f406"}.fa-user-alt-slash:before{content:"\f4fa"}.fa-user-astronaut:before{content:"\f4fb"}.fa-user-check:before{content:"\f4fc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-clock:before{content:"\f4fd"}.fa-user-cog:before{content:"\f4fe"}.fa-user-edit:before{content:"\f4ff"}.fa-user-friends:before{content:"\f500"}.fa-user-graduate:before{content:"\f501"}.fa-user-injured:before{content:"\f728"}.fa-user-lock:before{content:"\f502"}.fa-user-md:before{content:"\f0f0"}.fa-user-minus:before{content:"\f503"}.fa-user-ninja:before{content:"\f504"}.fa-user-nurse:before{content:"\f82f"}.fa-user-plus:before{content:"\f234"}.fa-user-secret:before{content:"\f21b"}.fa-user-shield:before{content:"\f505"}.fa-user-slash:before{content:"\f506"}.fa-user-tag:before{content:"\f507"}.fa-user-tie:before{content:"\f508"}.fa-user-times:before{content:"\f235"}.fa-users:before{content:"\f0c0"}.fa-users-cog:before{content:"\f509"}.fa-users-slash:before{content:"\e073"}.fa-usps:before{content:"\f7e1"}.fa-ussunnah:before{content:"\f407"}.fa-utensil-spoon:before{content:"\f2e5"}.fa-utensils:before{content:"\f2e7"}.fa-vaadin:before{content:"\f408"}.fa-vector-square:before{content:"\f5cb"}.fa-venus:before{content:"\f221"}.fa-venus-double:before{content:"\f226"}.fa-venus-mars:before{content:"\f228"}.fa-vest:before{content:"\e085"}.fa-vest-patches:before{content:"\e086"}.fa-viacoin:before{content:"\f237"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-vial:before{content:"\f492"}.fa-vials:before{content:"\f493"}.fa-viber:before{content:"\f409"}.fa-video:before{content:"\f03d"}.fa-video-slash:before{content:"\f4e2"}.fa-vihara:before{content:"\f6a7"}.fa-vimeo:before{content:"\f40a"}.fa-vimeo-square:before{content:"\f194"}.fa-vimeo-v:before{content:"\f27d"}.fa-vine:before{content:"\f1ca"}.fa-virus:before{content:"\e074"}.fa-virus-slash:before{content:"\e075"}.fa-viruses:before{content:"\e076"}.fa-vk:before{content:"\f189"}.fa-vnv:before{content:"\f40b"}.fa-voicemail:before{content:"\f897"}.fa-volleyball-ball:before{content:"\f45f"}.fa-volume-down:before{content:"\f027"}.fa-volume-mute:before{content:"\f6a9"}.fa-volume-off:before{content:"\f026"}.fa-volume-up:before{content:"\f028"}.fa-vote-yea:before{content:"\f772"}.fa-vr-cardboard:before{content:"\f729"}.fa-vuejs:before{content:"\f41f"}.fa-walking:before{content:"\f554"}.fa-wallet:before{content:"\f555"}.fa-warehouse:before{content:"\f494"}.fa-watchman-monitoring:before{content:"\e087"}.fa-water:before{content:"\f773"}.fa-wave-square:before{content:"\f83e"}.fa-waze:before{content:"\f83f"}.fa-weebly:before{content:"\f5cc"}.fa-weibo:before{content:"\f18a"}.fa-weight:before{content:"\f496"}.fa-weight-hanging:before{content:"\f5cd"}.fa-weixin:before{content:"\f1d7"}.fa-whatsapp:before{content:"\f232"}.fa-whatsapp-square:before{content:"\f40c"}.fa-wheelchair:before{content:"\f193"}.fa-whmcs:before{content:"\f40d"}.fa-wifi:before{content:"\f1eb"}.fa-wikipedia-w:before{content:"\f266"}.fa-wind:before{content:"\f72e"}.fa-window-close:before{content:"\f410"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-windows:before{content:"\f17a"}.fa-wine-bottle:before{content:"\f72f"}.fa-wine-glass:before{content:"\f4e3"}.fa-wine-glass-alt:before{content:"\f5ce"}.fa-wix:before{content:"\f5cf"}.fa-wizards-of-the-coast:before{content:"\f730"}.fa-wodu:before{content:"\e088"}.fa-wolf-pack-battalion:before{content:"\f514"}.fa-won-sign:before{content:"\f159"}.fa-wordpress:before{content:"\f19a"}.fa-wordpress-simple:before{content:"\f411"}.fa-wpbeginner:before{content:"\f297"}.fa-wpexplorer:before{content:"\f2de"}.fa-wpforms:before{content:"\f298"}.fa-wpressr:before{content:"\f3e4"}.fa-wrench:before{content:"\f0ad"}.fa-x-ray:before{content:"\f497"}.fa-xbox:before{content:"\f412"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-y-combinator:before{content:"\f23b"}.fa-yahoo:before{content:"\f19e"}.fa-yammer:before{content:"\f840"}.fa-yandex:before{content:"\f413"}.fa-yandex-international:before{content:"\f414"}.fa-yarn:before{content:"\f7e3"}.fa-yelp:before{content:"\f1e9"}.fa-yen-sign:before{content:"\f157"}.fa-yin-yang:before{content:"\f6ad"}.fa-yoast:before{content:"\f2b1"}.fa-youtube:before{content:"\f167"}.fa-youtube-square:before{content:"\f431"}.fa-zhihu:before{content:"\f63f"}.sr-only{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.sr-only-focusable:active,.sr-only-focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}@font-face{font-family:"Font Awesome 5 Brands";font-style:normal;font-weight:400;font-display:block;src:url(../webfonts/fa-brands-400.eot);src:url(../webfonts/fa-brands-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.woff) format("woff"),url(../webfonts/fa-brands-400.ttf) format("truetype"),url(../webfonts/fa-brands-400.svg#fontawesome) format("svg")}.fab{font-family:"Font Awesome 5 Brands"}@font-face{font-family:"Font Awesome 5 Free";font-style:normal;font-weight:400;font-display:block;src:url(../webfonts/fa-regular-400.eot);src:url(../webfonts/fa-regular-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.woff) format("woff"),url(../webfonts/fa-regular-400.ttf) format("truetype"),url(../webfonts/fa-regular-400.svg#fontawesome) format("svg")}.fab,.far{font-weight:400}@font-face{font-family:"Font Awesome 5 Free";font-style:normal;font-weight:900;font-display:block;src:url(../webfonts/fa-solid-900.eot);src:url(../webfonts/fa-solid-900.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.woff) format("woff"),url(../webfonts/fa-solid-900.ttf) format("truetype"),url(../webfonts/fa-solid-900.svg#fontawesome) format("svg")}.fa,.far,.fas{font-family:"Font Awesome 5 Free"}.fa,.fas{font-weight:900} \ No newline at end of file diff --git a/docs/assets/fontawesome-free-5.15.4-web/webfonts/fa-brands-400.eot b/docs/assets/fontawesome-free-5.15.4-web/webfonts/fa-brands-400.eot new file mode 100644 index 0000000000..cba6c6cce8 Binary files /dev/null and b/docs/assets/fontawesome-free-5.15.4-web/webfonts/fa-brands-400.eot differ diff --git a/docs/assets/fontawesome-free-5.14.0-web/webfonts/fa-brands-400.svg b/docs/assets/fontawesome-free-5.15.4-web/webfonts/fa-brands-400.svg similarity index 95% rename from docs/assets/fontawesome-free-5.14.0-web/webfonts/fa-brands-400.svg rename to docs/assets/fontawesome-free-5.15.4-web/webfonts/fa-brands-400.svg index 2c8659c12b..b9881a43b7 100644 --- a/docs/assets/fontawesome-free-5.14.0-web/webfonts/fa-brands-400.svg +++ b/docs/assets/fontawesome-free-5.15.4-web/webfonts/fa-brands-400.svg @@ -1,16 +1,12 @@ - -Created by FontForge 20200314 at Wed Jul 15 11:59:41 2020 +Created by FontForge 20201107 at Wed Aug 4 12:25:29 2021 By Robert Madole Copyright (c) Font Awesome - + + + + + + + + + + + - +d="M400 416c26.4922 0 48 -21.5078 48 -48v-352c0 -26.4922 -21.5078 -48 -48 -48h-352c-26.4922 0 -48 21.5078 -48 48v352c0 26.4922 21.5078 48 48 48h352zM336 136v160c-31.5996 -11.2002 -41.2002 -16 -59.7998 -16c-31.4004 0 -43.4004 16 -74.6006 16 +c-25.3994 0 -37.3994 -10.4004 -57.5996 -14.4004v6.40039c0 8.83105 -7.16895 16 -16 16s-16 -7.16895 -16 -16v-192c0 -8.83105 7.16895 -16 16 -16s16 7.16895 16 16v153.6c20.2002 4 32.2002 14.4004 57.5996 14.4004c31.4004 0 43.2002 -16 74.6006 -16 +c10.2002 0 17.7998 1.40039 27.7998 4.59961v-96c-10 -3.19922 -17.5996 -4.59961 -27.7998 -4.59961c-31.4004 0 -43.4004 16 -74.6006 16c-8.91309 -0.0322266 -17.5195 -1.44336 -25.5996 -4v-32c7.86035 2.58398 16.2559 4.00195 24.9756 4.00195 +c0.208008 0 0.416016 0 0.624023 -0.00195312c31.4004 0 43.2002 -16 74.6006 -16c18.5996 0 28.2002 4.7998 59.7998 16z" /> +d="M498.252 213.777c0.129883 -0.613281 0.322266 -1.21777 0.561523 -1.78223v-37.0557c-0.194336 -0.300781 -0.516602 -0.583008 -0.552734 -0.900391c-0.619141 -5.36426 -0.837891 -10.8076 -1.87012 -16.0869c-2.06934 -10.6074 -4.15723 -21.2393 -7.0166 -31.6523 +c-4.94531 -18.0205 -12.7578 -34.8809 -22.2998 -50.9258c-8.94336 -15.126 -19.4043 -28.9668 -31.4268 -41.6387c-3.74609 -3.92188 -7.54688 -7.80078 -11.5107 -11.5c-5.31152 -4.95703 -10.5146 -10.1094 -16.2998 -14.457 +c-9.3418 -7.02344 -18.9883 -13.6533 -28.7373 -20.1006c-15.083 -9.81543 -31.6211 -17.9053 -48.9512 -23.8174c-15.3828 -5.38281 -31.1533 -9.38574 -47.4893 -10.7178c-2.52734 -0.206055 -5.02051 -0.753906 -7.52734 -1.14258h-32.2891 +c-0.358398 0.245117 -0.762695 0.436523 -1.18945 0.55957c-6.1377 0.620117 -12.3418 0.863281 -18.4121 1.87305c-13.8301 2.22949 -27.5977 5.58398 -40.6416 9.83496c-19.5498 6.43359 -38.4463 15.0176 -55.8994 25.2773 +c-15.0488 8.79004 -28.9365 18.9688 -41.7871 30.5859c-9.6875 8.70605 -18.3936 18.0898 -26.3584 28.416c-9.38184 12.1963 -17.4385 25.4316 -24 39.5283c-7.5918 16.6592 -13.3467 34.7812 -16.7295 53.2998c-2.35547 13.1611 -3.85059 26.5459 -4.4248 40.2402 +c-0.136719 3.0332 -0.209961 5.74121 -0.209961 8.80859c0 9.05566 0.599609 17.9717 1.76172 26.7119c1.52637 11.874 4.15625 23.6367 7.69043 34.7588c5.05762 15.7021 12.0283 30.7871 20.4941 44.6006c9.58203 15.9961 20.7793 30.6025 33.6484 43.9502 +c9.55469 9.83496 19.7539 19.0605 29.9268 28.2676c5.70605 5.1582 11.8066 9.9082 17.9736 14.5186c12.0029 9.04004 24.6963 17.1025 38.0801 24.1572c12.5137 6.63281 25.9795 12.1963 39.7686 16.3555c10.9453 3.41016 22.5254 5.84375 34.2559 7.09961 +c2.42773 0.225586 4.82617 0.761719 7.23633 1.15039c10.7627 -0.00195312 21.5254 0 32.2881 0.00585938c0.299805 -0.195312 0.583984 -0.516602 0.899414 -0.552734c6.87793 -0.81543 13.8467 -1.16797 20.627 -2.48242 +c11.2432 -2.18359 22.4971 -4.51465 33.5156 -7.61523c19.999 -5.78125 39.2266 -14.2031 56.7227 -24.668c17.2832 -10.0947 32.9639 -22.1357 47.1133 -36.1152c6.71973 -6.90527 12.9209 -14.0508 18.8174 -21.6895c13.4639 -16.959 24.0283 -36.4561 30.874 -57.5 +c3.88867 -11.8086 7.16211 -24.2148 9.62207 -36.5996c2.0459 -10.1748 2.53809 -20.6602 3.74609 -31zM337.135 214.927l0.00488281 67.2695c-35.2686 0 -53.1152 -9.36719 -62.04 -36.1895v31.9316h-73.5176v-190.738h73.5127v93.667 +c0 22.1396 6.37012 37.04 33.5703 37.04c11.8984 0 28.4697 -2.98047 28.4697 -2.98047z" /> +d="M400 416c26.4922 0 48 -21.5078 48 -48v-352c0 -26.4922 -21.5078 -48 -48 -48h-352c-26.4922 0 -48 21.5078 -48 48v352c0 26.4922 21.5078 48 48 48h352zM416 16v352c0 8.83105 -7.16895 16 -16 16h-352c-8.83105 0 -16 -7.16895 -16 -16v-352 +c0 -8.83105 7.16895 -16 16 -16h352c8.83105 0 16 7.16895 16 16zM201.6 296c31.2002 0 43.2002 -16 74.6006 -16c18.5996 0 28.2002 4.7998 59.7998 16v-160c-31.5996 -11.2002 -41.2002 -16 -59.7998 -16c-31.4004 0 -43.2002 16 -74.6006 16 +c-0.208008 0.00195312 -0.415039 -0.0175781 -0.623047 -0.0175781c-8.7207 0 -17.1162 -1.39844 -24.9766 -3.98242v32c8.08008 2.55664 16.6865 3.96777 25.5996 4c31.2002 0 43.2002 -16 74.6006 -16c10.2002 0 17.7998 1.40039 27.7998 4.59961v96 +c-10 -3.19922 -17.5996 -4.59961 -27.7998 -4.59961c-31.4004 0 -43.2002 16 -74.6006 16c-25.3994 0 -37.3994 -10.4004 -57.5996 -14.4004v-153.6c0 -8.83105 -7.16895 -16 -16 -16s-16 7.16895 -16 16v192c0 8.83105 7.16895 16 16 16s16 -7.16895 16 -16v-6.40039 +c20.2002 4 32.2002 14.4004 57.5996 14.4004z" /> d="M87 -33.7998v73.5996h73.7002v-73.5996h-73.7002zM25.4004 101.4h61.5996v-61.6006h-61.5996v61.6006zM491.6 271.1c53.2002 -170.3 -73 -327.1 -235.6 -327.1v95.7998h0.299805v0.299805c101.7 0.200195 180.5 101 141.4 208 c-14.2998 39.6006 -46.1006 71.4004 -85.7998 85.7002c-107.101 38.7998 -208.101 -39.8994 -208.101 -141.7h-95.7998c0 162.2 156.9 288.7 327 235.601c74.2002 -23.2998 133.6 -82.4004 156.6 -156.601zM256.3 40.0996h-0.299805v-0.299805h-95.2998v95.6006h95.5996 v-95.3008z" /> - + @@ -1917,13 +1982,21 @@ c-42.5 0 -47.3994 -14.8008 -47.3994 -25.9004c0 -13.4004 5.7998 -17.2998 63.2002 +d="M104.324 178.828v26.1777h26.0664v-26.1777h-26.0664zM156.79 205.006h-26.3428v26.1777c-0.124023 7.05762 -5.8916 12.748 -12.9785 12.748c-7.08594 0 -12.8535 -5.69043 -12.9775 -12.748v-0.166016h-26.4004v0.166016 +c-0.000976562 0.119141 -0.000976562 0.220703 -0.000976562 0.339844c0 21.7041 17.6211 39.3242 39.3242 39.3242c21.5039 0 38.999 -17.2959 39.3213 -38.7227v-0.941406zM209.146 179.16v26.0117h26.3438v-26.0117 +c0 -0.0371094 -0.000976562 -0.0722656 -0.000976562 -0.109375c0 -64.7373 -52.5439 -117.3 -117.274 -117.331h-0.774414c-0.0380859 0 -0.0732422 0.000976562 -0.110352 0.000976562c-64.7373 0 -117.299 52.543 -117.33 117.273v0.166016h26.3369 +c0 -50.2793 40.8203 -91.1006 91.0996 -91.1006h0.609375c50.2793 0 91.1006 40.8213 91.1006 91.1006zM51.9131 179.16v25.96h-26.291v25.3994c0 50.6445 41.1162 91.7617 91.7607 91.7617s91.7607 -41.1172 91.7607 -91.7617v-25.293h-26.3438v25.293v0.200195 +c0 36.1055 -29.3135 65.4199 -65.4199 65.4199c-35.7656 0 -64.8672 -28.7646 -65.4121 -64.4023v-26.6201h26.2891v-25.957c0.356445 -21.2305 17.7031 -38.3564 39.0176 -38.3564s38.6611 17.126 39.0176 38.3564h26.3438 +c-0.140625 -35.9551 -29.374 -65.1016 -65.3613 -65.1016s-65.2207 29.1465 -65.3613 65.1016zM470.313 250.333c-11.3467 0 -20.8633 -4.75977 -24.2402 -12.1172v-8.41211c2.21875 -4.53809 6.30859 -7.69238 12.6191 -9.62988 +c4.75879 -1.37891 9.76562 -2.3623 14.832 -2.87793c6.36426 -0.827148 13.0068 -1.71484 20.6992 -4.42676c13.7256 -4.59375 24.0742 -13.2275 28.9443 -24.2412l0.166016 -0.664062l-0.166016 -25.8994c-7.69238 -17.0479 -28.668 -28.4473 -52.2998 -28.4473 +c-25.6797 0 -47.374 12.6182 -55.2891 32.0439l-0.552734 1.43848l23.0205 11.5078l0.719727 -1.49414c5.97754 -12.1211 17.5996 -19.0391 31.9336 -19.0391c12.0098 0 22.083 4.81445 25.791 12.3418v9.85059c-2.37988 4.59473 -6.47656 7.75098 -12.8398 9.85156 +c-5.20312 1.71582 -10.3506 2.37988 -15.8291 3.09961c-6.78809 0.675781 -13.4814 2.04199 -19.8135 3.98438c-14.1123 4.87109 -23.9678 13.2275 -28.668 24.2412c-0.158203 0.949219 -0.123047 -2.02637 0 24.8496c7.36133 17.0469 27.8379 28.4473 50.9727 28.4473 +c24.9062 0 45.3818 -12.0098 53.4062 -31.2705l0.609375 -1.43848l-23.2451 -11.5117l-0.71875 1.5498c-5.47949 11.6221 -16.3818 18.2637 -30.0518 18.2637zM287.568 136.656v68.3994h26.0664v-68.3994h-26.0664zM639.834 189.956l0.166016 -0.722656l-0.166016 -28.8906 +c-7.52734 -15.9941 -27.8916 -26.7305 -50.584 -26.7305s-43.0029 10.7363 -50.585 26.7305l-0.166016 0.720703l0.166016 28.8887c2.93262 6.25391 8.24121 12.0137 15.4414 16.7139c-5.57422 3.90332 -10.0391 9.14453 -13.0068 15.3311l-0.166016 0.664062 +l0.166016 25.3467c7.36133 15.9922 26.7334 26.7324 48.1504 26.7324s40.7881 -10.7402 48.1504 -26.7295l0.166016 -0.664062l-0.166016 -25.3467c-2.90137 -6.22852 -7.38379 -11.4873 -13.0078 -15.3301c7.1416 -4.7041 12.5088 -10.46 15.4414 -16.7139z +M566.614 240.762v-13.7246c3.48535 -6.19922 12.5068 -10.3486 22.5801 -10.3486c10.0723 0 19.0938 4.14844 22.6357 10.3486v13.7246c-3.59766 6.31055 -12.6191 10.5166 -22.6357 10.5166c-10.0176 0 -18.9805 -4.20605 -22.5801 -10.5166zM613.933 168.593v16.1572 +c-3.76367 6.36523 -13.3379 10.5146 -24.6826 10.5146c-11.1836 0 -20.9756 -4.20605 -24.6836 -10.5146v-16.1572c3.70801 -6.52734 13.5586 -10.8994 24.6836 -10.8994c11.3447 0 20.9189 4.25879 24.6826 10.8994zM376.4 182.038v89.7129h25.8994v-135.095h-25.6777 +l-62.5391 94.085v0.386719h-26.5098v40.623h29z" /> +d="M284.046 223.2c0.0341797 0 0.0664062 -0.00195312 0.100586 -0.00195312c18.8496 0 34.1592 -15.2754 34.2168 -34.1113c0 -18.8281 -15.2822 -34.1143 -34.1104 -34.1143s-34.1143 15.2861 -34.1143 34.1143c0 18.7588 15.1748 34.002 33.9072 34.1133zM173.596 223.2 +c0.0332031 0 0.0673828 -0.00195312 0.100586 -0.00195312c18.8496 0 34.1592 -15.2754 34.2168 -34.1113c0 -18.8281 -15.2822 -34.1143 -34.1104 -34.1143s-34.1143 15.2861 -34.1143 34.1143c0 18.7588 15.1748 34.002 33.9072 34.1133zM394.519 223.2 +c0.0351562 0 0.0683594 -0.00195312 0.102539 -0.00195312c18.8496 0 34.1592 -15.2754 34.2148 -34.1113c0 -18.8281 -15.2822 -34.1143 -34.1104 -34.1143s-34.1133 15.2861 -34.1133 34.1143c0 18.7588 15.1738 34.002 33.9062 34.1133zM548.326 278.519 +c17.3076 -26.9443 26.0674 -55.9189 26.0898 -86.9395c0 -30.209 -8.76074 -59.2021 -26.0703 -86.125c-15.5342 -24.1934 -37.3076 -45.5703 -64.6787 -63.6191c-52.8672 -34.8164 -122.354 -53.9746 -195.667 -53.9746 +c-0.150391 -0.000976562 0.0664062 -0.00585938 -0.0830078 -0.00585938c-24.5488 0 -48.5908 2.18359 -71.9443 6.36621c-14.8564 -14.2842 -31.3604 -26.5059 -49.5098 -36.5889c-66.7744 -33.3467 -125.6 -20.9092 -155.324 -10.2002 +c-5.54492 1.96289 -9.51758 7.25488 -9.51758 13.4697c0 3.82715 1.50879 7.30469 3.96289 9.87109c20.9619 21.6748 55.6416 64.5342 47.1162 103.49c-33.1426 33.9004 -51.1123 74.7764 -51.1123 118.148c0 42.5605 17.9697 83.4365 51.1123 117.337 +c8.52148 38.9521 -26.1582 81.7939 -47.1201 103.47c-2.45996 2.56738 -3.97656 6.0498 -3.97656 9.88281c0 6.21973 3.98047 11.5156 9.53125 13.4785c29.7246 10.71 88.5488 23.1211 155.302 -10.2109c18.1504 -10.0811 34.6553 -22.3027 49.5107 -36.5879 +c23.3457 4.18066 47.0137 6.35742 71.5547 6.35742c0.15918 0 0.318359 -0.000976562 0.476562 -0.000976562c73.293 0 142.78 -19.1826 195.666 -54c27.3711 -18.0479 49.1465 -39.4453 64.6816 -63.6182zM284.987 38.0996c128.612 0 232.866 67.376 232.866 150.487 +c0 83.0957 -104.274 150.469 -232.866 150.469c-128.593 0 -232.847 -67.3691 -232.847 -150.469c0 -36.2002 19.7861 -69.4375 52.7783 -95.4004c9.28809 -29.5986 3.84668 -62.958 -16.3252 -100.078c-0.960938 -1.79297 -1.8584 -3.58496 -2.8418 -5.35645 +c18.6367 1.63574 36.5557 6.875 52.5225 14.8701c13.5889 7.65625 25.9609 16.8633 37.1377 27.585l20.1289 19.3926c28.2617 -7.47852 57.8037 -11.501 88.4033 -11.501c0.347656 0 0.695312 0 1.04297 0.000976562z" /> @@ -2379,10 +2455,11 @@ c13.7002 9.39941 16.4004 24.3994 9.10059 31.3994c-7.2002 6.90039 -28.2002 -7 -29 c12.5996 33.0996 -3.59961 45.5 -3.59961 45.5s-23.4004 12.9004 -33.3008 -20.2002c-9.89941 -33.0996 -6.39941 -44.8994 -6.39941 -44.8994s30.7002 -13.4004 43.2998 19.5996zM442.1 188.1c0 0 15.7002 -1.09961 26.4004 14.2002s1.2998 25.5 1.2998 25.5 s-8.59961 11.1006 -19.5996 -9.09961c-11.1006 -20.1006 -8.10059 -30.6006 -8.10059 -30.6006z" /> +d="M448 400v-336c-63 -23 -82 -32 -119 -32c-63 0 -87 32 -150 32c-20 0 -36 -4 -51 -8v64c15 4 31 8 51 8c63 0 87 -32 150 -32c20 0 35 3 55 9v208c-20 -6 -35 -9 -55 -9c-63 0 -87 32 -150 32c-51 0 -75 -21 -115 -29v-307 +c0.00195312 -0.136719 0.00292969 -0.273438 0.00292969 -0.410156c0 -17.4404 -14.1602 -31.5996 -31.6006 -31.5996c-0.136719 0 -0.265625 0.0078125 -0.402344 0.00976562c-0.136719 -0.00195312 -0.273438 -0.00292969 -0.410156 -0.00292969 +c-17.4404 0 -31.5996 14.1602 -31.5996 31.6006c0 0.136719 0.0078125 0.265625 0.00976562 0.402344v384c-0.00195312 0.136719 -0.00292969 0.273438 -0.00292969 0.410156c0 17.4404 14.1602 31.5996 31.6006 31.5996 +c0.136719 0 0.265625 -0.0078125 0.402344 -0.00976562c0.136719 0.00195312 0.273438 0.00292969 0.410156 0.00292969c17.4404 0 31.5996 -14.1602 31.5996 -31.6006c0 -0.136719 -0.0078125 -0.265625 -0.00976562 -0.402344v-13c40 8 64 29 115 29c63 0 87 -32 150 -32 +c37 0 56 9 119 32z" /> - @@ -3345,9 +3420,13 @@ M353.9 173.3c3.55273 2.83594 6.87891 5.7998 10.0996 9l-34.9004 35c-3.18457 -3.22 c2.53027 3.79688 4.77832 7.81738 6.7002 12l-39.5 39.7998c-0.374023 -5.3252 -1.63574 -10.4893 -3.59961 -15.2002zM391.6 230.8l-53.0996 53.4004c4.25977 -7.79688 6.82422 -16.7627 7.09961 -26.2002l41.3008 -41.5c1.7959 4.61523 3.39258 9.46387 4.69922 14.2998z M392.6 236.4c1.25586 5.3623 2.04199 10.9189 2.30078 16.5996l-64.3008 64.7002c-2.61426 -3.74805 -5.95898 -6.85938 -9.89941 -9.2002z" /> +d="M14 352.208c0 52.9043 42.8877 95.792 95.793 95.792h164.368c52.9053 0 95.793 -42.8877 95.793 -95.792c0 -33.5 -17.1963 -62.9844 -43.2432 -80.1055c26.0469 -17.1211 43.2432 -46.6045 43.2432 -80.1045c0 -52.9053 -42.8877 -95.793 -95.793 -95.793h-2.08008 +c-24.8018 0 -47.4033 9.42578 -64.415 24.8906v-88.2627c0 -53.6104 -44.0088 -96.833 -97.3574 -96.833c-52.7725 0 -96.3086 42.7568 -96.3086 95.793c0 33.498 17.1943 62.9805 43.2393 80.1016c-26.0449 17.1221 -43.2393 46.6055 -43.2393 80.1035 +c0 33.5 17.1963 62.9834 43.2422 80.1045c-26.0459 17.1211 -43.2422 46.6055 -43.2422 80.1055zM176.288 256.413h-66.4951c-35.5762 0 -64.415 -28.8398 -64.415 -64.415c0 -35.4385 28.6172 -64.1924 64.0029 -64.4141 +c0.136719 0.000976562 0.274414 0.000976562 0.412109 0.000976562h66.4951v128.828zM207.666 191.998c0 -35.5752 28.8389 -64.415 64.415 -64.415h2.08008c35.5762 0 64.415 28.8398 64.415 64.415s-28.8389 64.415 -64.415 64.415h-2.08008 +c-35.5762 0 -64.415 -28.8398 -64.415 -64.415zM109.793 96.2051c-0.137695 0 -0.275391 0.000976562 -0.412109 0.000976562c-35.3857 -0.220703 -64.0029 -28.9746 -64.0029 -64.4131c0 -35.4453 29.2246 -64.415 64.9307 -64.415 +c36.2822 0 65.9795 29.4365 65.9795 65.4551v63.3721h-66.4951zM109.793 416.622c-35.5762 0 -64.415 -28.8398 -64.415 -64.4141c0 -35.5762 28.8389 -64.415 64.415 -64.415h66.4951v128.829h-66.4951zM207.666 287.793h66.4951c35.5762 0 64.415 28.8389 64.415 64.415 +c0 35.5742 -28.8389 64.4141 -64.415 64.4141h-66.4951v-128.829z" /> - + - -Created by FontForge 20200314 at Wed Jul 15 11:59:40 2020 +Created by FontForge 20201107 at Wed Aug 4 12:25:29 2021 By Robert Madole Copyright (c) Font Awesome - + - -Created by FontForge 20200314 at Wed Jul 15 11:59:41 2020 +Created by FontForge 20201107 at Wed Aug 4 12:25:29 2021 By Robert Madole Copyright (c) Font Awesome - + + + @@ -3707,11 +3720,17 @@ c0 53.0195 42.9805 96 96 96c53.0205 0 96 -42.9805 96 -96c0 -11.2803 -2.30957 -21 - + + + + + PMD + + + + image/svg+xml + + PMD + + + http://www.bijzonderbezig.nl + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/index.md b/docs/index.md index be951ab7f8..49ab4fd093 100644 --- a/docs/index.md +++ b/docs/index.md @@ -26,7 +26,7 @@ additional_js: **PMD** is a static source code analyzer. It finds common programming flaws like unused variables, empty catch blocks, unnecessary object creation, and -so forth. It's mainly concerned with **Java and Apex**, but **supports 14 other +so forth. It's mainly concerned with **Java and Apex**, but **supports 16 other languages**. PMD features many **built-in checks** (in PMD lingo, *rules*), which are documented diff --git a/docs/pages/pmd/devdocs/how_pmd_works.md b/docs/pages/pmd/devdocs/how_pmd_works.md index 1ac3f99929..f91b76757d 100644 --- a/docs/pages/pmd/devdocs/how_pmd_works.md +++ b/docs/pages/pmd/devdocs/how_pmd_works.md @@ -9,10 +9,7 @@ author: Tom Copeland, Andreas Dangel ## Overview -The processing starts e.g. with the main class: `net.sourceforge.pmd.PMD` - -{%include note.html content="This is the command line interface. There are many other means, who -PMD can be invoked. E.g. via ant, maven, gradle..." %} +The processing starts with the main class {% jdoc core::PmdAnalysis %}. * Parse command line parameters (see net.sourceforge.pmd.cli.PMDParameters) Also load the incremental analysis cache file diff --git a/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md b/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md index 4ee9585405..473648ea00 100644 --- a/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md +++ b/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md @@ -3,15 +3,10 @@ title: Adding PMD support for a new ANTLR grammar based language short_title: Adding a new language with ANTLR tags: [devdocs, extending] summary: "How to add a new language to PMD using ANTLR grammar." -last_updated: February 2023 (7.0.0) +last_updated: April 2023 (7.0.0) sidebar: pmd_sidebar permalink: pmd_devdocs_major_adding_new_language_antlr.html folder: pmd/devdocs - -# -# needs to be changed to branch master instead of pmd/7.0.x once pmd7 is released -# https://github.com/pmd/pmd/blob/pmd/7.0.x -> https://github.com/pmd/pmd/blob/master -# --- {% include callout.html type="warning" content=" @@ -21,27 +16,33 @@ folder: pmd/devdocs This is really a big contribution and can't be done with a drive by contribution. It requires dedicated passion and long commitment to implement support for a new language.

-This step-by-step guide is just a small intro to get the basics started and it's also not necessarily up-to-date -or complete and you have to be able to fill in the blanks.

+This step-by-step guide is just a small intro to get the basics started, and it's also not necessarily up-to-date +or complete. You have to be able to fill in the blanks.

-Currently the Antlr integration has some basic limitations compared to JavaCC: The output of the -Antlr parser generator is not an abstract syntax tree (AST) but a parse tree. As such, a parse tree is -much more fine-grained than what a typical JavaCC grammar will produce. This means that the +Currently, the Antlr integration has some basic **limitations** compared to JavaCC: The output of the +Antlr parser generator is not an abstract syntax tree (AST) but a parse tree (also known as CST, concrete syntax tree). +As such, a parse tree is much more fine-grained than what a typical JavaCC grammar will produce. This means that the parse tree is much deeper and contains nodes down to the different token types.

-The Antlr nodes themselves don't have any attributes because they are on the wrong abstraction level. -As they don't have attributes, there are no attributes that can be used in XPath based rules.

+The Antlr nodes are context objects and serve a different abstraction than nodes in an AST. These context objects +themselves don't have any attributes because they themselves represent the attributes (as nodes or leaves in the +parse tree). As they don't have attributes, there are no attributes that can be used in XPath based rules.

+ +The current implementation of the languages using ANTLR use these context objects as nodes in PMD's AST +representation.

In order to overcome these limitations, one would need to implement a post-processing step that transforms -a parse tree into an abstract syntax tree and introducing real nodes on a higher abstraction level. This -step is **not** described in this guide.

+a parse tree into an abstract syntax tree and introducing real nodes on a higher abstraction level. These +real nodes can then have attributes which are available in XPath based rules. The transformation can happen +with a visitor, but the implementation of the AST is a manual step. This step is **not** described +in this guide.

After the basic support for a language is there, there are lots of missing features left. Typical features that can greatly improve rule writing are: symbol table, type resolution, call/data flow analysis.

Symbol table keeps track of variables and their usages. Type resolution tries to find the actual class type of each used type, following along method calls (including overloaded and overwritten methods), allowing -to query sub types and type hierarchy. This requires additional configuration of an auxiliary classpath. +to query subtypes and type hierarchy. This requires additional configuration of an auxiliary classpath. Call and data flow analysis keep track of the data as it is moving through different execution paths a program has.

@@ -52,37 +53,57 @@ definitely don't come for free. It is much effort and requires perseverance to i ## 1. Start with a new sub-module * See pmd-swift for examples. +* Make sure to add your new module to PMD's parent pom as `` entry, so that it is built alongside the + other languages. +* Also add your new module to the dependencies list in "pmd-languages-deps/pom.xml", so that the new language + is automatically available in the binary distribution (pmd-dist) as well as for the shell-completion + in the pmd-cli module. + ## 2. Implement an AST parser for your language * ANTLR will generate the parser for you based on the grammar file. The grammar file needs to be placed in the folder `src/main/antlr4` in the appropriate sub package `ast` of the language. E.g. for swift, the grammar - file is [Swift.g4](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-swift/src/main/antlr4/net/sourceforge/pmd/lang/swift/ast/Swift.g4) + file is [Swift.g4](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/antlr4/net/sourceforge/pmd/lang/swift/ast/Swift.g4) and is placed in the package `net.sourceforge.pmd.lang.swift.ast`. +* Configure the options "superClass" and "contextSuperClass". These are the base classes for the generated + classes. ## 3. Create AST node classes * The individual AST nodes are generated, but you need to define the common interface for them. * You need to define the supertype interface for all nodes of the language. For that, we provide - [`AntlrNode`](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/antlr4/AntlrNode.java). -* See [`SwiftNode`](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/ast/SwiftNode.java) + [`AntlrNode`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/antlr4/AntlrNode.java). +* See [`SwiftNode`](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/ast/SwiftNode.java) as an example. * Additionally, you need several base classes: * a language specific inner node - these nodes represent the production rules from the grammar. In Antlr, they are called "ParserRuleContext". We call them "InnerNode". Use the base class from pmd-core - [`BaseAntlrInnerNode`](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/antlr4/BaseAntlrInnerNode.java) - . And example is [`SwiftInnerNode`](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/ast/SwiftInnerNode.java). + [`BaseAntlrInnerNode`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/antlr4/BaseAntlrInnerNode.java) + . And example is [`SwiftInnerNode`](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/ast/SwiftInnerNode.java). + Note that this language specific inner node is package-private, as it is only the base class for the concrete + nodes generated by ANLTR. * a language specific root node - this provides the root of the AST and our parser will return subtypes of this node. The root node itself is a "InnerNode". - See [`SwiftRootNode`](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/ast/SwiftRootNode.java). + See [`SwiftRootNode`](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/ast/SwiftRootNode.java). + Note that this language specific root node is package-private, as it is only the base class for the concrete + node generated by ANLTR. * a language specific terminal node. - See [`SwiftTerminalNode`](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/ast/SwiftTerminalNode.java). + See [`SwiftTerminalNode`](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/ast/SwiftTerminalNode.java). * a language specific error node. - See [`SwiftErrorNode`](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/ast/SwiftErrorNode.java). + See [`SwiftErrorNode`](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/ast/SwiftErrorNode.java). + * a language name dictionary. This is used to convert ANTLR node names to useful XPath node names. + See [`SwiftNameDictionary'](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/ast/SwiftNameDictionary.java). +* Once these base classes exist, you need to change the ANTLR grammar to add additional members via `@parser::members` + * Define a package private field `DICO` which creates a new instance of your language name dictionary using the + vocabulary from the generated parser (`VOCABULARY`). + * Define two additional methods to help converting the ANTLR context objects into PMD AST nodes. + The methods are abstract in [`AntlrGeneratedParserBase`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/antlr4/AntlrGeneratedParserBase.java) + and need to be implemented here for the concrete language: `createPmdTerminal()` and `createPmdError()`. * In order for the generated code to match and use our custom classes, we have a common ant script, that fiddles with - the generated code. The ant script is [`antlr4-wrapper.xml`](https://github.com/pmd/pmd/blob/pmd/7.0.x/antlr4-wrapper.xml) and - does not need to be adjusted - it has plenty of parameters to set. The ant script is added in the - language module's `pom.xml` where the parameters are set (e.g. name of root name class). Have a look at - Swift's example: [`pmd-swift/pom.xml`](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-swift/pom.xml). + the generated code. The ant script is [`antlr4-wrapper.xml`](https://github.com/pmd/pmd/blob/master/antlr4-wrapper.xml) + and does not need to be adjusted - it has plenty of parameters that can be configured. + The ant script is added in the language module's `pom.xml` where the parameters are set (e.g. name of root name + class). Have a look at Swift's example: [`pmd-swift/pom.xml`](https://github.com/pmd/pmd/blob/master/pmd-swift/pom.xml). * You can add additional methods in your "InnerNode" (e.g. `SwiftInnerNode`) that are available on all nodes. But on most cases you won't need to do anything. @@ -93,31 +114,31 @@ definitely don't come for free. It is much effort and requires perseverance to i have the parser generated. * The generated code will be placed under `target/generated-sources/antlr4` and will not be committed to source control. -* You should review the [swift pom](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-swift/pom.xml). +* You should review [`pmd-swift/pom.xml`](https://github.com/pmd/pmd/blob/master/pmd-swift/pom.xml). ## 5. Create a TokenManager * This is needed to support CPD (copy paste detection) -* We provide a default implementation using [`AntlrTokenManager`](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-core/src/main/java/net/sourceforge/pmd/cpd/internal/AntlrTokenizer.java). +* We provide a default implementation using [`AntlrTokenManager`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/impl/AntlrTokenizer.java). * You must create your own "AntlrTokenizer" such as we do with - [`SwiftTokenizer`](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-swift/src/main/java/net/sourceforge/pmd/cpd/SwiftTokenizer.java). + [`SwiftTokenizer`](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/java/net/sourceforge/pmd/cpd/SwiftTokenizer.java). * If you wish to filter specific tokens (e.g. comments to support CPD suppression via "CPD-OFF" and "CPD-ON") you can create your own implementation of - [`AntlrTokenFilter`](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-core/src/main/java/net/sourceforge/pmd/cpd/token/AntlrTokenFilter.java). + [`AntlrTokenFilter`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/token/AntlrTokenFilter.java). You'll need to override then the protected method `getTokenFilter(AntlrTokenManager)` and return your custom filter. See the tokenizer for C# as an exmaple: - [`CsTokenizer`](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-cs/src/main/java/net/sourceforge/pmd/cpd/CsTokenizer.java). + [`CsTokenizer`](https://github.com/pmd/pmd/blob/master/pmd-cs/src/main/java/net/sourceforge/pmd/cpd/CsTokenizer.java). If you don't need a custom token filter, you don't need to override the method. It returns the default `AntlrTokenFilter` which doesn't filter anything. ## 6. Create a PMD parser “adapter” * Create your own parser, that adapts the ANLTR interface to PMD's parser interface. -* We provide a [`AntlrBaseParser`](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/antlr4/AntlrBaseParser.java) +* We provide a [`AntlrBaseParser`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/antlr4/AntlrBaseParser.java) implementation that you need to extend to create your own adapter as we do with - [`PmdSwiftParser`](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/ast/PmdSwiftParser.java). + [`PmdSwiftParser`](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/ast/PmdSwiftParser.java). ## 7. Create a language version handler -* Now you need to create your version handler, as we did with [`SwiftHandler`](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/SwiftHandler.java). +* Now you need to create your version handler, as we did with [`SwiftHandler`](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/SwiftHandler.java). * This class is sort of a gateway between PMD and all parsing logic specific to your language. * For a minimal implementation, it just needs to return a parser *(see step #6)*. * It can be used to provide other features for your language like @@ -130,15 +151,15 @@ definitely don't come for free. It is much effort and requires perseverance to i * A parser visitor adapter is not needed anymore with PMD 7. The visitor interface now provides a default implementation. * The visitor for ANTLR based AST is generated along the parser from the ANTLR grammar file. The - base interface for a visitor is [`AstVisitor`](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/AstVisitor.java). + base interface for a visitor is [`AstVisitor`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/AstVisitor.java). * The generated visitor class for Swift is called `SwiftVisitor`. * In order to help use this visitor later on, a base visitor class should be created. - See [`SwiftVisitorBase`](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/ast/SwiftVisitorBase.java) + See [`SwiftVisitorBase`](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/ast/SwiftVisitorBase.java) as an example. ## 9. Make PMD recognize your language * Create your own subclass of `net.sourceforge.pmd.lang.impl.SimpleLanguageModuleBase`, see Swift as an example: - [`SwiftLanguageModule`](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/SwiftLanguageModule.java). + [`SwiftLanguageModule`](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/SwiftLanguageModule.java). * Add for each version of your language a call to `addVersion` in your language module’s constructor. Use `addDefaultVersion` for defining the default version. * You’ll need to refer the language version handler created in step #7. @@ -146,15 +167,21 @@ definitely don't come for free. It is much effort and requires perseverance to i Add your fully qualified class name as a single line into it. ## 10. Create an abstract rule class for the language -* You need to create your own `AbstractRule` in order to interface your language with PMD's generic rule +* You need to create your own abstract rule class in order to interface your language with PMD's generic rule execution. -* See [`AbstractSwiftRule`](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/AbstractSwiftRule.java) as an example. -* While the rule basically just extends - [`AntlrBaseRule`](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/antlr4/AntlrBaseRule.java) without adding anything, every language should have its own base class for rule. +* See [`AbstractSwiftRule`](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/AbstractSwiftRule.java) as an example. +* The rule basically just extends + [`AbstractVisitorRule`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/AbstractVisitorRule.java) + and only redefines the abstract `buildVisitor()` method to return our own type of visitor. + In this case our `SwiftVisitor` is used. + While there is no real functionality added, every language should have its own base class for rules. This helps to organize the code. * All other rules for your language should extend this class. The purpose of this class is to provide a visitor via the method `buildVisitor()` for analyzing the AST. The provided visitor only implements the visit methods - for specific AST nodes. The other node types use the default behavior and you don't need to care about them. + for specific AST nodes. The other node types use the default behavior, and you don't need to care about them. +* Note: This is different from how it was in PMD 6: Each rule in PMD 6 was itself a visitor (implementing the visitor + interface of the specific language). Now the rule just provides a visitor, which can be hidden and potentially + shared between rules. ## 11. Create rules * Creating rules is already pretty well documented in PMD - and it’s no different for a new language, except you @@ -162,20 +189,38 @@ definitely don't come for free. It is much effort and requires perseverance to i * PMD supports 2 types of rules, through visitors or XPath. * To add a visitor rule: * You need to extend the abstract rule you created on the previous step, you can use the swift - rule [UnavailableFunctionRule](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/rule/bestpractices/UnavailableFunctionRule.java) + rule [UnavailableFunctionRule](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/rule/bestpractices/UnavailableFunctionRule.java) as an example. Note, that all rule classes should be suffixed with `Rule` and should be placed in a package the corresponds to their category. * To add an XPath rule you can follow our guide [Writing XPath Rules](pmd_userdocs_extending_writing_xpath_rules.html). +* When creating the category ruleset XML file, the XML can reference build properties that are replaced + during the build. This is used for the `externalInfoUrl` attribute of a rule. E.g. we use `${pmd.website.baseurl}` + to point to the correct webpage (depending on the PMD version). In order for this to work, you need to add a + resource filtering configuration in the language module's `pom.xml`. Under `` add the following lines: + ```xml + + + ${project.basedir}/src/main/resources + true + + + ``` ## 14. Test the rules * Testing rules is described in depth in [Testing your rules](pmd_userdocs_extending_testing.html). * Each rule has its own test class: Create a test class for your rule extending `PmdRuleTst` - *(see UnavailableFunctionTest for example)* - * Create a category rule set for your language *(see pmd-swift/src/main/resources/bestpractices.xml for example)* + *(see + [`UnavailableFunctionTest`](https://github.com/pmd/pmd/blob/master/pmd-swift/src/test/java/net/sourceforge/pmd/lang/swift/rule/bestpractices/UnavailableFunctionTest.java) + for example)* + * Create a category rule set for your language *(see + [`pmd-swift/src/main/resources/bestpractices.xml`](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/resources/category/swift/bestpractices.xml) + for example)* * Place the test XML file with the test cases in the correct location * When executing the test class * this triggers the unit test to read the corresponding XML file with the rule test data - *(see `UnavailableFunction.xml` for example)* + *(see + [`UnavailableFunction.xml`](https://github.com/pmd/pmd/blob/master/pmd-swift/src/test/resources/net/sourceforge/pmd/lang/swift/rule/bestpractices/xml/UnavailableFunction.xml) + for example)* * This test XML file contains sample pieces of code which should trigger a specified number of violations of this rule. The unit test will execute the rule on this piece of code, and verify that the number of violations matches. diff --git a/docs/pages/pmd/devdocs/major_contributions/adding_a_new_javacc_based_language.md b/docs/pages/pmd/devdocs/major_contributions/adding_a_new_javacc_based_language.md index 1e4e523b1c..0501ec73b8 100644 --- a/docs/pages/pmd/devdocs/major_contributions/adding_a_new_javacc_based_language.md +++ b/docs/pages/pmd/devdocs/major_contributions/adding_a_new_javacc_based_language.md @@ -16,15 +16,15 @@ folder: pmd/devdocs This is really a big contribution and can't be done with a drive by contribution. It requires dedicated passion and long commitment to implement support for a new language.

-This step-by-step guide is just a small intro to get the basics started and it's also not necessarily up-to-date -or complete and you have to be able to fill in the blanks.

+This step-by-step guide is just a small intro to get the basics started, and it's also not necessarily up-to-date +or complete. You have to be able to fill in the blanks.

After the basic support for a language is there, there are lots of missing features left. Typical features that can greatly improve rule writing are: symbol table, type resolution, call/data flow analysis.

Symbol table keeps track of variables and their usages. Type resolution tries to find the actual class type of each used type, following along method calls (including overloaded and overwritten methods), allowing -to query sub types and type hierarchy. This requires additional configuration of an auxiliary classpath. +to query subtypes and type hierarchy. This requires additional configuration of an auxiliary classpath. Call and data flow analysis keep track of the data as it is moving through different execution paths a program has.

@@ -35,7 +35,12 @@ definitely don't come for free. It is much effort and requires perseverance to i ## 1. Start with a new sub-module -* See pmd-java or pmd-vm for examples. +* See pmd-java or pmd-vm for examples. +* Make sure to add your new module to PMD's parent pom as `` entry, so that it is built alongside the + other languages. +* Also add your new module to the dependencies list in "pmd-languages-deps/pom.xml", so that the new language + is automatically available in the binary distribution (pmd-dist) as well as for the shell-completion + in the pmd-cli module. ## 2. Implement an AST parser for your language * Ideally an AST parser should be implemented as a JJT file *(see VmParser.jjt or Java.jjt for example)* diff --git a/docs/pages/pmd/devdocs/major_contributions/adding_new_cpd_language.md b/docs/pages/pmd/devdocs/major_contributions/adding_new_cpd_language.md index 4590867fa8..52ffb4bbec 100644 --- a/docs/pages/pmd/devdocs/major_contributions/adding_new_cpd_language.md +++ b/docs/pages/pmd/devdocs/major_contributions/adding_new_cpd_language.md @@ -17,10 +17,17 @@ Happily for you, to add CPD support for a new language is now easier than ever! All you need to do is follow this few steps: 1. Create a new module for your language, you can take [the Golang module](https://github.com/pmd/pmd/tree/master/pmd-go) as an example + * Make sure to add your new module to the parent pom as `` entry, so that it is built alongside the + other languages. + * Also add your new module to the dependencies list in "pmd-languages-deps/pom.xml", so that the new language + is automatically available in the binary distribution (pmd-dist) as well as for the shell-completion + in the pmd-cli module. + 2. Create a Tokenizer - - For Antlr grammars you can take the grammar from [here](https://github.com/antlr/grammars-v4) and extend [AntlrTokenizer](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/internal/AntlrTokenizer.java) taking Go as an example - + - For Antlr grammars you can take the grammar from [here](https://github.com/antlr/grammars-v4) and + extend [AntlrTokenizer](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/impl/AntlrTokenizer.java) + taking Go as an example ```java public class GoTokenizer extends AntlrTokenizer { @@ -32,7 +39,9 @@ All you need to do is follow this few steps: } ``` - - For JavaCC grammars you should subclass [JavaCCTokenizer](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/internal/JavaCCTokenizer.java) which has many examples you could follow, you should also take the [Python implementation](https://github.com/pmd/pmd/blob/master/pmd-python/src/main/java/net/sourceforge/pmd/cpd/PythonTokenizer.java) as reference + - For JavaCC grammars you should subclass [JavaCCTokenizer](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/impl/JavaCCTokenizer.java) + which has many examples you could follow, you should also take the + [Python implementation](https://github.com/pmd/pmd/blob/master/pmd-python/src/main/java/net/sourceforge/pmd/cpd/PythonTokenizer.java) as reference - For any other scenario you can use [AnyTokenizer](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/AnyTokenizer.java) If you're using Antlr or JavaCC, update the pom.xml of your submodule to use the appropriate ant wrapper. See `pmd-go/pom.xml` and `pmd-python/pom.xml` for examples. diff --git a/docs/pages/pmd/languages/coco.md b/docs/pages/pmd/languages/coco.md new file mode 100644 index 0000000000..44a6b31939 --- /dev/null +++ b/docs/pages/pmd/languages/coco.md @@ -0,0 +1,13 @@ +--- +title: Coco +permalink: pmd_languages_coco.html +--- + +Coco is a modern programming language designed specifically for building event-driven software. +It is part of the Coco Platform from . + +## Support in PMD +Starting from version 7.0.0, Coco support was added to CPD. + +### Limitations +- Support for Coco only extends to CPD to detect code duplication in Coco source files. diff --git a/docs/pages/pmd/languages/js_ts.md b/docs/pages/pmd/languages/js_ts.md new file mode 100644 index 0000000000..7633105a2d --- /dev/null +++ b/docs/pages/pmd/languages/js_ts.md @@ -0,0 +1,16 @@ +--- +title: JavaScript and TypeScript +permalink: pmd_languages_js_ts.html +tags: [languages] +summary: "JavaScript and TypeScript infos" +--- + +**JavaScript** support is using [Rhino](https://github.com/mozilla/rhino) for parsing and supports CPD as well as +PMD with rules. + +See [Compatibility Table](https://mozilla.github.io/rhino/compat/engines.html) for supported language features. + + +**TypeScript** is supported for Copy-Paste-Detection only and uses the ANTLR grammar from +[antlr/grammars-v4](https://github.com/antlr/grammars-v4/tree/master/javascript/typescript). +This grammar is published under the [MIT](https://opensource.org/licenses/MIT) license. diff --git a/docs/pages/pmd/languages/julia.md b/docs/pages/pmd/languages/julia.md new file mode 100644 index 0000000000..de36f3e9ea --- /dev/null +++ b/docs/pages/pmd/languages/julia.md @@ -0,0 +1,15 @@ +--- +title: Julia +permalink: pmd_languages_julia.html +--- + +The [Julia](https://julialang.org/) is dynamically typed, like a scripting language, +and has good support for interactive use. +Julia was designed from the beginning for high performance. +Julia programs compile to efficient native code for multiple platforms via LLVM. + +## Support in PMD +Starting from version 7.0.0, Julia support was added to CPD. + +### Limitations +- Support for Julia only extends to CPD to detect code duplication in Julia source files. diff --git a/docs/pages/pmd/projectdocs/committers/main_landing_page.md b/docs/pages/pmd/projectdocs/committers/main_landing_page.md index a0f2515068..8ad63c686f 100644 --- a/docs/pages/pmd/projectdocs/committers/main_landing_page.md +++ b/docs/pages/pmd/projectdocs/committers/main_landing_page.md @@ -27,12 +27,6 @@ It usually takes 15 minutes. * There is also a sub page "news" which lists all news. * Layout: [_layouts/news.html](https://github.com/pmd/pmd.github.io/blob/master/_layouts/news.html) * Page (which is pretty empty): [news.html](https://github.com/pmd/pmd.github.io/blob/master/news.html) -* Documentation for the latest release: - * The PMD documentation of the latest release is simply copied as static html into the folder [latest/](https://github.com/pmd/pmd.github.io/tree/master/latest). - This makes the latest release documentation available under the stable URL - . This URL is also used for the [sitemap.xml](https://github.com/pmd/pmd.github.io/blob/master/sitemap.xml). -* Documentation for previous releases are still being kept under the folders `pmd-/`. - ## Building the page locally diff --git a/docs/pages/pmd/projectdocs/committers/releasing.md b/docs/pages/pmd/projectdocs/committers/releasing.md index d41605db65..92ddf8035c 100644 --- a/docs/pages/pmd/projectdocs/committers/releasing.md +++ b/docs/pages/pmd/projectdocs/committers/releasing.md @@ -45,7 +45,7 @@ e.g. it requires that the repo `pmd.github.io` is checked out aside the main pmd The script `do-release.sh` is called in the directory `/home/joe/source/pmd` and searches for `../pmd.github.io`. -Also make sure, that the repo "pmd.github.io" is locally up to date and has no local changes. +Also make sure, that the repo "pmd.github.io" is locally up-to-date and has no local changes. ### The Release Notes and docs @@ -183,11 +183,8 @@ Here is, what happens: * Remove old javadoc for the SNAPSHOT version, e.g. delete . * Create a draft news post on for the new release. This contains the rendered release notes. -* Add the documentation of the new release to a subfolder on , also make - this folder available as `latest`, so that shows the new - version and is the URL for the specific release. -* Also copy the documentation to sourceforge's web space, so that it is available as - . All previously copied version are listed +* Copy the documentation to sourceforge's web space, so that it is available as + . All previously copied versions are listed under . * After all this is done, the release on github () is published and the news post on sourceforge (https://sourceforge.net/p/pmd/news/> is publishes as well. @@ -206,7 +203,7 @@ news: * Downloads: https://github.com/pmd/pmd/releases/tag/pmd_releases%2F - * Documentation: https://pmd.github.io/pmd-/ + * Documentation: https://docs.pmd-code.org/pmd-doc-/ And Copy-Paste the release notes @@ -219,20 +216,21 @@ Tweet on , eg.: ### Checklist -| Task | Description | URL | ☐ / ✔ | -|------|-------------|-----|-------| -| maven central | The new version of all artifacts are available in maven central | | | -| github releases | A new release with 3 assets (bin, src, doc) is created | | | -| sourceforge files | The 3 assets (bin, src, doc) are uploaded, the new version is pre-selected as latest | | | -| homepage | Main landing page points to new version, doc for new version is available | | | -| homepage2 | New blogpost for the new release is posted | | | -| docs | New docs are uploaded | | | -| docs-archive | New docs are also on archive site | | | -| javadoc | New javadocs are uploaded | | | -| news | New blogpost on sourceforge is posted | | | -| regression-tester | New release baseline is uploaded | | | -| mailing list | announcement on mailing list is sent | | | -| twitter | tweet about the new release | | | +| Task | Description | URL | ☐ / ✔ | +|-------------------|--------------------------------------------------------------------------------------|-----------------------------------------------------------------|-------------------------| +| maven central | The new version of all artifacts are available in maven central | | | +| github releases | A new release with 3 assets (bin, src, doc) is created | | | +| sourceforge files | The 3 assets (bin, src, doc) are uploaded, the new version is pre-selected as latest | | | +| homepage | Main landing page points to new version, doc for new version is available | | | +| homepage2 | New blogpost for the new release is posted | | | +| docs | New docs are uploaded | | | +| docs2 | New version in the docs is listed under "Version specific documentation" | | | +| docs-archive | New docs are also on archive site | | | +| javadoc | New javadocs are uploaded | | | +| news | New blogpost on sourceforge is posted | | | +| regression-tester | New release baseline is uploaded | | | +| mailing list | announcement on mailing list is sent | | | +| twitter | tweet about the new release | | | ## Prepare the next release @@ -309,7 +307,7 @@ In theory, the fixes should already be there, but you never now. If releases from multiple branches are being done, the order matters. You should start from the "oldest" branch, e.g. `pmd/5.4.x`, release from there. Then merge (see above) into the next branch, e.g. `pmd/5.5.x` and release from there. Then merge into the `master` branch and release from there. This way, the last release done, becomes -automatically the latest release on and on sourceforge. +automatically the latest release on and on sourceforge. ### (Optional) Create a new release branch diff --git a/docs/pages/pmd/projectdocs/credits.md b/docs/pages/pmd/projectdocs/credits.md index 7c364b7d02..95a5fff653 100644 --- a/docs/pages/pmd/projectdocs/credits.md +++ b/docs/pages/pmd/projectdocs/credits.md @@ -379,640 +379,643 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
Josh Feingold

💻 🐛
Josh Holthaus

🐛
Joshua S Arquilevich

🐛 +
João Dinis Ferreira

📖
João Ferreira

💻 🐛 -
João Pedro Schmitt

🐛 +
João Pedro Schmitt

🐛
Juan Martín Sotuyo Dodero

💻 📖 🐛 🚧
Juan Pablo Civile

🐛
Julian Voronetsky

🐛
Julien

🐛
Julius

🐛
JustPRV

🐛 -
Jörn Huxhorn

🐛 +
Jörn Huxhorn

🐛
KThompso

🐛
Kai Amundsen

🐛
Karel Vervaeke

🐛
Karl-Andero Mere

🐛
Karl-Philipp Richter

🐛
Karsten Silz

🐛 -
Kazuma Watanabe

🐛 +
Kazuma Watanabe

🐛
Kev

🐛
Keve Müller

🐛
Kevin Guerra

💻
Kevin Jones

🐛
Kevin Wayne

🐛
Kieran Black

🐛 -
Kirill Zubov

🐛 +
Kirill Zubov

🐛
Kirk Clemens

💻 🐛
Klaus Hartl

🐛
Koen Van Looveren

🐛
Kris Scheibe

💻 🐛
Kunal Thanki

🐛
LaLucid

💻 -
Larry Diamond

💻 🐛 +
Larry Diamond

💻 🐛
Lars Knickrehm

🐛
Leo Gutierrez

🐛
LiGaOg

💻
Liam Sharp

🐛
Lintsi

🐛
Linus Fernandes

🐛 -
Lixon Lookose

🐛 +
Lixon Lookose

🐛
Logesh

🐛
Lorenzo Gabriele

🐛
Loïc Ledoyen

🐛
Lucas Silva

🐛
Lucas Soncini

💻 🐛
Luis Alcantar

💻 -
Lukasz Slonina

🐛 +
Lukasz Slonina

🐛
Lukebray

🐛
Lynn

💻 🐛
Lyor Goldstein

🐛
MCMicS

🐛
Macarse

🐛
Machine account for PMD

💻 -
Maciek Siemczyk

🐛 +
Maciek Siemczyk

🐛
Maikel Steneker

💻 🐛
Maksim Moiseikin

🐛
Manfred Koch

🐛
Manuel Moya Ferrer

💻 🐛
Manuel Ryan

🐛
Marat Vyshegorodtsev

🐛 -
Marcel Härle

🐛 +
Marcel Härle

🐛
Marcello Fialho

🐛
Marcin Rataj

🐛
Mark Adamcin

🐛
Mark Hall

💻 🐛
Mark Kolich

🐛
Mark Pritchard

🐛 -
Markus Rathgeb

🐛 +
Markus Rathgeb

🐛
Marquis Wang

🐛
MartGit

🐛
Martin Feldsztejn

🐛
Martin Lehmann

🐛
Martin Spamer

🐛
Martin Tarjányi

🐛 -
MatFl

🐛 +
MatFl

🐛
Mateusz Stefanski

🐛
Mathieu Gouin

🐛
MatiasComercio

💻 🐛
Matt Benson

🐛
Matt De Poorter

🐛
Matt Hargett

💻 💵 -
Matt Harrah

🐛 +
Matt Harrah

🐛
Matt Nelson

🐛
Matthew Amos

🐛
Matthew Duggan

🐛
Matthew Hall

🐛
Matías Fraga

💻 🐛
Maxime Robert

💻 🐛 -
MetaBF

🐛 +
MetaBF

🐛
Michael

🐛
Michael Bell

🐛
Michael Bernstein

🐛
Michael Clay

🐛
Michael Dombrowski

🐛
Michael Hausegger

🐛 -
Michael Hoefer

🐛 +
Michael Hoefer

🐛
Michael Möbius

🐛
Michael N. Lipp

🐛
Michael Pellegrini

🐛
Michal Kordas

🐛
Michał Borek

🐛
Michał Kuliński

🐛 -
Miguel Núñez Díaz-Montes

🐛 +
Miguel Núñez Díaz-Montes

🐛
Mihai Ionut

🐛
Mirek Hankus

🐛
Mladjan Gadzic

🐛
MrAngry52

🐛
Muminur Choudhury

🐛
Mykhailo Palahuta

💻 🐛 -
Nagendra Kumar Singh

🐛 +
Nagendra Kumar Singh

🐛
Nahuel Barrios

🐛
Nathan Braun

🐛
Nathan Reynolds

🐛
Nathan Reynolds

🐛
Nathanaël

🐛
Naveen

💻 -
Nazdravi

🐛 +
Nazdravi

🐛
Neha-Dhonde

🐛
Nicholas Doyle

🐛
Nick Butcher

🐛
Nico Gallinal

🐛
Nicola Dal Maso

🐛
Nicolas Filotto

💻 -
Nicolas Vervelle

🐛 +
Nicolas Vervelle

🐛
Nicolas Vuillamy

📖
Nikita Chursin

🐛
Niklas Baudy

🐛
Nikolas Havrikov

🐛
Nilesh Virkar

🐛
Nimit Patel

🐛 -
Niranjan Harpale

🐛 +
Niranjan Harpale

🐛
Nirvik Patel

💻
Noah Sussman

🐛
Noah0120

🐛
Noam Tamim

🐛
Noel Grandin

🐛
Olaf Haalstra

🐛 -
Oleg Andreych

💻 🐛 +
Oleg Andreych

💻 🐛
Oleg Pavlenko

🐛
Oleksii Dykov

💻 🐛
Oliver Eikemeier

🐛
Oliver Siegmar

💵
Olivier Parent

💻 🐛
Ollie Abbey

💻 🐛 -
OverDrone

🐛 +
OverDrone

🐛
Ozan Gulle

💻 🐛
PUNEET JAIN

🐛
Parbati Bose

🐛
Paul Berg

🐛
Paul Guyot

💻
Pavel Bludov

🐛 -
Pavel Mička

🐛 +
Pavel Mička

🐛
Pedro Nuno Santos

🐛
Pedro Rijo

🐛
Pelisse Romain

💻 📖 🐛
Per Abich

💻
Pete Davids

🐛
Peter Bruin

🐛 -
Peter Chittum

💻 🐛 +
Peter Chittum

💻 🐛
Peter Cudmore

🐛
Peter Kasson

🐛
Peter Kofler

🐛
Peter Paul Bakker

💻
Pham Hai Trung

🐛
Philip Graf

💻 🐛 -
Philip Hachey

🐛 +
Philip Hachey

🐛
Philippe Ozil

🐛
Phinehas Artemix

🐛
Phokham Nonava

🐛 +
Pim van der Loos

💻 ⚠️
Piotr Szymański

🐛
Piotrek Żygieło

💻 🐛 📖 -
Pranay Jaiswal

🐛 -
Prasad Kamath

🐛 +
Pranay Jaiswal

🐛 +
Prasad Kamath

🐛
Prasanna

🐛
Presh-AR

🐛
Puneet1726

🐛
Rafael Cortês

🐛
RaheemShaik999

🐛 -
RajeshR

💻 🐛 -
Ramachandra Mohan

🐛 +
RajeshR

💻 🐛 +
Ramachandra Mohan

🐛
Ramel0921

🐛
Raquel Pau

🐛
Ravikiran Janardhana

🐛
Reda Benhemmouche

🐛
Renato Oliveira

💻 🐛 -
Rich DiCroce

🐛 -
Riot R1cket

🐛 +
Rich DiCroce

🐛 +
Riot R1cket

🐛
Rishabh Jain

🐛
RishabhDeep Singh

🐛
Robbie Martinus

💻 🐛
Robert Henry

🐛
Robert Mihaly

🐛 -
Robert Painsi

🐛 -
Robert Russell

🐛 +
Robert Painsi

🐛 +
Robert Russell

🐛
Robert Sösemann

💻 📖 📢 🐛
Robert Whitebit

🐛
Robin Richtsfeld

🐛
Robin Stocker

💻 🐛
Robin Wils

🐛 -
RochusOest

🐛 -
Rodolfo Noviski

🐛 +
RochusOest

🐛 +
Rodolfo Noviski

🐛
Rodrigo Casara

🐛
Rodrigo Fernandes

🐛
Roman Salvador

💻 🐛
Ronald Blaschke

🐛
Róbert Papp

🐛 -
Saikat Sengupta

🐛 -
Saksham Handu

🐛 +
Saikat Sengupta

🐛 +
Saksham Handu

🐛
Saladoc

🐛
Salesforce Bob Lightning

🐛
Sam Carlberg

🐛
Satoshi Kubo

🐛
Scott Kennedy

🐛 -
Scott Wells

🐛 💻 -
Scrsloota

💻 +
Scott Wells

🐛 💻 +
Scrsloota

💻
Sebastian Bögl

🐛
Sebastian Schuberth

🐛
Sebastian Schwarz

🐛
Seren

🐛 💻
Sergey Gorbaty

🐛 -
Sergey Kozlov

🐛 -
Sergey Yanzin

💻 🐛 +
Sergey Kozlov

🐛 +
Sergey Yanzin

💻 🐛
Seth Wilcox

💻
Shubham

💻 🐛
Simon Abykov

💻 🐛
Simon Xiao

🐛
Srinivasan Venkatachalam

🐛 -
Stanislav Gromov

🐛 -
Stanislav Myachenkov

💻 +
Stanislav Gromov

🐛 +
Stanislav Myachenkov

💻
Stefan Birkner

🐛
Stefan Bohn

🐛
Stefan Endrullis

🐛
Stefan Klöss-Schuster

🐛
Stefan Wolf

🐛 -
Stephan H. Wissel

🐛 -
Stephen

🐛 +
Stephan H. Wissel

🐛 +
Stephen

🐛
Stephen Friedrich

🐛
Steve Babula

💻
Steven Stearns

🐛 💻
Stexxe

🐛
Stian Lågstad

🐛 -
StuartClayton5

🐛 -
Supun Arunoda

🐛 +
StuartClayton5

🐛 +
Supun Arunoda

🐛
Suren Abrahamyan

🐛
Suvashri

📖
SwatiBGupta1110

🐛
SyedThoufich

🐛
Szymon Sasin

🐛 -
T-chuangxin

🐛 -
TERAI Atsuhiro

🐛 +
T-chuangxin

🐛 +
TERAI Atsuhiro

🐛
TIOBE Software

💻 🐛
Tarush Singh

💻
Taylor Smock

🐛
Techeira Damián

💻 🐛
Ted Husted

🐛 -
TehBakker

🐛 -
The Gitter Badger

🐛 +
TehBakker

🐛 +
The Gitter Badger

🐛
Theodoor

🐛
Thiago Henrique Hüpner

🐛
Thibault Meyer

🐛
Thomas Güttler

🐛
Thomas Jones-Low

🐛 -
Thomas Smith

💻 🐛 -
ThrawnCA

🐛 +
Thomas Smith

💻 🐛 +
ThrawnCA

🐛
Thunderforge

💻 🐛
Tim van der Lippe

🐛
Tobias Weimer

💻 🐛
Tom Copeland

🐛 💻 📖
Tom Daly

🐛 -
Tomer Figenblat

🐛 -
Tomi De Lucca

💻 🐛 +
Tomer Figenblat

🐛 +
Tomi De Lucca

💻 🐛
Torsten Kleiber

🐛
TrackerSB

🐛
Tyson Stewart

🐛
Ullrich Hafner

🐛
Utku Cuhadaroglu

💻 🐛 -
Valentin Brandl

🐛 -
Valeria

🐛 +
Valentin Brandl

🐛 +
Valeria

🐛
Valery Yatsynovich

📖
Vasily Anisimov

🐛
Vibhor Goyal

🐛
Vickenty Fesunov

🐛
Victor Noël

🐛 -
Vincent Galloy

💻 -
Vincent HUYNH

🐛 +
Vincent Galloy

💻 +
Vincent HUYNH

🐛
Vincent Maurin

🐛
Vincent Privat

🐛
Vishhwas

🐛
Vitaly

🐛
Vitaly Polonetsky

🐛 -
Vojtech Polivka

🐛 -
Vsevolod Zholobov

🐛 +
Vojtech Polivka

🐛 +
Vsevolod Zholobov

🐛
Vyom Yadav

💻
Wang Shidong

🐛
Waqas Ahmed

🐛
Wayne J. Earl

🐛
Wchenghui

🐛 -
Will Winder

🐛 -
William Brockhus

💻 🐛 +
Will Winder

🐛 +
William Brockhus

💻 🐛
Wilson Kurniawan

🐛
Wim Deblauwe

🐛
Woongsik Choi

🐛
XenoAmess

💻 🐛
Yang

💻 -
YaroslavTER

🐛 -
Yasar Shaikh

💻 +
YaroslavTER

🐛 +
Yasar Shaikh

💻
Young Chan

💻 🐛
YuJin Kim

🐛
Yuri Dolzhenko

🐛
Yurii Dubinka

🐛
Zoltan Farkas

🐛 -
Zustin

🐛 -
aaronhurst-google

🐛 💻 +
Zustin

🐛 +
aaronhurst-google

🐛 💻
alexmodis

🐛
andreoss

🐛
andrey81inmd

💻 🐛
anicoara

🐛
arunprasathav

🐛 -
asiercamara

🐛 -
astillich-igniti

💻 +
asiercamara

🐛 +
astillich-igniti

💻
avesolovksyy

🐛
avishvat

🐛
avivmu

🐛
axelbarfod1

🐛
b-3-n

🐛 -
balbhadra9

🐛 -
base23de

🐛 +
balbhadra9

🐛 +
base23de

🐛
bergander

🐛
berkam

💻 🐛
breizh31

🐛
caesarkim

🐛
carolyujing

🐛 -
cbfiddle

🐛 -
cesares-basilico

🐛 +
cbfiddle

🐛 +
cesares-basilico

🐛
chrite

🐛
cobratbq

🐛
coladict

🐛
cosmoJFH

🐛
cristalp

🐛 -
crunsk

🐛 -
cwholmes

🐛 +
crunsk

🐛 +
cwholmes

🐛
cyberjj999

🐛
cyw3

🐛
d1ss0nanz

🐛
dague1

📖
dalizi007

💻 -
danbrycefairsailcom

🐛 -
dariansanity

🐛 +
danbrycefairsailcom

🐛 +
dariansanity

🐛
darrenmiliband

🐛
davidburstrom

🐛
dbirkman-paloalto

🐛
deepak-patra

🐛
dependabot[bot]

💻 🐛 -
dinesh150

🐛 -
diziaq

🐛 +
dinesh150

🐛 +
diziaq

🐛
dreaminpast123

🐛
duanyanan

🐛
dutt-sanjay

🐛
dylanleung

🐛
dzeigler

🐛 -
ekkirala

🐛 -
emersonmoura

🐛 +
ekkirala

🐛 +
emersonmoura

🐛
fairy

🐛
filiprafalowicz

💻
foxmason

🐛
frankegabor

🐛
frankl

🐛 -
freafrea

🐛 -
fsapatin

🐛 +
freafrea

🐛 +
fsapatin

🐛
gracia19

🐛
guo fei

🐛
gurmsc5

🐛
gwilymatgearset

💻 🐛
haigsn

🐛 -
hemanshu070

🐛 -
henrik242

🐛 +
hemanshu070

🐛 +
henrik242

🐛
hongpuwu

🐛
hvbtup

💻 🐛
igniti GmbH

🐛
ilovezfs

🐛
itaigilo

🐛 -
jakivey32

🐛 -
jbennett2091

🐛 +
jakivey32

🐛 +
jbennett2091

🐛
jcamerin

🐛
jkeener1

🐛
jmetertea

🐛
johnra2

💻
josemanuelrolon

💻 🐛 -
kabroxiko

💻 🐛 -
karwer

🐛 +
kabroxiko

💻 🐛 +
karwer

🐛
kaulonline

🐛
kdaemonv

🐛
kdebski85

🐛 💻
kenji21

💻 🐛
kfranic

🐛 -
khalidkh

🐛 -
koalalam

🐛 +
khalidkh

🐛 +
koalalam

🐛
krzyk

🐛
lasselindqvist

🐛
lgemeinhardt

🐛
lihuaib

🐛
lonelyma1021

🐛 -
lpeddy

🐛 -
lujiefsi

💻 +
lpeddy

🐛 +
lujiefsi

💻
lukelukes

💻
lyriccoder

🐛
marcelmore

🐛
matchbox

🐛
matthiaskraaz

🐛 -
meandonlyme

🐛 -
mikesive

🐛 +
meandonlyme

🐛 +
mikesive

🐛
milossesic

🐛
mluckam

💻
mohan-chinnappan-n

💻
mriddell95

🐛
mrlzh

🐛 -
msloan

🐛 -
mucharlaravalika

🐛 +
msloan

🐛 +
mucharlaravalika

🐛
mvenneman

🐛
nareshl119

🐛
nicolas-harraudeau-sonarsource

🐛
noerremark

🐛
novsirion

🐛 -
oggboy

🐛 -
oinume

🐛 +
nwcm

📖 +
oggboy

🐛 +
oinume

🐛
orimarko

💻 🐛
pacvz

💻
pallavi agarwal

🐛
parksungrin

🐛 + +
patpatpat123

🐛
patriksevallius

🐛
pbrajesh1

🐛 - -
phoenix384

🐛
piotrszymanski-sc

💻
plan3d

🐛
poojasix

🐛 + +
prabhushrikant

🐛
pujitha8783

🐛
r-r-a-j

🐛 - -
raghujayjunk

🐛
rajeshveera

🐛
rajeswarreddy88

🐛
recdevs

🐛 + +
reudismam

💻 🐛
rijkt

🐛
rillig-tk

🐛 - -
rmohan20

💻 🐛
rnveach

🐛
rxmicro

🐛
ryan-gustafson

💻 🐛 + +
sabi0

🐛
scais

🐛
sebbASF

🐛 - -
sergeygorbaty

💻
shilko2013

🐛
shiomiyan

📖
simeonKondr

🐛 + +
snajberk

🐛
sniperrifle2004

🐛
snuyanzin

🐛 💻 - -
sratz

🐛
stonio

🐛
sturton

💻 🐛
sudharmohan

🐛 + +
suruchidawar

🐛
svenfinitiv

🐛
tashiscool

🐛 - -
test-git-hook

🐛
testation21

💻 🐛
thanosa

🐛
tiandiyixian

🐛 + +
tobwoerk

🐛
tprouvot

🐛 💻
trentchilders

🐛 - -
triandicAnt

🐛
trishul14

🐛
tsui

🐛
winhkey

🐛 + +
witherspore

🐛
wjljack

🐛
wuchiuwong

🐛 - -
xingsong

🐛
xioayuge

🐛
xnYi9wRezm

💻 🐛
xuanuy

🐛 + +
xyf0921

🐛
yalechen-cyw3

🐛
yasuharu-sato

🐛 - -
zenglian

🐛
zgrzyt93

💻 🐛
zh3ng

🐛
zt_soft

🐛 + +
ztt79

🐛
zzzzfeng

🐛
Árpád Magosányi

🐛 - -
任贵杰

🐛
茅延安

💻 diff --git a/docs/pages/pmd/projectdocs/logo.md b/docs/pages/pmd/projectdocs/logo.md index 17a94f01e9..3838039f8e 100644 --- a/docs/pages/pmd/projectdocs/logo.md +++ b/docs/pages/pmd/projectdocs/logo.md @@ -10,11 +10,26 @@ folder: pmd/projectdocs The following PMD Logos and Icons are licensed under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/): -* [PMD.svg](images/logo/PMD.svg) +* [PMD.svg](images/logo/PMD.svg) - main logo source file. All other sizes/images are derived from that. * [PMD.png](images/logo/PMD.png) +* [Logo (70px, transparent)](images/logo/pmd-logo-70px.png) +* [Logo (70px, transparent, square shape)](images/logo/pmd-logo-70px-squared.png) * [Logo (300px, transparent)](images/logo/pmd-logo-300px.png) +* [Logo (300px, transparent, square shape)](images/logo/pmd-logo-300px-squared.png) * [Logo (300px, white)](images/logo/pmd-logo-white-300px.png) +* [Logo (300px, white, square shape)](images/logo/pmd-logo-white-300px-squared.png) +* [Logo (400x165px, white)](images/logo/pmd-logo-white-400x165px.png) * [Logo (600px, transparent)](images/logo/pmd-logo-600px.png) +* [Logo (600px, transparent, square shape)](images/logo/pmd-logo-600px-squared.png) * [Logo (600px, white)](images/logo/pmd-logo-white-600px.png) +* [Logo (600px, white, suqare shape)](images/logo/pmd-logo-white-600px-squared.png) * [Favicon (16x16)](images/logo/favicon.ico) + +This new greenish logo was introduced with PMD 7. + +Before that, PMD used the following logo with the tagline "Don't shoot the messenger". +These old logos are provided here only as reference for historical reasons and shouldn't be used anymore. + +* [Old logo - pmd-old.svg](images/logo/pmd-old.svg) +* [Old logo (600x440px, white)](images/logo/pmd-old-logo-white-600x440px.png) diff --git a/docs/pages/pmd/userdocs/cpd/cpd.md b/docs/pages/pmd/userdocs/cpd/cpd.md index a8719c55b9..82ca9e7831 100644 --- a/docs/pages/pmd/userdocs/cpd/cpd.md +++ b/docs/pages/pmd/userdocs/cpd/cpd.md @@ -261,36 +261,40 @@ to be "debug". * C# * C/C++ +* [Coco](pmd_languages_coco.html) * Dart * EcmaScript (JavaScript) * Fortran -* Gherkin (Cucumber) +* [Gherkin](pmd_languages_gherkin.html) (Cucumber) * Go * Groovy -* Html -* Java -* Jsp -* Kotlin +* [Html](pmd_languages_html.html) +* [Java](pmd_languages_java.html) +* [Jsp](pmd_languages_jsp.html) +* [Julia](pmd_languages_julia.html) +* [Kotlin](pmd_languages_kotlin.html) * Lua * Matlab * Modelica * Objective-C * Perl * PHP -* PL/SQL +* [PL/SQL](pmd_languages_plsql.html) * Python * Ruby -* Salesforce.com Apex +* [Salesforce.com Apex](pmd_languages_apex.html) * Scala * Swift -* Visualforce -* XML +* T-SQL +* [TypeScript](pmd_languages_js_ts.html) +* [Visualforce](pmd_languages_visualforce.html) +* [XML](pmd_languages_xml.html) ## Available report formats * text : Default format -* xml +* xml (and xslt) * csv * csv_with_linecount_per_file * vs @@ -404,6 +408,8 @@ the CPD task as usual and right after it invoke the Ant XSLT script like this: ``` +See [section "xslt" in CPD Report Formats](pmd_userdocs_cpd_report_formats.html#xslt) for more examples. + ## GUI CPD also comes with a simple GUI. You can start it through the unified CLI interface provided in the `bin` folder: @@ -457,7 +463,7 @@ public Object someParameterizedFactoryMethod(int x) throws Exception { // any code here will be ignored for the duplication detection } //disable suppression -@SuppressWarnings("CPD-END) +@SuppressWarnings("CPD-END") public void nextMethod() { } ``` diff --git a/docs/pages/pmd/userdocs/cpd/cpd_report_formats.md b/docs/pages/pmd/userdocs/cpd/cpd_report_formats.md index f21bd5b448..7ba812383b 100644 --- a/docs/pages/pmd/userdocs/cpd/cpd_report_formats.md +++ b/docs/pages/pmd/userdocs/cpd/cpd_report_formats.md @@ -95,6 +95,7 @@ Starting at line 110 of /home/pmd/source/pmd-core/src/test/java/net/sourceforge/ ## xml This format uses XML to output the duplications in a more structured format. +The XML format can then further be processed using XSLT transformations. See [section xslt](#xslt) for examples. Example: @@ -220,3 +221,41 @@ Example: /home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/JaxenXPathRuleQueryTest.java(88): Between lines 88 and 104 /home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/JaxenXPathRuleQueryTest.java(110): Between lines 110 and 126 ``` + +## xslt + +This is not a direct report format. But you can use `xml` to generate an XML report and then use one of the following +XSLT stylesheets to convert the report into html. Or you can write your own stylesheet. + +You can either use [Ant's XSLT task](https://ant.apache.org/manual/Tasks/style.html) or use any other (CLI) xslt processor, +e.g. `xalan` (see ). + +### cpdhtml.xslt + +This stylesheet is available in the sources or from GitHub at: . + +```shell +xalan -in cpd-report-sample.xml -xsl cpdhtml.xslt -out cpd-report-sample-cpdhtml.html +``` + +[Example](report-examples/cpdhtml.html) + +This stylesheet by default only consideres duplications longer than 30 lines. You can change the default value with +the param `lines`: + +```shell +xalan -in cpd-report-sample.xml -xsl cpdhtml.xslt -out cpd-report-sample-cpdhtml.html -param lines 10 +``` + +### cpdhtml-v2.xslt + +This stylesheet is available in the sources or from GitHub at: . + +```shell +xalan -in pmd-core-cpd-report.xml -xsl etc/xslt/cpdhtml-v2.xslt -out pmd-core-cpd-report-v2.html +``` + +[Example](report-examples/cpdhtml-v2.html) + +It requires javascript enabled and uses [Bootstrap](https://getbootstrap.com/), +[jQuery](https://jquery.com/), and [DataTables](https://datatables.net/). diff --git a/docs/pages/pmd/userdocs/suppressing_warnings.md b/docs/pages/pmd/userdocs/suppressing_warnings.md index 68bf5e4379..da433e6469 100644 --- a/docs/pages/pmd/userdocs/suppressing_warnings.md +++ b/docs/pages/pmd/userdocs/suppressing_warnings.md @@ -192,8 +192,7 @@ then the violation will be suppressed. Note that the query shouldn't be finding the violation nodes to suppress, but rather, finding a non-empty sequence of nodes when evaluated with the violation node as a context node. -The XPath version used by those queries is XPath 1.0, so it doesn't support various XPath 2.0 -features. This will be updated with PMD 7.0.0. +The XPath version used by those queries is XPath 3.1 since PMD 7. Before then XPath 1.0 was used. For example, to suppress reporting specifically "String" parameters which are unused: diff --git a/docs/pages/pmd/userdocs/tools/java-api.md b/docs/pages/pmd/userdocs/tools/java-api.md index 36ebb017ea..5347e7b56a 100644 --- a/docs/pages/pmd/userdocs/tools/java-api.md +++ b/docs/pages/pmd/userdocs/tools/java-api.md @@ -30,186 +30,6 @@ Note: You'll need to select a specific version. This is done in the example via This will transitively pull in the artifact `pmd-core` which contains the API. -## Command line interface - -The easiest way is to call PMD with the same interface as from command line. The main class is -`net.sourceforge.pmd.PMD`: - -``` java -import net.sourceforge.pmd.PMD; - -public class Example { - public static void main(String[] args) { - String[] pmdArgs = { - "-d", "/home/workspace/src/main/java/code", - "-R", "rulesets/java/quickstart.xml", - "-f", "xml", - "-r", "/home/workspace/pmd-report.xml" - }; - PMD.main(pmdArgs); - } -} -``` - -It uses the same options as described in [PMD CLI reference](pmd_userdocs_cli_reference.html). - -## Programmatically, variant 1 - -This is very similar: - -``` java -import net.sourceforge.pmd.PMD; -import net.sourceforge.pmd.PMDConfiguration; - -public class PmdExample { - - public static void main(String[] args) { - PMDConfiguration configuration = new PMDConfiguration(); - configuration.setInputPaths("/home/workspace/src/main/java/code"); - configuration.addRuleSet("rulesets/java/quickstart.xml"); - configuration.setReportFormat("xml"); - configuration.setReportFile("/home/workspace/pmd-report.xml"); - - PMD.runPmd(configuration); - } -} -``` - -## Programmatically, variant 2 - -This gives you more control over which files are processed, but is also more complicated. -You can also provide your own custom renderers. - -1. First we create a `PMDConfiguration` and configure it, first the rules: - - ```java - PMDConfiguration configuration = new PMDConfiguration(); - configuration.setMinimumPriority(RulePriority.MEDIUM); - configuration.addRuleSet("rulesets/java/quickstart.xml"); - ``` - -2. Then we configure, which paths to analyze: - - ```java - configuration.setInputPaths("/home/workspace/src/main/java/code"); - ``` - -3. The we configure the default language version for Java. And in order to support type resolution, - PMD needs to have access to the compiled classes and dependencies as well. This is called - "auxclasspath" and is also configured here. - - Note: you can specify multiple class paths separated by `:` on Unix-systems or `;` under Windows. - - ```java - configuration.setDefaultLanguageVersion(LanguageRegistry.findLanguageByTerseName("java").getVersion("11")); - configuration.prependAuxClasspath("/home/workspace/target/classes:/home/.m2/repository/my/dependency.jar"); - ``` - -4. Then we configure the reporting. Configuring the report file is optional. If not specified, the report - will be written to `stdout`. - - ```java - configuration.setReportFormat("xml"); - configuration.setReportFile("/home/workspace/pmd-report.xml"); - ``` - -5. Now an optional step: If you want to use additional renderers as in the example, set them up before - calling PMD. You can use a built-in renderer, e.g. `XMLRenderer` or a custom renderer implementing - `Renderer`. Note, that you must manually initialize the renderer by setting a suitable `Writer`: - - ```java - Writer rendererOutput = new StringWriter(); - Renderer renderer = createRenderer(rendererOutput); - - // ... - private static Renderer createRenderer(Writer writer) { - XMLRenderer xml = new XMLRenderer("UTF-8"); - xml.setWriter(writer); - return xml; - } - ``` - -6. Finally we can start the PMD analysis. There is the possibility to fine-tune the configuration - by adding additional files to analyze or adding additional rulesets or renderers: - - ```java - try (PmdAnalysis pmd = PmdAnalysis.create(configuration)) { - // optional: add more rulesets - pmd.addRuleSet(pmd.newRuleSetLoader().loadFromResource("custom-ruleset.xml")); - // optional: add more files - pmd.files().addFile(Paths.get("src", "main", "more-java", "ExtraSource.java")); - // optional: add more renderers - pmd.addRenderer(renderer); - - // or just call PMD - pmd.performAnalysis(); - } - ``` - - The renderer will be automatically flushed and closed at the end of the analysis. - -7. Then you can check the rendered output. - - ``` java - System.out.println("Rendered Report:"); - System.out.println(rendererOutput.toString()); - ``` - -Here is a complete example: - -``` java -import java.io.IOException; -import java.io.StringWriter; -import java.io.Writer; -import java.nio.file.Paths; - -import net.sourceforge.pmd.PMDConfiguration; -import net.sourceforge.pmd.PmdAnalysis; -import net.sourceforge.pmd.RulePriority; -import net.sourceforge.pmd.lang.LanguageRegistry; -import net.sourceforge.pmd.renderers.Renderer; -import net.sourceforge.pmd.renderers.XMLRenderer; - -public class PmdExample2 { - - public static void main(String[] args) throws IOException { - PMDConfiguration configuration = new PMDConfiguration(); - configuration.setMinimumPriority(RulePriority.MEDIUM); - configuration.addRuleSet("rulesets/java/quickstart.xml"); - - configuration.setInputPaths("/home/workspace/src/main/java/code"); - - configuration.setDefaultLanguageVersion(LanguageRegistry.findLanguageByTerseName("java").getVersion("11")); - configuration.prependAuxClasspath("/home/workspace/target/classes"); - - configuration.setReportFormat("xml"); - configuration.setReportFile("/home/workspace/pmd-report.xml"); - - Writer rendererOutput = new StringWriter(); - Renderer renderer = createRenderer(rendererOutput); - - try (PmdAnalysis pmd = PmdAnalysis.create(configuration)) { - // optional: add more rulesets - pmd.addRuleSet(pmd.newRuleSetLoader().loadFromResource("custom-ruleset.xml")); - // optional: add more files - pmd.files().addFile(Paths.get("src", "main", "more-java", "ExtraSource.java")); - // optional: add more renderers - pmd.addRenderer(renderer); - - // or just call PMD - pmd.performAnalysis(); - } - - System.out.println("Rendered Report:"); - System.out.println(rendererOutput.toString()); - } - - private static Renderer createRenderer(Writer writer) { - XMLRenderer xml = new XMLRenderer("UTF-8"); - xml.setWriter(writer); - return xml; - } -} -``` - +## Running PMD programmatically +The programmatic API for PMD is centered around {% jdoc core::PmdAnalysis %}, please see the javadocs for usage information. diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index b875222f4d..1a77626a20 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -5,7 +5,7 @@ keywords: changelog, release notes --- {% if is_release_notes_processor %} -{% capture baseurl %}https://pmd.github.io/pmd-{{ site.pmd.version }}/{% endcapture %} +{% capture baseurl %}https://docs.pmd-code.org/pmd-doc-{{ site.pmd.version }}/{% endcapture %} {% else %} {% assign baseurl = "" %} {% endif %} @@ -34,16 +34,39 @@ for all.

{% tocmaker is_release_notes_processor %} -### Changes since 7.0.0-rc1 +### Changes since 7.0.0-rc2 This section lists the most important changes from the last release candidate. -The remaining section describe the complete release notes for 7.0.0. +The remaining section describes the complete release notes for 7.0.0. + +#### New CPD report format cpdhtml-v2.xslt + +Thanks to @mohan-chinnappan-n a new CPD report format has been added which features a data table. +It uses an XSLT stylesheet to convert CPD's XML format into HTML. + +See [the example report]({{ baseurl }}report-examples/cpdhtml-v2.html). + +#### Fixed issues -Fixed Issues: * java-codestyle - * [#4273](https://github.com/pmd/pmd/issues/4273): \[java] CommentDefaultAccessModifier ignoredAnnotations should include "org.junit.jupiter.api.extension.RegisterExtension" by default + * [#4432](https://github.com/pmd/pmd/issues/4432): \[java] \[7.0-rc1] UnnecessaryImport - Unused static import is being used * java-errorprone - * [#4449](https://github.com/pmd/pmd/issues/4449): \[java] AvoidAccessibilityAlteration: Possible false positive in AvoidAccessibilityAlteration rule when using Lambda expression + * [#4457](https://github.com/pmd/pmd/issues/4457): \[java] OverrideBothEqualsAndHashcode: false negative with anonymous classes + * [#4546](https://github.com/pmd/pmd/issues/4546): \[java] OverrideBothEqualsAndHashCode ignores records + +#### API Changes + +* The following previously deprecated classes have been removed: + * pmd-core + * `net.sourceforge.pmd.PMD` + * `net.sourceforge.pmd.cli.PMDCommandLineInterface` + * `net.sourceforge.pmd.cli.PMDParameters` + * `net.sourceforge.pmd.cli.PmdParametersParseResult` + +#### External Contributions + +* [#4426](https://github.com/pmd/pmd/pull/4426): \[cpd] New XML to HTML XLST report format for PMD CPD - [mohan-chinnappan-n](https://github.com/mohan-chinnappan-n) (@mohan-chinnappan-n) +* [#4540](https://github.com/pmd/pmd/pull/4540): \[java] Fix #4457: false negative about OverrideBothEqualsAndHashcode - [AnnaDev](https://github.com/LynnBroe) (@LynnBroe) ### 🚀 Major Features and Enhancements @@ -60,7 +83,7 @@ The new official logo of PMD: * Rewritten type resolution framework and symbol table correctly implements the JLS * AST exposes more semantic information (method calls, field accesses) -For more information, see the [Detailed Release Notes for PMD 7](pmd_release_notes_pmd7.html). +For more information, see the [Detailed Release Notes for PMD 7]({{ baseurl }}pmd_release_notes_pmd7.html). Contributors: [Clément Fournier](https://github.com/oowekyala) (@oowekyala), [Andreas Dangel](https://github.com/adangel) (@adangel), @@ -78,7 +101,7 @@ Contributors: [Clément Fournier](https://github.com/oowekyala) (@oowekyala), ![Demo]({{ baseurl }}images/userdocs/pmd-demo.gif) -For more information, see the [Detailed Release Notes for PMD 7](pmd_release_notes_pmd7.html). +For more information, see the [Detailed Release Notes for PMD 7]({{ baseurl }}pmd_release_notes_pmd7.html). Contributors: [Juan Martín Sotuyo Dodero](https://github.com/jsotuyod) (@jsotuyod) @@ -88,16 +111,28 @@ Contributors: [Juan Martín Sotuyo Dodero](https://github.com/jsotuyod) (@jsotuy * Previously, Antlr grammar could only be used for CPD * New supported languages: Swift and Kotlin -For more information, see the [Detailed Release Notes for PMD 7](pmd_release_notes_pmd7.html). +For more information, see the [Detailed Release Notes for PMD 7]({{ baseurl }}pmd_release_notes_pmd7.html). Contributors: [Lucas Soncini](https://github.com/lsoncini) (@lsoncini), [Matías Fraga](https://github.com/matifraga) (@matifraga), [Tomás De Lucca](https://github.com/tomidelucca) (@tomidelucca) +#### Updated PMD Designer + +This PMD release ships a new version of the pmd-designer. +For the changes, see [PMD Designer Changelog](https://github.com/pmd/pmd-designer/releases/tag/7.0.0-rc1). + +#### New CPD report format cpdhtml-v2.xslt + +Thanks to @mohan-chinnappan-n a new CPD report format has been added which features a data table. +It uses an XSLT stylesheet to convert CPD's XML format into HTML. + +See [the example report]({{ baseurl }}report-examples/cpdhtml-v2.html). + ### 🎉 Language Related Changes Note that this is just a concise listing of the highlight. -For more information on the languages, see the [Detailed Release Notes for PMD 7](pmd_release_notes_pmd7.html). +For more information on the languages, see the [Detailed Release Notes for PMD 7]({{ baseurl }}pmd_release_notes_pmd7.html). #### New: Swift support @@ -114,6 +149,28 @@ Contributors: [Lucas Soncini](https://github.com/lsoncini) (@lsoncini), * Support for Kotlin 1.8 grammar * initially 2 built-in rules +#### New: CPD support for TypeScript + +Thanks to a contribution, CPD now supports the TypeScript language. It is shipped +with the rest of the JavaScript support in the module `pmd-javascript`. + +Contributors: [Paul Guyot](https://github.com/pguyot) (@pguyot) + +#### New: CPD support for Julia + +Thanks to a contribution, CPD now supports the Julia language. It is shipped +in the new module `pmd-julia`. + +Contributors: [Wener](https://github.com/wener-tiobe) (@wener-tiobe) + +#### New: CPD support for Coco + +Thanks to a contribution, CPD now supports Coco, a modern programming language +designed specifically for building event-driven software. It is shipped in the new +module `pmd-coco`. + +Contributors: [Wener](https://github.com/wener-tiobe) (@wener-tiobe) + #### Changed: JavaScript support * latest version supports ES6 and also some new constructs (see [Rhino](https://github.com/mozilla/rhino)]) @@ -147,36 +204,121 @@ Contributors: [Lucas Soncini](https://github.com/lsoncini) (@lsoncini), #### Changed Rules -**Java** +**General changes** -* {% rule "java/codestyle/UnnecessaryFullyQualifiedName" %}: the rule has two new properties, +* All statistical rules (like ExcessiveClassLength, ExcessiveParameterList) have been simplified and unified. + The properties `topscore` and `sigma` have been removed. The property `minimum` is still there, however the type is not + a decimal number anymore but has been changed to an integer. This affects rules in the languages Apex, Java, PLSQL + and Velocity Template Language (vm): + * Apex: {% rule apex/design/ExcessiveClassLength %}, {% rule apex/design/ExcessiveParameterList %}, + {% rule apex/design/ExcessivePublicCount %}, {% rule apex/design/NcssConstructorCount %}, + {% rule apex/design/NcssMethodCount %}, {% rule apex/design/NcssTypeCount %} + * Java: {% rule java/design/ExcessiveImports %}, {% rule java/design/ExcessiveParameterList %}, + {% rule java/design/ExcessivePublicCount %}, {% rule java/design/SwitchDensity %} + * PLSQL: {% rule plsql/design/ExcessiveMethodLength %}, {% rule plsql/design/ExcessiveObjectLength %}, + {% rule plsql/design/ExcessivePackageBodyLength %}, {% rule plsql/design/ExcessivePackageSpecificationLength %}, + {% rule plsql/design/ExcessiveParameterList %}, {% rule plsql/design/ExcessiveTypeLength %}, + {% rule plsql/design/NcssMethodCount %}, {% rule plsql/design/NcssObjectCount %}, + {% rule plsql/design/NPathComplexity %} + * VM: {% rule vm/design/ExcessiveTemplateLength %} + +* The general property `violationSuppressXPath` which is available for all rules to + [suppress warnings]({{ baseurl }}pmd_userdocs_suppressing_warnings.html) now uses XPath version 3.1 by default. + This version of the XPath language is mostly identical to XPath 2.0. In PMD 6, XPath 1.0 has been used. + If you upgrade from PMD 6, you need to verify your `violationSuppressXPath` properties. + +**Apex General changes** + +* The properties `cc_categories`, `cc_remediation_points_multiplier`, `cc_block_highlighting` have been removed + from all rules. These properties have been deprecated since PMD 6.13.0. + See [issue #1648](https://github.com/pmd/pmd/issues/1648) for more details. + +**Java General changes** + +* Violations reported on methods or classes previously reported the line range of the entire method + or class. With PMD 7.0.0, the reported location is now just the identifier of the method or class. + This affects various rules, e.g. {% rule java/design/CognitiveComplexity %}. + + The report location is controlled by the overrides of the method {% jdoc core::lang.ast.Node#getReportLocation() %} + in different node types. + + See [issue #4439](https://github.com/pmd/pmd/issues/4439) and [issue #730](https://github.com/pmd/pmd/issues/730) + for more details. + +**Java Best Practices** + +* {% rule java/bestpractices/ArrayIsStoredDirectly %}: Violations are now reported on the assignment and not + anymore on the formal parameter. The reported line numbers will probably move. +* {% rule java/bestpractices/AvoidReassigningLoopVariables %}: This rule might not report anymore all + reassignments of the control variable in for-loops when the property `forReassign` is set to `skip`. + See [issue #4500](https://github.com/pmd/pmd/issues/4500) for more details. +* {% rule java/bestpractices/LooseCoupling %}: The rule has a new property to allow some types to be coupled + to (`allowedTypes`). +* {% rule java/bestpractices/UnusedLocalVariable %}: This rule has some important false-negatives fixed + and finds many more cases now. For details see issues [#2130](https://github.com/pmd/pmd/issues/2130), + [#4516](https://github.com/pmd/pmd/issues/4516), and [#4517](https://github.com/pmd/pmd/issues/4517). + +**Java Codestyle** + +* {% rule java/codestyle/MethodNamingConventions %}: The property `checkNativeMethods` has been removed. The + property was deprecated since PMD 6.3.0. Use the property `nativePattern` to control whether native methods + should be considered or not. +* {% rule java/codestyle/ShortVariable %}: This rule now also reports short enum constant names. +* {% rule java/codestyle/UseDiamondOperator %}: The property `java7Compatibility` has been removed. The rule now + handles Java 7 properly without a property. +* {% rule java/codestyle/UnnecessaryFullyQualifiedName %}: The rule has two new properties, to selectively disable reporting on static field and method qualifiers. The rule also has been improved to be more precise. -* {% rule "java/codestyle/UselessParentheses" %}: the rule has two new properties which control how strict +* {% rule java/codestyle/UselessParentheses %}: The rule has two new properties which control how strict the rule should be applied. With `ignoreClarifying` (default: true) parentheses that are strictly speaking not necessary are allowed, if they separate expressions of different precedence. The other property `ignoreBalancing` (default: true) is similar, in that it allows parentheses that help reading and understanding the expressions. -* {% rule "java/bestpractices/LooseCoupling" %}: the rule has a new property to allow some types to be coupled - to (`allowedTypes`). -* {% rule "java/errorprone/EmptyCatchBlock" %}: `CloneNotSupportedException` and `InterruptedException` are not - special-cased anymore. Rename the exception parameter to `ignored` to ignore them. -* {% rule "java/errorprone/DontImportSun" %}: `sun.misc.Signal` is not special-cased anymore. -* {% rule "java/codestyle/UseDiamondOperator" %}: the property `java7Compatibility` is removed. The rule now - handles Java 7 properly without a property. -* {% rule "java/design/SingularField" %}: Properties `checkInnerClasses` and `disallowNotAssignment` are removed. - The rule is now more precise and will check these cases properly. -* {% rule "java/design/UseUtilityClass" %}: The property `ignoredAnnotations` has been removed. -* {% rule "java/design/LawOfDemeter" %}: the rule has a new property `trustRadius`. This defines the maximum degree + +**Java Design** + +* {% rule java/design/CyclomaticComplexity %}: The property `reportLevel` has been removed. The property was + deprecated since PMD 6.0.0. The report level can now be configured separated for classes and methods using + `classReportLevel` and `methodReportLevel` instead. +* {% rule java/design/ImmutableField %}: The property `ignoredAnnotations` has been removed. The property was + deprecated since PMD 6.52.0. +* {% rule java/design/LawOfDemeter %}: The rule has a new property `trustRadius`. This defines the maximum degree of trusted data. The default of 1 is the most restrictive. -* {% rule "java/documentation/CommentContent" %}: The properties `caseSensitive` and `disallowedTerms` are removed. The - new property `fobiddenRegex` can be used now to define the disallowed terms with a single regular +* {% rule java/design/NPathComplexity %}: The property `minimum` has been removed. It was deprecated since PMD 6.0.0. + Use the property `reportLevel` instead. +* {% rule java/design/SingularField %}: The properties `checkInnerClasses` and `disallowNotAssignment` have been removed. + The rule is now more precise and will check these cases properly. +* {% rule java/design/UseUtilityClass %}: The property `ignoredAnnotations` has been removed. + +**Java Documentation** + +* {% rule java/documentation/CommentContent %}: The properties `caseSensitive` and `disallowedTerms` are removed. The + new property `forbiddenRegex` can be used now to define the disallowed terms with a single regular expression. +* {% rule java/documentation/CommentRequired %}: + * Overridden methods are now detected even without the `@Override` + annotation. This is relevant for the property `methodWithOverrideCommentRequirement`. + See also [pull request #3757](https://github.com/pmd/pmd/pull/3757). + * Elements in annotation types are now detected as well. This might lead to an increased number of violations + for missing public method comments. +* {% rule java/documentation/CommentSize %}: When determining the line-length of a comment, the leading comment + prefix markers (e.g. `*` or `//`) are ignored and don't add up to the line-length. + See also [pull request #4369](https://github.com/pmd/pmd/pull/4369). + +**Java Error Prone** + +* {% rule java/errorprone/AvoidDuplicateLiterals %}: The property `exceptionfile` has been removed. The property was + deprecated since PMD 6.10.0. Use the property `exceptionList` instead. +* {% rule java/errorprone/DontImportSun %}: `sun.misc.Signal` is not special-cased anymore. +* {% rule java/errorprone/EmptyCatchBlock %}: `CloneNotSupportedException` and `InterruptedException` are not + special-cased anymore. Rename the exception parameter to `ignored` to ignore them. +* {% rule java/errorprone/ImplicitSwitchFallThrough %}: Violations are now reported on the case statements + rather than on the switch statements. This is more accurate but might result in more violations now. #### Removed Rules Many rules, that were previously deprecated have been finally removed. -See [Detailed Release Notes for PMD 7](pmd_release_notes_pmd7.html) for the complete list. +See [Detailed Release Notes for PMD 7]({{ baseurl }}pmd_release_notes_pmd7.html) for the complete list. ### 🚨 API @@ -185,7 +327,7 @@ have a clear separation between a well-defined API and the implementation, which This should help us in future development. Also, there are some improvement and changes in different areas. For the detailed description -of the changes listed here, see [Detailed Release Notes for PMD 7](pmd_release_notes_pmd7.html). +of the changes listed here, see [Detailed Release Notes for PMD 7]({{ baseurl }}pmd_release_notes_pmd7.html). * Miscellaneous smaller changes and cleanups * XPath 3.1 support for XPath-based rules @@ -195,7 +337,7 @@ of the changes listed here, see [Detailed Release Notes for PMD 7](pmd_release_n * Language Lifecycle and Language Properties ### 💥 Compatibility and migration notes -See [Detailed Release Notes for PMD 7](pmd_release_notes_pmd7.html). +See [Detailed Release Notes for PMD 7]({{ baseurl }}pmd_release_notes_pmd7.html). ### 🐛 Fixed Issues @@ -208,6 +350,7 @@ See [Detailed Release Notes for PMD 7](pmd_release_notes_pmd7.html). * [#2497](https://github.com/pmd/pmd/issues/2497): PMD 7 Logo page * [#2498](https://github.com/pmd/pmd/issues/2498): Update PMD 7 Logo in documentation * [#3797](https://github.com/pmd/pmd/issues/3797): \[all] Use JUnit5 + * [#4462](https://github.com/pmd/pmd/issues/4462): Provide Software Bill of Materials (SBOM) * ant * [#4080](https://github.com/pmd/pmd/issues/4080): \[ant] Split off Ant integration into a new submodule * core @@ -220,6 +363,7 @@ See [Detailed Release Notes for PMD 7](pmd_release_notes_pmd7.html). * [#2218](https://github.com/pmd/pmd/issues/2218): \[core] `isFindBoundary` should not be an attribute * [#2234](https://github.com/pmd/pmd/issues/2234): \[core] Consolidate PMD CLI into a single command * [#2239](https://github.com/pmd/pmd/issues/2239): \[core] Merging Javacc build scripts + * [#2500](https://github.com/pmd/pmd/issues/2500): \[core] Clarify API for ANTLR based languages * [#2518](https://github.com/pmd/pmd/issues/2518): \[core] Language properties * [#2602](https://github.com/pmd/pmd/issues/2602): \[core] Remove ParserOptions * [#2614](https://github.com/pmd/pmd/pull/2614): \[core] Upgrade Saxon, add XPath 3.1, remove Jaxen @@ -244,6 +388,11 @@ See [Detailed Release Notes for PMD 7](pmd_release_notes_pmd7.html). * [#2234](https://github.com/pmd/pmd/issues/2234): \[core] Consolidate PMD CLI into a single command * [#3828](https://github.com/pmd/pmd/issues/3828): \[core] Progress reporting * [#4079](https://github.com/pmd/pmd/issues/4079): \[cli] Split off CLI implementation into a pmd-cli submodule + * [#4482](https://github.com/pmd/pmd/issues/4482): \[cli] pmd.bat can only be executed once + * [#4484](https://github.com/pmd/pmd/issues/4484): \[cli] ast-dump with no properties produce an NPE +* doc + * [#2501](https://github.com/pmd/pmd/issues/2501): \[doc] Verify ANTLR Documentation + * [#4438](https://github.com/pmd/pmd/issues/4438): \[doc] Documentation links in VS Code are outdated * testing * [#2435](https://github.com/pmd/pmd/issues/2435): \[test] Remove duplicated Dummy language module * [#4234](https://github.com/pmd/pmd/issues/4234): \[test] Tests that change the logging level do not work @@ -258,6 +407,7 @@ Language specific fixes: * [#4427](https://github.com/pmd/pmd/issues/4427): \[apex] ApexBadCrypto test failing to detect inline code * apex-design * [#2667](https://github.com/pmd/pmd/issues/2667): \[apex] Integrate nawforce/ApexLink to build robust Unused rule + * [#4509](https://github.com/pmd/pmd/issues/4509): \[apex] ExcessivePublicCount doesn't consider inner classes correctly * java * [#520](https://github.com/pmd/pmd/issues/520): \[java] Allow `@SuppressWarnings` with constants instead of literals * [#864](https://github.com/pmd/pmd/issues/864): \[java] Similar/duplicated implementations for determining FQCN @@ -274,6 +424,7 @@ Language specific fixes: * [#1661](https://github.com/pmd/pmd/issues/1661): \[java] About operator nodes * [#2366](https://github.com/pmd/pmd/pull/2366): \[java] Remove qualified names * [#2819](https://github.com/pmd/pmd/issues/2819): \[java] GLB bugs in pmd 7 + * [#3642](https://github.com/pmd/pmd/issues/3642): \[java] Parse error on rare extra dimensions on method return type on annotation methods * [#3763](https://github.com/pmd/pmd/issues/3763): \[java] Ambiguous reference error in valid code * [#3749](https://github.com/pmd/pmd/issues/3749): \[java] Improve `isOverridden` in ASTMethodDeclaration * [#3750](https://github.com/pmd/pmd/issues/3750): \[java] Make symbol table support instanceof pattern bindings @@ -282,6 +433,8 @@ Language specific fixes: * [#4317](https://github.com/pmd/pmd/issues/4317): \[java] Some AST nodes should not be TypeNodes * [#4359](https://github.com/pmd/pmd/issues/4359): \[java] Type resolution fails with NPE when the scope is not a type declaration * [#4367](https://github.com/pmd/pmd/issues/4367): \[java] Move testrule TypeResTest into internal + * [#4383](https://github.com/pmd/pmd/issues/4383): \[java] IllegalStateException: Object is not an array type! + * [#4405](https://github.com/pmd/pmd/issues/4405): \[java] Processing error with ArrayIndexOutOfBoundsException * java-bestpractices * [#342](https://github.com/pmd/pmd/issues/342): \[java] AccessorMethodGeneration: Name clash with another public field not properly handled * [#755](https://github.com/pmd/pmd/issues/755): \[java] AccessorClassGeneration false positive for private constructors @@ -291,7 +444,9 @@ Language specific fixes: * [#1189](https://github.com/pmd/pmd/issues/1189): \[java] UnusedPrivateMethod false positive from inner class via external class * [#1205](https://github.com/pmd/pmd/issues/1205): \[java] Improve ConstantsInInterface message to mention alternatives * [#1212](https://github.com/pmd/pmd/issues/1212): \[java] Don't raise JUnitTestContainsTooManyAsserts on JUnit 5's assertAll - * [#1422](https://github.com/pmd/pmd/issues/1422): \[java] JUnitTestsShouldIncludeAssert false positive with inherited @Rule field + * [#1422](https://github.com/pmd/pmd/issues/1422): \[java] JUnitTestsShouldIncludeAssert false positive with inherited @Rule field + * [#1455](https://github.com/pmd/pmd/issues/1455): \[java] JUnitTestsShouldIncludeAssert: False positives for assert methods named "check" and "verify" + * [#1563](https://github.com/pmd/pmd/issues/1563): \[java] ForLoopCanBeForeach false positive with method call using index variable * [#1565](https://github.com/pmd/pmd/issues/1565): \[java] JUnitAssertionsShouldIncludeMessage false positive with AssertJ * [#1747](https://github.com/pmd/pmd/issues/1747): \[java] PreserveStackTrace false-positive * [#1969](https://github.com/pmd/pmd/issues/1969): \[java] MissingOverride false-positive triggered by package-private method overwritten in another package by extending class @@ -312,9 +467,14 @@ Language specific fixes: * [#2946](https://github.com/pmd/pmd/issues/2946): \[java] SwitchStmtsShouldHaveDefault false positive on enum inside enums * [#3672](https://github.com/pmd/pmd/pull/3672): \[java] LooseCoupling - fix false positive with generics * [#3675](https://github.com/pmd/pmd/pull/3675): \[java] MissingOverride - fix false positive with mixing type vars + * [#3858](https://github.com/pmd/pmd/issues/3858): \[java] UseCollectionIsEmpty should infer local variable type from method invocation + * [#4516](https://github.com/pmd/pmd/issues/4516): \[java] UnusedLocalVariable: false-negative with try-with-resources + * [#4517](https://github.com/pmd/pmd/issues/4517): \[java] UnusedLocalVariable: false-negative with compound assignments + * [#4518](https://github.com/pmd/pmd/issues/4518): \[java] UnusedLocalVariable: false-positive with multiple for-loop indices * java-codestyle * [#1208](https://github.com/pmd/pmd/issues/1208): \[java] PrematureDeclaration rule false-positive on variable declared to measure time * [#1429](https://github.com/pmd/pmd/issues/1429): \[java] PrematureDeclaration as result of method call (false positive) + * [#1480](https://github.com/pmd/pmd/issues/1480): \[java] IdenticalCatchBranches false positive with return expressions * [#1673](https://github.com/pmd/pmd/issues/1673): \[java] UselessParentheses false positive with conditional operator * [#1790](https://github.com/pmd/pmd/issues/1790): \[java] UnnecessaryFullyQualifiedName false positive with enum constant * [#1918](https://github.com/pmd/pmd/issues/1918): \[java] UselessParentheses false positive with boolean operators @@ -332,9 +492,14 @@ Language specific fixes: * [#3500](https://github.com/pmd/pmd/pull/3500): \[java] UnnecessaryBoxing - check for Integer.valueOf(String) calls * [#4273](https://github.com/pmd/pmd/issues/4273): \[java] CommentDefaultAccessModifier ignoredAnnotations should include "org.junit.jupiter.api.extension.RegisterExtension" by default * [#4357](https://github.com/pmd/pmd/pull/4357): \[java] Fix IllegalStateException in UseDiamondOperator rule + * [#4432](https://github.com/pmd/pmd/issues/4432): \[java] \[7.0-rc1] UnnecessaryImport - Unused static import is being used + * [#4487](https://github.com/pmd/pmd/issues/4487): \[java] UnnecessaryConstructor: false-positive with @Inject and @Autowired + * [#4511](https://github.com/pmd/pmd/issues/4511): \[java] LocalVariableCouldBeFinal shouldn't report unused variables + * [#4512](https://github.com/pmd/pmd/issues/4512): \[java] MethodArgumentCouldBeFinal shouldn't report unused parameters * java-design * [#1014](https://github.com/pmd/pmd/issues/1014): \[java] LawOfDemeter: False positive with lambda expression * [#1605](https://github.com/pmd/pmd/issues/1605): \[java] LawOfDemeter: False positive for standard UTF-8 charset name + * [#2160](https://github.com/pmd/pmd/issues/2160): \[java] Issues with Law of Demeter * [#2175](https://github.com/pmd/pmd/issues/2175): \[java] LawOfDemeter: False positive for chained methods with generic method call * [#2179](https://github.com/pmd/pmd/issues/2179): \[java] LawOfDemeter: False positive with static property access - should treat class-level property as global object, not dot-accessed property * [#2180](https://github.com/pmd/pmd/issues/2180): \[java] LawOfDemeter: False positive with Thread and ThreadLocalRandom @@ -344,7 +509,11 @@ Language specific fixes: * [#3668](https://github.com/pmd/pmd/pull/3668): \[java] ClassWithOnlyPrivateConstructorsShouldBeFinal - fix FP with inner private classes * [#3754](https://github.com/pmd/pmd/issues/3754): \[java] SingularField false positive with read in while condition * [#3786](https://github.com/pmd/pmd/issues/3786): \[java] SimplifyBooleanReturns should consider operator precedence + * [#3840](https://github.com/pmd/pmd/issues/3840): \[java] LawOfDemeter disallows method call on locally created object * [#4238](https://github.com/pmd/pmd/pull/4238): \[java] Make LawOfDemeter not use the rulechain + * [#4254](https://github.com/pmd/pmd/issues/4254): \[java] ImmutableField - false positive with Lombok @Setter + * [#4477](https://github.com/pmd/pmd/issues/4477): \[java] SignatureDeclareThrowsException: false-positive with TestNG annotations + * [#4490](https://github.com/pmd/pmd/issues/4490): \[java] ImmutableField - false negative with Lombok @Getter * java-documentation * [#4369](https://github.com/pmd/pmd/pull/4369): \[java] Improve CommentSize * [#4416](https://github.com/pmd/pmd/pull/4416): \[java] Fix reported line number in CommentContentRule @@ -352,7 +521,7 @@ Language specific fixes: * [#659](https://github.com/pmd/pmd/issues/659): \[java] MissingBreakInSwitch - last default case does not contain a break * [#1005](https://github.com/pmd/pmd/issues/1005): \[java] CloneMethodMustImplementCloneable triggers for interfaces * [#1669](https://github.com/pmd/pmd/issues/1669): \[java] NullAssignment - FP with ternay and null as constructor argument - * [#1899](https://github.com/pmd/pmd/issues/1899): \[java] Recognize @SuppressWanings("fallthrough") for MissingBreakInSwitch + * [#1899](https://github.com/pmd/pmd/issues/1899): \[java] Recognize @SuppressWanings("fallthrough") for MissingBreakInSwitch * [#2320](https://github.com/pmd/pmd/issues/2320): \[java] NullAssignment - FP with ternary and null as method argument * [#2532](https://github.com/pmd/pmd/issues/2532): \[java] AvoidDecimalLiteralsInBigDecimalConstructor can not detect the case `new BigDecimal(Expression)` * [#2579](https://github.com/pmd/pmd/issues/2579): \[java] MissingBreakInSwitch detects the lack of break in the last case @@ -365,17 +534,27 @@ Language specific fixes: * [#3173](https://github.com/pmd/pmd/issues/3173): \[java] UseProperClassLoader false positive * [#3351](https://github.com/pmd/pmd/issues/3351): \[java] ConstructorCallsOverridableMethod ignores abstract methods * [#3400](https://github.com/pmd/pmd/issues/3400): \[java] AvoidUsingOctalValues FN with underscores + * [#3843](https://github.com/pmd/pmd/issues/3843): \[java] UseEqualsToCompareStrings should consider return type * [#4356](https://github.com/pmd/pmd/pull/4356): \[java] Fix NPE in CloseResourceRule * [#4449](https://github.com/pmd/pmd/issues/4449): \[java] AvoidAccessibilityAlteration: Possible false positive in AvoidAccessibilityAlteration rule when using Lambda expression + * [#4457](https://github.com/pmd/pmd/issues/4457): \[java] OverrideBothEqualsAndHashcode: false negative with anonymous classes + * [#4493](https://github.com/pmd/pmd/issues/4493): \[java] MissingStaticMethodInNonInstantiatableClass: false-positive about @Inject + * [#4505](https://github.com/pmd/pmd/issues/4505): \[java] ImplicitSwitchFallThrough NPE in PMD 7.0.0-rc1 + * [#4513](https://github.com/pmd/pmd/issues/4513): \[java] UselessOperationOnImmutable various false negatives with String + * [#4514](https://github.com/pmd/pmd/issues/4514): \[java] AvoidLiteralsInIfCondition false positive and negative for String literals when ignoreExpressions=true + * [#4546](https://github.com/pmd/pmd/issues/4546): \[java] OverrideBothEqualsAndHashCode ignores records * java-multithreading * [#2537](https://github.com/pmd/pmd/issues/2537): \[java] DontCallThreadRun can't detect the case that call run() in `this.run()` * [#2538](https://github.com/pmd/pmd/issues/2538): \[java] DontCallThreadRun can't detect the case that call run() in `foo.bar.run()` * [#2577](https://github.com/pmd/pmd/issues/2577): \[java] UseNotifyAllInsteadOfNotify falsely detect a special case with argument: `foo.notify(bar)` + * [#4483](https://github.com/pmd/pmd/issues/4483): \[java] NonThreadSafeSingleton false positive with double-checked locking * java-performance * [#1224](https://github.com/pmd/pmd/issues/1224): \[java] InefficientEmptyStringCheck false negative in anonymous class * [#2587](https://github.com/pmd/pmd/issues/2587): \[java] AvoidArrayLoops could also check for list copy through iterated List.add() * [#2712](https://github.com/pmd/pmd/issues/2712): \[java] SimplifyStartsWith false-positive with AssertJ * [#3486](https://github.com/pmd/pmd/pull/3486): \[java] InsufficientStringBufferDeclaration: Fix NPE + * [#3848](https://github.com/pmd/pmd/issues/3848): \[java] StringInstantiation: false negative when using method result + * [#4070](https://github.com/pmd/pmd/issues/4070): \[java] A false positive about the rule RedundantFieldInitializer * kotlin * [#419](https://github.com/pmd/pmd/issues/419): \[kotlin] Add support for Kotlin * [#4389](https://github.com/pmd/pmd/pull/4389): \[kotlin] Update grammar to version 1.8 @@ -395,15 +574,25 @@ Language specific fixes: * [#1882](https://github.com/pmd/pmd/pull/1882): \[swift] UnavailableFunction Swift rule - [Tomás de Lucca](https://github.com/tomidelucca) (@tomidelucca) * [#2830](https://github.com/pmd/pmd/pull/2830): \[apex] Apexlink POC - [Kevin Jones](https://github.com/nawforce) (@nawforce) * [#3866](https://github.com/pmd/pmd/pull/3866): \[core] Add CLI Progress Bar - [@JerritEic](https://github.com/JerritEic) (@JerritEic) +* [#4402](https://github.com/pmd/pmd/pull/4402): \[javascript] CPD: add support for Typescript using antlr4 grammar - [Paul Guyot](https://github.com/pguyot) (@pguyot) +* [#4403](https://github.com/pmd/pmd/pull/4403): \[julia] CPD: Add support for Julia code duplication - [Wener](https://github.com/wener-tiobe) (@wener-tiobe) * [#4412](https://github.com/pmd/pmd/pull/4412): \[doc] Added new error msg to ConstantsInInterface - [David Ljunggren](https://github.com/dague1) (@dague1) +* [#4426](https://github.com/pmd/pmd/pull/4426): \[cpd] New XML to HTML XLST report format for PMD CPD - [mohan-chinnappan-n](https://github.com/mohan-chinnappan-n) (@mohan-chinnappan-n) * [#4428](https://github.com/pmd/pmd/pull/4428): \[apex] ApexBadCrypto bug fix for #4427 - inline detection of hard coded values - [Steven Stearns](https://github.com/sfdcsteve) (@sfdcsteve) +* [#4431](https://github.com/pmd/pmd/pull/4431): \[coco] CPD: Coco support for code duplication detection - [Wener](https://github.com/wener-tiobe) (@wener-tiobe) * [#4444](https://github.com/pmd/pmd/pull/4444): \[java] CommentDefaultAccessModifier - ignore org.junit.jupiter.api.extension.RegisterExtension by default - [Nirvik Patel](https://github.com/nirvikpatel) (@nirvikpatel) * [#4450](https://github.com/pmd/pmd/pull/4450): \[java] Fix #4449 AvoidAccessibilityAlteration: Correctly handle Lambda expressions in PrivilegedAction scenarios - [Seren](https://github.com/mohui1999) (@mohui1999) +* [#4452](https://github.com/pmd/pmd/pull/4452): \[doc] Update PMD_APEX_ROOT_DIRECTORY documentation reference - [nwcm](https://github.com/nwcm) (@nwcm) +* [#4474](https://github.com/pmd/pmd/pull/4474): \[java] ImmutableField: False positive with lombok (fixes #4254) - [Pim van der Loos](https://github.com/PimvanderLoos) (@PimvanderLoos) +* [#4488](https://github.com/pmd/pmd/pull/4488): \[java] Fix #4477: A false-positive about SignatureDeclareThrowsException - [AnnaDev](https://github.com/LynnBroe) (@LynnBroe) +* [#4494](https://github.com/pmd/pmd/pull/4494): \[java] Fix #4487: A false-positive about UnnecessaryConstructor and @Inject and @Autowired - [AnnaDev](https://github.com/LynnBroe) (@LynnBroe) +* [#4495](https://github.com/pmd/pmd/pull/4495): \[java] Fix #4493: false-positive about MissingStaticMethodInNonInstantiatableClass and @Inject - [AnnaDev](https://github.com/LynnBroe) (@LynnBroe) +* [#4520](https://github.com/pmd/pmd/pull/4520): \[doc] Fix typo: missing closing quotation mark after CPD-END - [João Dinis Ferreira](https://github.com/joaodinissf) (@joaodinissf) +* [#4540](https://github.com/pmd/pmd/pull/4540): \[java] Fix #4457: false negative about OverrideBothEqualsAndHashcode - [AnnaDev](https://github.com/LynnBroe) (@LynnBroe) ### 📈 Stats -* 4416 commits -* 464 closed tickets & PRs -* Days since last release: 28 +* 4557 commits +* 572 closed tickets & PRs +* Days since last release: 35 {% endtocmaker %} - diff --git a/docs/pages/release_notes_old.md b/docs/pages/release_notes_old.md index 7b05d6ff5b..f773376557 100644 --- a/docs/pages/release_notes_old.md +++ b/docs/pages/release_notes_old.md @@ -7,12 +7,637 @@ Previous versions of PMD can be downloaded here: https://github.com/pmd/pmd/rele +## 29-April-2023 - 7.0.0-rc2 + +We're excited to bring you the next major version of PMD! + +Since this is a big release, we provide here only a concise version of the release notes. We prepared a separate +page with the full [Detailed Release Notes for PMD 7.0.0](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_release_notes_pmd7.html). + +
+ℹ️ Release Candidates +

PMD 7.0.0 is finally almost ready. In order to gather feedback, we are going to ship a couple of release candidates. +These are officially available on GitHub and Maven Central and can be used as usual (e.g. as a dependency). +We encourage you to try out the new features, but keep in mind that we may introduce API breaking changes between +the release candidates. It should be stable enough if you don't use custom rules.

+ +

We have still some tasks planned for the next release candidates. +You can see the progress in PMD 7 Tracking Issue #3898.

+ +

If you find any problem or difficulty while updating from PMD 6, please provide feedback via our +issue tracker. That way we can improve the experience +for all.

+
+ +### Table Of Contents + +* [Changes since 7.0.0-rc1](#changes-since-7.0.0-rc1) + * [API Changes](#api-changes) + * [Updated PMD Designer](#updated-pmd-designer) + * [Language Related Changes](#language-related-changes) + * [Rule Changes](#rule-changes) + * [Fixed Issues](#fixed-issues) + * [External contributions](#external-contributions) +* [🚀 Major Features and Enhancements](#🚀-major-features-and-enhancements) + * [New official logo](#new-official-logo) + * [Revamped Java module](#revamped-java-module) + * [Revamped Command Line Interface](#revamped-command-line-interface) + * [Full Antlr support](#full-antlr-support) + * [Updated PMD Designer](#updated-pmd-designer) +* [🎉 Language Related Changes](#🎉-language-related-changes) + * [New: Swift support](#new:-swift-support) + * [New: Kotlin support (experimental)](#new:-kotlin-support-(experimental)) + * [New: CPD support for TypeScript](#new:-cpd-support-for-typescript) + * [New: CPD support for Julia](#new:-cpd-support-for-julia) + * [Changed: JavaScript support](#changed:-javascript-support) + * [Changed: Language versions](#changed:-language-versions) +* [🌟 New and changed rules](#🌟-new-and-changed-rules) + * [New Rules](#new-rules) + * [Changed Rules](#changed-rules) + * [Removed Rules](#removed-rules) +* [🚨 API](#🚨-api) +* [💥 Compatibility and migration notes](#💥-compatibility-and-migration-notes) +* [🐛 Fixed Issues](#🐛-fixed-issues) +* [✨ External Contributions](#✨-external-contributions) +* [📈 Stats](#📈-stats) + +### Changes since 7.0.0-rc1 + +This section lists the most important changes from the last release candidate. +The remaining section describes the complete release notes for 7.0.0. + +#### API Changes +* Moved the two classes AntlrTokenizer and JavaCCTokenizer from + `internal` package into package net.sourceforge.pmd.cpd.impl. These two classes are part of the API and + are base classes for CPD language implementations. +* `AntlrBaseRule` is gone in favor of AbstractVisitorRule. +* The classes KotlinInnerNode and SwiftInnerNode + are package-private now. +* The parameter order of addSourceFile has been swapped + in order to have the same meaning as in 6.55.0. That will make it easier if you upgrade from 6.55.0 to 7.0.0. + However, that means, that you need to change these method calls if you have migrated to 7.0.0-rc1 already. + +#### Updated PMD Designer +This PMD release ships a new version of the pmd-designer. +For the changes, see [PMD Designer Changelog](https://github.com/pmd/pmd-designer/releases/tag/7.0.0-rc1). + +#### Language Related Changes +* New: CPD support for TypeScript +* New: CPD support for Julia + +#### Rule Changes +* [`ImmutableField`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_java_design.html#immutablefield): the property `ignoredAnnotations` has been removed. The property was + deprecated since PMD 6.52.0. +* [`SwitchDensity`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_java_design.html#switchdensity): the type of the property `minimum` has been changed from decimal to integer + for consistency with other statistical rules. + +#### Fixed Issues +* cli + * [#4482](https://github.com/pmd/pmd/issues/4482): \[cli] pmd.bat can only be executed once + * [#4484](https://github.com/pmd/pmd/issues/4484): \[cli] ast-dump with no properties produce an NPE +* core + * [#2500](https://github.com/pmd/pmd/issues/2500): \[core] Clarify API for ANTLR based languages +* doc + * [#2501](https://github.com/pmd/pmd/issues/2501): \[doc] Verify ANTLR Documentation + * [#4438](https://github.com/pmd/pmd/issues/4438): \[doc] Documentation links in VS Code are outdated +* java-codestyle + * [#4273](https://github.com/pmd/pmd/issues/4273): \[java] CommentDefaultAccessModifier ignoredAnnotations should include "org.junit.jupiter.api.extension.RegisterExtension" by default + * [#4487](https://github.com/pmd/pmd/issues/4487): \[java] UnnecessaryConstructor: false-positive with @Inject and @Autowired +* java-design + * [#4254](https://github.com/pmd/pmd/issues/4254): \[java] ImmutableField - false positive with Lombok @Setter + * [#4477](https://github.com/pmd/pmd/issues/4477): \[java] SignatureDeclareThrowsException: false-positive with TestNG annotations + * [#4490](https://github.com/pmd/pmd/issues/4490): \[java] ImmutableField - false negative with Lombok @Getter +* java-errorprone + * [#4449](https://github.com/pmd/pmd/issues/4449): \[java] AvoidAccessibilityAlteration: Possible false positive in AvoidAccessibilityAlteration rule when using Lambda expression + * [#4493](https://github.com/pmd/pmd/issues/4493): \[java] MissingStaticMethodInNonInstantiatableClass: false-positive about @Inject + * [#4505](https://github.com/pmd/pmd/issues/4505): \[java] ImplicitSwitchFallThrough NPE in PMD 7.0.0-rc1 +* java-multithreading + * [#4483](https://github.com/pmd/pmd/issues/4483): \[java] NonThreadSafeSingleton false positive with double-checked locking +* miscellaneous + * [#4462](https://github.com/pmd/pmd/issues/4462): Provide Software Bill of Materials (SBOM) + +#### External contributions +* [#4402](https://github.com/pmd/pmd/pull/4402): \[javascript] CPD: add support for Typescript using antlr4 grammar - [Paul Guyot](https://github.com/pguyot) (@pguyot) +* [#4403](https://github.com/pmd/pmd/pull/4403): \[julia] CPD: Add support for Julia code duplication - [Wener](https://github.com/wener-tiobe) (@wener-tiobe) +* [#4444](https://github.com/pmd/pmd/pull/4444): \[java] CommentDefaultAccessModifier - ignore org.junit.jupiter.api.extension.RegisterExtension by default - [Nirvik Patel](https://github.com/nirvikpatel) (@nirvikpatel) +* [#4450](https://github.com/pmd/pmd/pull/4450): \[java] Fix #4449 AvoidAccessibilityAlteration: Correctly handle Lambda expressions in PrivilegedAction scenarios - [Seren](https://github.com/mohui1999) (@mohui1999) +* [#4452](https://github.com/pmd/pmd/pull/4452): \[doc] Update PMD_APEX_ROOT_DIRECTORY documentation reference - [nwcm](https://github.com/nwcm) (@nwcm) +* [#4474](https://github.com/pmd/pmd/pull/4474): \[java] ImmutableField: False positive with lombok (fixes #4254) - [Pim van der Loos](https://github.com/PimvanderLoos) (@PimvanderLoos) +* [#4488](https://github.com/pmd/pmd/pull/4488): \[java] Fix #4477: A false-positive about SignatureDeclareThrowsException - [AnnaDev](https://github.com/LynnBroe) (@LynnBroe) +* [#4494](https://github.com/pmd/pmd/pull/4494): \[java] Fix #4487: A false-positive about UnnecessaryConstructor and @Inject and @Autowired - [AnnaDev](https://github.com/LynnBroe) (@LynnBroe) +* [#4495](https://github.com/pmd/pmd/pull/4495): \[java] Fix #4493: false-positive about MissingStaticMethodInNonInstantiatableClass and @Inject - [AnnaDev](https://github.com/LynnBroe) (@LynnBroe) +* [#4520](https://github.com/pmd/pmd/pull/4520): \[doc] Fix typo: missing closing quotation mark after CPD-END - [João Dinis Ferreira](https://github.com/joaodinissf) (@joaodinissf) + +### 🚀 Major Features and Enhancements + +#### New official logo + +The new official logo of PMD: + +![New PMD Logo](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/images/logo/pmd-logo-300px.png) + +#### Revamped Java module + +* Java grammar substantially refactored - more correct regarding the Java Language Specification (JLS) +* Built-in rules have been upgraded for the changed AST +* Rewritten type resolution framework and symbol table correctly implements the JLS +* AST exposes more semantic information (method calls, field accesses) + +For more information, see the [Detailed Release Notes for PMD 7](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_release_notes_pmd7.html). + +Contributors: [Clément Fournier](https://github.com/oowekyala) (@oowekyala), +[Andreas Dangel](https://github.com/adangel) (@adangel), +[Juan Martín Sotuyo Dodero](https://github.com/jsotuyod) (@jsotuyod) + +#### Revamped Command Line Interface + +* unified and consistent Command Line Interface for both Linux/Unix and Windows across our different utilities +* single script `pmd` (`pmd.bat` for Windows) to launch the different utilities: + * `pmd check` to run PMD rules and analyze a project + * `pmd cpd` to run CPD (copy paste detector) + * `pmd designer` to run the PMD Rule Designer +* progress bar support for `pmd check` +* shell completion + +![Demo](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/images/userdocs/pmd-demo.gif) + +For more information, see the [Detailed Release Notes for PMD 7](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_release_notes_pmd7.html). + +Contributors: [Juan Martín Sotuyo Dodero](https://github.com/jsotuyod) (@jsotuyod) + +#### Full Antlr support + +* [Antlr](https://www.antlr.org/) based grammars can now be used to build full-fledged PMD rules. +* Previously, Antlr grammar could only be used for CPD +* New supported languages: Swift and Kotlin + +For more information, see the [Detailed Release Notes for PMD 7](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_release_notes_pmd7.html). + +Contributors: [Lucas Soncini](https://github.com/lsoncini) (@lsoncini), +[Matías Fraga](https://github.com/matifraga) (@matifraga), +[Tomás De Lucca](https://github.com/tomidelucca) (@tomidelucca) + +#### Updated PMD Designer + +This PMD release ships a new version of the pmd-designer. +For the changes, see [PMD Designer Changelog](https://github.com/pmd/pmd-designer/releases/tag/7.0.0-rc1). + +### 🎉 Language Related Changes + +Note that this is just a concise listing of the highlight. +For more information on the languages, see the [Detailed Release Notes for PMD 7](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_release_notes_pmd7.html). + +#### New: Swift support + +* use PMD to analyze Swift code with PMD rules +* initially 4 built-in rules + +Contributors: [Lucas Soncini](https://github.com/lsoncini) (@lsoncini), +[Matías Fraga](https://github.com/matifraga) (@matifraga), +[Tomás De Lucca](https://github.com/tomidelucca) (@tomidelucca) + +#### New: Kotlin support (experimental) + +* use PMD to analyze Kotlin code with PMD rules +* Support for Kotlin 1.8 grammar +* initially 2 built-in rules + +#### New: CPD support for TypeScript + +Thanks to a contribution, CPD now supports the TypeScript language. It is shipped +with the rest of the JavaScript support in the module `pmd-javascript`. + +Contributors: [Paul Guyot](https://github.com/pguyot) (@pguyot) + +#### New: CPD support for Julia + +Thanks to a contribution, CPD now supports the Julia language. It is shipped +in the new module `pmd-julia`. + +Contributors: [Wener](https://github.com/wener-tiobe) (@wener-tiobe) + +#### Changed: JavaScript support + +* latest version supports ES6 and also some new constructs (see [Rhino](https://github.com/mozilla/rhino)]) +* comments are retained + +#### Changed: Language versions + +* more predefined language versions for each supported language +* can be used to limit rule execution for specific versions only with `minimumLanguageVersion` and + `maximumLanguageVersion` attributes. + +### 🌟 New and changed rules + +#### New Rules + +**Apex** +* [`UnusedMethod`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_apex_design.html#unusedmethod) finds unused methods in your code. + +**Java** +* [`UnnecessaryBoxing`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_java_codestyle.html#unnecessaryboxing) reports boxing and unboxing conversions that may be made implicit. + +**Kotlin** +* [`FunctionNameTooShort`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_kotlin_bestpractices.html#functionnametooshort) +* [`OverrideBothEqualsAndHashcode`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_kotlin_errorprone.html#overridebothequalsandhashcode) + +**Swift** +* [`ProhibitedInterfaceBuilder`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_swift_bestpractices.html#prohibitedinterfacebuilder) +* [`UnavailableFunction`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_swift_bestpractices.html#unavailablefunction) +* [`ForceCast`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_swift_errorprone.html#forcecast) +* [`ForceTry`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_swift_errorprone.html#forcetry) + +#### Changed Rules + +**General changes** + +* All statistical rules (like ExcessiveClassLength, ExcessiveParameterList) have been simplified and unified. + The properties `topscore` and `sigma` have been removed. The property `minimum` is still there, however the type is not + a decimal number anymore but has been changed to an integer. This affects rules in the languages Apex, Java, PLSQL + and Velocity Template Language (vm): + * Apex: [`ExcessiveClassLength`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_apex_design.html#excessiveclasslength), [`ExcessiveParameterList`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_apex_design.html#excessiveparameterlist), + [`ExcessivePublicCount`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_apex_design.html#excessivepubliccount), [`NcssConstructorCount`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_apex_design.html#ncssconstructorcount), + [`NcssMethodCount`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_apex_design.html#ncssmethodcount), [`NcssTypeCount`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_apex_design.html#ncsstypecount) + * Java: [`ExcessiveImports`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_java_design.html#excessiveimports), [`ExcessiveParameterList`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_java_design.html#excessiveparameterlist), + [`ExcessivePublicCount`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_java_design.html#excessivepubliccount), [`SwitchDensity`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_java_design.html#switchdensity) + * PLSQL: [`ExcessiveMethodLength`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_plsql_design.html#excessivemethodlength), [`ExcessiveObjectLength`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_plsql_design.html#excessiveobjectlength), + [`ExcessivePackageBodyLength`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_plsql_design.html#excessivepackagebodylength), [`ExcessivePackageSpecificationLength`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_plsql_design.html#excessivepackagespecificationlength), + [`ExcessiveParameterList`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_plsql_design.html#excessiveparameterlist), [`ExcessiveTypeLength`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_plsql_design.html#excessivetypelength), + [`NcssMethodCount`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_plsql_design.html#ncssmethodcount), [`NcssObjectCount`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_plsql_design.html#ncssobjectcount), + [`NPathComplexity`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_plsql_design.html#npathcomplexity) + * VM: [`ExcessiveTemplateLength`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_vm_design.html#excessivetemplatelength) + +* The general property `violationSuppressXPath` which is available for all rules to + [suppress warnings](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_userdocs_suppressing_warnings.html) now uses XPath version 3.1 by default. + This version of the XPath language is mostly identical to XPath 2.0. In PMD 6, XPath 1.0 has been used. + If you upgrade from PMD 6, you need to verify your `violationSuppressXPath` properties. + +**Apex General changes** + +* The properties `cc_categories`, `cc_remediation_points_multiplier`, `cc_block_highlighting` have been removed + from all rules. These properties have been deprecated since PMD 6.13.0. + See [issue #1648](https://github.com/pmd/pmd/issues/1648) for more details. + +**Java General changes** + +* Violations reported on methods or classes previously reported the line range of the entire method + or class. With PMD 7.0.0, the reported location is now just the identifier of the method or class. + This affects various rules, e.g. [`CognitiveComplexity`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_java_design.html#cognitivecomplexity). + + The report location is controlled by the overrides of the method getReportLocation + in different node types. + + See [issue #4439](https://github.com/pmd/pmd/issues/4439) and [issue #730](https://github.com/pmd/pmd/issues/730) + for more details. + +**Java Best Practices** + +* [`ArrayIsStoredDirectly`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_java_bestpractices.html#arrayisstoreddirectly): Violations are now reported on the assignment and not + anymore on the formal parameter. The reported line numbers will probably move. +* [`AvoidReassigningLoopVariables`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_java_bestpractices.html#avoidreassigningloopvariables): This rule might not report anymore all + reassignments of the control variable in for-loops when the property `forReassign` is set to `skip`. + See [issue #4500](https://github.com/pmd/pmd/issues/4500) for more details. +* [`LooseCoupling`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_java_bestpractices.html#loosecoupling): The rule has a new property to allow some types to be coupled + to (`allowedTypes`). +* [`UnusedLocalVariable`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_java_bestpractices.html#unusedlocalvariable): This rule has some important false-negatives fixed + and finds many more cases now. For details see issues [#2130](https://github.com/pmd/pmd/issues/2130), + [#4516](https://github.com/pmd/pmd/issues/4516), and [#4517](https://github.com/pmd/pmd/issues/4517). + +**Java Codestyle** + +* [`MethodNamingConventions`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_java_codestyle.html#methodnamingconventions): The property `checkNativeMethods` has been removed. The + property was deprecated since PMD 6.3.0. Use the property `nativePattern` to control whether native methods + should be considered or not. +* [`ShortVariable`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_java_codestyle.html#shortvariable): This rule now also reports short enum constant names. +* [`UseDiamondOperator`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_java_codestyle.html#usediamondoperator): The property `java7Compatibility` has been removed. The rule now + handles Java 7 properly without a property. +* [`UnnecessaryFullyQualifiedName`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_java_codestyle.html#unnecessaryfullyqualifiedname): The rule has two new properties, + to selectively disable reporting on static field and method qualifiers. The rule also has been improved + to be more precise. +* [`UselessParentheses`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_java_codestyle.html#uselessparentheses): The rule has two new properties which control how strict + the rule should be applied. With `ignoreClarifying` (default: true) parentheses that are strictly speaking + not necessary are allowed, if they separate expressions of different precedence. + The other property `ignoreBalancing` (default: true) is similar, in that it allows parentheses that help + reading and understanding the expressions. + +**Java Design** + +* [`CyclomaticComplexity`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_java_design.html#cyclomaticcomplexity): The property `reportLevel` has been removed. The property was + deprecated since PMD 6.0.0. The report level can now be configured separated for classes and methods using + `classReportLevel` and `methodReportLevel` instead. +* [`ImmutableField`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_java_design.html#immutablefield): The property `ignoredAnnotations` has been removed. The property was + deprecated since PMD 6.52.0. +* [`LawOfDemeter`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_java_design.html#lawofdemeter): The rule has a new property `trustRadius`. This defines the maximum degree + of trusted data. The default of 1 is the most restrictive. +* [`NPathComplexity`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_java_design.html#npathcomplexity): The property `minimum` has been removed. It was deprecated since PMD 6.0.0. + Use the property `reportLevel` instead. +* [`SingularField`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_java_design.html#singularfield): The properties `checkInnerClasses` and `disallowNotAssignment` have been removed. + The rule is now more precise and will check these cases properly. +* [`UseUtilityClass`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_java_design.html#useutilityclass): The property `ignoredAnnotations` has been removed. + +**Java Documentation** + +* [`CommentContent`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_java_documentation.html#commentcontent): The properties `caseSensitive` and `disallowedTerms` are removed. The + new property `forbiddenRegex` can be used now to define the disallowed terms with a single regular + expression. +* [`CommentRequired`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_java_documentation.html#commentrequired): + * Overridden methods are now detected even without the `@Override` + annotation. This is relevant for the property `methodWithOverrideCommentRequirement`. + See also [pull request #3757](https://github.com/pmd/pmd/pull/3757). + * Elements in annotation types are now detected as well. This might lead to an increased number of violations + for missing public method comments. +* [`CommentSize`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_java_documentation.html#commentsize): When determining the line-length of a comment, the leading comment + prefix markers (e.g. `*` or `//`) are ignored and don't add up to the line-length. + See also [pull request #4369](https://github.com/pmd/pmd/pull/4369). + +**Java Error Prone** + +* [`AvoidDuplicateLiterals`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_java_errorprone.html#avoidduplicateliterals): The property `exceptionfile` has been removed. The property was + deprecated since PMD 6.10.0. Use the property `exceptionList` instead. +* [`DontImportSun`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_java_errorprone.html#dontimportsun): `sun.misc.Signal` is not special-cased anymore. +* [`EmptyCatchBlock`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_java_errorprone.html#emptycatchblock): `CloneNotSupportedException` and `InterruptedException` are not + special-cased anymore. Rename the exception parameter to `ignored` to ignore them. +* [`ImplicitSwitchFallThrough`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_rules_java_errorprone.html#implicitswitchfallthrough): Violations are now reported on the case statements + rather than on the switch statements. This is more accurate but might result in more violations now. + +#### Removed Rules + +Many rules, that were previously deprecated have been finally removed. +See [Detailed Release Notes for PMD 7](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_release_notes_pmd7.html) for the complete list. + +### 🚨 API + +The API of PMD has been growing over the years and needed some cleanup. The goal is, to +have a clear separation between a well-defined API and the implementation, which is internal. +This should help us in future development. + +Also, there are some improvement and changes in different areas. For the detailed description +of the changes listed here, see [Detailed Release Notes for PMD 7](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_release_notes_pmd7.html). + +* Miscellaneous smaller changes and cleanups +* XPath 3.1 support for XPath-based rules +* Node stream API for AST traversal +* Metrics framework +* Testing framework +* Language Lifecycle and Language Properties + +### 💥 Compatibility and migration notes +See [Detailed Release Notes for PMD 7](https://docs.pmd-code.org/pmd-doc-7.0.0-rc2/pmd_release_notes_pmd7.html). + +### 🐛 Fixed Issues + +* miscellaneous + * [#881](https://github.com/pmd/pmd/issues/881): \[all] Breaking API changes for 7.0.0 + * [#896](https://github.com/pmd/pmd/issues/896): \[all] Use slf4j + * [#1431](https://github.com/pmd/pmd/pull/1431): \[ui] Remove old GUI applications (designerold, bgastviewer) + * [#1451](https://github.com/pmd/pmd/issues/1451): \[core] RulesetFactoryCompatibility stores the whole ruleset file in memory as a string + * [#2496](https://github.com/pmd/pmd/issues/2496): Update PMD 7 Logo on landing page + * [#2497](https://github.com/pmd/pmd/issues/2497): PMD 7 Logo page + * [#2498](https://github.com/pmd/pmd/issues/2498): Update PMD 7 Logo in documentation + * [#3797](https://github.com/pmd/pmd/issues/3797): \[all] Use JUnit5 + * [#4462](https://github.com/pmd/pmd/issues/4462): Provide Software Bill of Materials (SBOM) +* ant + * [#4080](https://github.com/pmd/pmd/issues/4080): \[ant] Split off Ant integration into a new submodule +* core + * [#880](https://github.com/pmd/pmd/issues/880): \[core] Make visitors generic + * [#1622](https://github.com/pmd/pmd/pull/1622): \[core] NodeStream API + * [#1687](https://github.com/pmd/pmd/issues/1687): \[core] Deprecate and Remove XPath 1.0 support + * [#1785](https://github.com/pmd/pmd/issues/1785): \[core] Allow abstract node types to be valid rulechain visits + * [#1825](https://github.com/pmd/pmd/pull/1825): \[core] Support NoAttribute for XPath + * [#2038](https://github.com/pmd/pmd/issues/2038): \[core] Remove DCD + * [#2218](https://github.com/pmd/pmd/issues/2218): \[core] `isFindBoundary` should not be an attribute + * [#2234](https://github.com/pmd/pmd/issues/2234): \[core] Consolidate PMD CLI into a single command + * [#2239](https://github.com/pmd/pmd/issues/2239): \[core] Merging Javacc build scripts + * [#2500](https://github.com/pmd/pmd/issues/2500): \[core] Clarify API for ANTLR based languages + * [#2518](https://github.com/pmd/pmd/issues/2518): \[core] Language properties + * [#2602](https://github.com/pmd/pmd/issues/2602): \[core] Remove ParserOptions + * [#2614](https://github.com/pmd/pmd/pull/2614): \[core] Upgrade Saxon, add XPath 3.1, remove Jaxen + * [#2696](https://github.com/pmd/pmd/pull/2696): \[core] Remove DFA + * [#2821](https://github.com/pmd/pmd/issues/2821): \[core] Rule processing error filenames are missing paths + * [#2873](https://github.com/pmd/pmd/issues/2873): \[core] Utility classes in pmd 7 + * [#2885](https://github.com/pmd/pmd/issues/2885): \[core] Error recovery mode + * [#3203](https://github.com/pmd/pmd/issues/3203): \[core] Replace RuleViolationFactory implementations with ViolationDecorator + * [#3692](https://github.com/pmd/pmd/pull/3692): \[core] Analysis listeners + * [#3782](https://github.com/pmd/pmd/issues/3782): \[core] Language lifecycle + * [#3815](https://github.com/pmd/pmd/issues/3815): \[core] Update Saxon HE to 10.7 + * [#3893](https://github.com/pmd/pmd/pull/3893): \[core] Text documents + * [#3902](https://github.com/pmd/pmd/issues/3902): \[core] Violation decorators + * [#3918](https://github.com/pmd/pmd/issues/3918): \[core] Make LanguageRegistry non static + * [#3922](https://github.com/pmd/pmd/pull/3922): \[core] Better error reporting for the ruleset parser + * [#4035](https://github.com/pmd/pmd/issues/4035): \[core] ConcurrentModificationException in DefaultRuleViolationFactory + * [#4120](https://github.com/pmd/pmd/issues/4120): \[core] Explicitly name all language versions + * [#4353](https://github.com/pmd/pmd/pull/4353): \[core] Micro optimizations for Node API + * [#4365](https://github.com/pmd/pmd/pull/4365): \[core] Improve benchmarking + * [#4420](https://github.com/pmd/pmd/pull/4420): \[core] Remove PMD.EOL +* cli + * [#2234](https://github.com/pmd/pmd/issues/2234): \[core] Consolidate PMD CLI into a single command + * [#3828](https://github.com/pmd/pmd/issues/3828): \[core] Progress reporting + * [#4079](https://github.com/pmd/pmd/issues/4079): \[cli] Split off CLI implementation into a pmd-cli submodule + * [#4482](https://github.com/pmd/pmd/issues/4482): \[cli] pmd.bat can only be executed once + * [#4484](https://github.com/pmd/pmd/issues/4484): \[cli] ast-dump with no properties produce an NPE +* doc + * [#2501](https://github.com/pmd/pmd/issues/2501): \[doc] Verify ANTLR Documentation + * [#4438](https://github.com/pmd/pmd/issues/4438): \[doc] Documentation links in VS Code are outdated +* testing + * [#2435](https://github.com/pmd/pmd/issues/2435): \[test] Remove duplicated Dummy language module + * [#4234](https://github.com/pmd/pmd/issues/4234): \[test] Tests that change the logging level do not work + +Language specific fixes: + +* apex + * [#1937](https://github.com/pmd/pmd/issues/1937): \[apex] Apex should only have a single RootNode + * [#1648](https://github.com/pmd/pmd/issues/1648): \[apex,vf] Remove CodeClimate dependency + * [#1750](https://github.com/pmd/pmd/pull/1750): \[apex] Remove apex statistical rules + * [#2836](https://github.com/pmd/pmd/pull/2836): \[apex] Remove Apex ProjectMirror + * [#4427](https://github.com/pmd/pmd/issues/4427): \[apex] ApexBadCrypto test failing to detect inline code +* apex-design + * [#2667](https://github.com/pmd/pmd/issues/2667): \[apex] Integrate nawforce/ApexLink to build robust Unused rule + * [#4509](https://github.com/pmd/pmd/issues/4509): \[apex] ExcessivePublicCount doesn't consider inner classes correctly +* java + * [#520](https://github.com/pmd/pmd/issues/520): \[java] Allow `@SuppressWarnings` with constants instead of literals + * [#864](https://github.com/pmd/pmd/issues/864): \[java] Similar/duplicated implementations for determining FQCN + * [#905](https://github.com/pmd/pmd/issues/905): \[java] Add new node for anonymous class declaration + * [#910](https://github.com/pmd/pmd/issues/910): \[java] AST inconsistency between primitive and reference type arrays + * [#997](https://github.com/pmd/pmd/issues/997): \[java] Java8 parsing corner case with annotated array types + * [#998](https://github.com/pmd/pmd/issues/998): \[java] AST inconsistencies around FormalParameter + * [#1019](https://github.com/pmd/pmd/issues/1019): \[java] Breaking Java Grammar changes for PMD 7.0.0 + * [#1124](https://github.com/pmd/pmd/issues/1124): \[java] ImmutableList implementation in the qname codebase + * [#1128](https://github.com/pmd/pmd/issues/1128): \[java] Improve ASTLocalVariableDeclaration + * [#1150](https://github.com/pmd/pmd/issues/1150): \[java] ClassOrInterfaceType AST improvements + * [#1207](https://github.com/pmd/pmd/issues/1207): \[java] Resolve explicit types using FQCNs, without hitting the classloader + * [#1367](https://github.com/pmd/pmd/issues/1367): \[java] Parsing error on annotated inner class + * [#1661](https://github.com/pmd/pmd/issues/1661): \[java] About operator nodes + * [#2366](https://github.com/pmd/pmd/pull/2366): \[java] Remove qualified names + * [#2819](https://github.com/pmd/pmd/issues/2819): \[java] GLB bugs in pmd 7 + * [#3642](https://github.com/pmd/pmd/issues/3642): \[java] Parse error on rare extra dimensions on method return type on annotation methods + * [#3763](https://github.com/pmd/pmd/issues/3763): \[java] Ambiguous reference error in valid code + * [#3749](https://github.com/pmd/pmd/issues/3749): \[java] Improve `isOverridden` in ASTMethodDeclaration + * [#3750](https://github.com/pmd/pmd/issues/3750): \[java] Make symbol table support instanceof pattern bindings + * [#3752](https://github.com/pmd/pmd/issues/3752): \[java] Expose annotations in symbol API + * [#4237](https://github.com/pmd/pmd/pull/4237): \[java] Cleanup handling of Java comments + * [#4317](https://github.com/pmd/pmd/issues/4317): \[java] Some AST nodes should not be TypeNodes + * [#4359](https://github.com/pmd/pmd/issues/4359): \[java] Type resolution fails with NPE when the scope is not a type declaration + * [#4367](https://github.com/pmd/pmd/issues/4367): \[java] Move testrule TypeResTest into internal +* java-bestpractices + * [#342](https://github.com/pmd/pmd/issues/342): \[java] AccessorMethodGeneration: Name clash with another public field not properly handled + * [#755](https://github.com/pmd/pmd/issues/755): \[java] AccessorClassGeneration false positive for private constructors + * [#770](https://github.com/pmd/pmd/issues/770): \[java] UnusedPrivateMethod yields false positive for counter-variant arguments + * [#807](https://github.com/pmd/pmd/issues/807): \[java] AccessorMethodGeneration false positive with overloads + * [#833](https://github.com/pmd/pmd/issues/833): \[java] ForLoopCanBeForeach should consider iterating on this + * [#1189](https://github.com/pmd/pmd/issues/1189): \[java] UnusedPrivateMethod false positive from inner class via external class + * [#1205](https://github.com/pmd/pmd/issues/1205): \[java] Improve ConstantsInInterface message to mention alternatives + * [#1212](https://github.com/pmd/pmd/issues/1212): \[java] Don't raise JUnitTestContainsTooManyAsserts on JUnit 5's assertAll + * [#1422](https://github.com/pmd/pmd/issues/1422): \[java] JUnitTestsShouldIncludeAssert false positive with inherited @Rule field + * [#1455](https://github.com/pmd/pmd/issues/1455): \[java] JUnitTestsShouldIncludeAssert: False positives for assert methods named "check" and "verify" + * [#1563](https://github.com/pmd/pmd/issues/1563): \[java] ForLoopCanBeForeach false positive with method call using index variable + * [#1565](https://github.com/pmd/pmd/issues/1565): \[java] JUnitAssertionsShouldIncludeMessage false positive with AssertJ + * [#1747](https://github.com/pmd/pmd/issues/1747): \[java] PreserveStackTrace false-positive + * [#1969](https://github.com/pmd/pmd/issues/1969): \[java] MissingOverride false-positive triggered by package-private method overwritten in another package by extending class + * [#1998](https://github.com/pmd/pmd/issues/1998): \[java] AccessorClassGeneration false-negative: subclass calls private constructor + * [#2130](https://github.com/pmd/pmd/issues/2130): \[java] UnusedLocalVariable: false-negative with array + * [#2147](https://github.com/pmd/pmd/issues/2147): \[java] JUnitTestsShouldIncludeAssert - false positives with lambdas and static methods + * [#2464](https://github.com/pmd/pmd/issues/2464): \[java] LooseCoupling must ignore class literals: ArrayList.class + * [#2542](https://github.com/pmd/pmd/issues/2542): \[java] UseCollectionIsEmpty can not detect the case `foo.bar().size()` + * [#2650](https://github.com/pmd/pmd/issues/2650): \[java] UseTryWithResources false positive when AutoCloseable helper used + * [#2796](https://github.com/pmd/pmd/issues/2796): \[java] UnusedAssignment false positive with call chains + * [#2797](https://github.com/pmd/pmd/issues/2797): \[java] MissingOverride long-standing issues + * [#2806](https://github.com/pmd/pmd/issues/2806): \[java] SwitchStmtsShouldHaveDefault false-positive with Java 14 switch non-fallthrough branches + * [#2822](https://github.com/pmd/pmd/issues/2822): \[java] LooseCoupling rule: Extend to cover user defined implementations and interfaces + * [#2843](https://github.com/pmd/pmd/pull/2843): \[java] Fix UnusedAssignment FP with field accesses + * [#2882](https://github.com/pmd/pmd/issues/2882): \[java] UseTryWithResources - false negative for explicit close + * [#2883](https://github.com/pmd/pmd/issues/2883): \[java] JUnitAssertionsShouldIncludeMessage false positive with method call + * [#2890](https://github.com/pmd/pmd/issues/2890): \[java] UnusedPrivateMethod false positive with generics + * [#2946](https://github.com/pmd/pmd/issues/2946): \[java] SwitchStmtsShouldHaveDefault false positive on enum inside enums + * [#3672](https://github.com/pmd/pmd/pull/3672): \[java] LooseCoupling - fix false positive with generics + * [#3675](https://github.com/pmd/pmd/pull/3675): \[java] MissingOverride - fix false positive with mixing type vars + * [#3858](https://github.com/pmd/pmd/issues/3858): \[java] UseCollectionIsEmpty should infer local variable type from method invocation + * [#4516](https://github.com/pmd/pmd/issues/4516): \[java] UnusedLocalVariable: false-negative with try-with-resources + * [#4517](https://github.com/pmd/pmd/issues/4517): \[java] UnusedLocalVariable: false-negative with compound assignments + * [#4518](https://github.com/pmd/pmd/issues/4518): \[java] UnusedLocalVariable: false-positive with multiple for-loop indices +* java-codestyle + * [#1208](https://github.com/pmd/pmd/issues/1208): \[java] PrematureDeclaration rule false-positive on variable declared to measure time + * [#1429](https://github.com/pmd/pmd/issues/1429): \[java] PrematureDeclaration as result of method call (false positive) + * [#1480](https://github.com/pmd/pmd/issues/1480): \[java] IdenticalCatchBranches false positive with return expressions + * [#1673](https://github.com/pmd/pmd/issues/1673): \[java] UselessParentheses false positive with conditional operator + * [#1790](https://github.com/pmd/pmd/issues/1790): \[java] UnnecessaryFullyQualifiedName false positive with enum constant + * [#1918](https://github.com/pmd/pmd/issues/1918): \[java] UselessParentheses false positive with boolean operators + * [#2134](https://github.com/pmd/pmd/issues/2134): \[java] PreserveStackTrace not handling `Throwable.addSuppressed(...)` + * [#2299](https://github.com/pmd/pmd/issues/2299): \[java] UnnecessaryFullyQualifiedName false positive with similar package name + * [#2391](https://github.com/pmd/pmd/issues/2391): \[java] UseDiamondOperator FP when expected type and constructed type have a different parameterization + * [#2528](https://github.com/pmd/pmd/issues/2528): \[java] MethodNamingConventions - JUnit 5 method naming not support ParameterizedTest + * [#2739](https://github.com/pmd/pmd/issues/2739): \[java] UselessParentheses false positive for string concatenation + * [#2748](https://github.com/pmd/pmd/issues/2748): \[java] UnnecessaryCast false positive with unchecked cast + * [#2973](https://github.com/pmd/pmd/issues/2973): \[java] New rule: UnnecessaryBoxing + * [#3195](https://github.com/pmd/pmd/pull/3195): \[java] Improve rule UnnecessaryReturn to detect more cases + * [#3218](https://github.com/pmd/pmd/pull/3218): \[java] Generalize UnnecessaryCast to flag all unnecessary casts + * [#3221](https://github.com/pmd/pmd/issues/3221): \[java] PrematureDeclaration false positive for unused variables + * [#3238](https://github.com/pmd/pmd/issues/3238): \[java] Improve ExprContext, fix FNs of UnnecessaryCast + * [#3500](https://github.com/pmd/pmd/pull/3500): \[java] UnnecessaryBoxing - check for Integer.valueOf(String) calls + * [#4273](https://github.com/pmd/pmd/issues/4273): \[java] CommentDefaultAccessModifier ignoredAnnotations should include "org.junit.jupiter.api.extension.RegisterExtension" by default + * [#4357](https://github.com/pmd/pmd/pull/4357): \[java] Fix IllegalStateException in UseDiamondOperator rule + * [#4487](https://github.com/pmd/pmd/issues/4487): \[java] UnnecessaryConstructor: false-positive with @Inject and @Autowired + * [#4511](https://github.com/pmd/pmd/issues/4511): \[java] LocalVariableCouldBeFinal shouldn't report unused variables + * [#4512](https://github.com/pmd/pmd/issues/4512): \[java] MethodArgumentCouldBeFinal shouldn't report unused parameters +* java-design + * [#1014](https://github.com/pmd/pmd/issues/1014): \[java] LawOfDemeter: False positive with lambda expression + * [#1605](https://github.com/pmd/pmd/issues/1605): \[java] LawOfDemeter: False positive for standard UTF-8 charset name + * [#2160](https://github.com/pmd/pmd/issues/2160): \[java] Issues with Law of Demeter + * [#2175](https://github.com/pmd/pmd/issues/2175): \[java] LawOfDemeter: False positive for chained methods with generic method call + * [#2179](https://github.com/pmd/pmd/issues/2179): \[java] LawOfDemeter: False positive with static property access - should treat class-level property as global object, not dot-accessed property + * [#2180](https://github.com/pmd/pmd/issues/2180): \[java] LawOfDemeter: False positive with Thread and ThreadLocalRandom + * [#2182](https://github.com/pmd/pmd/issues/2182): \[java] LawOfDemeter: False positive with package-private access + * [#2188](https://github.com/pmd/pmd/issues/2188): \[java] LawOfDemeter: False positive with fields assigned to local vars + * [#2536](https://github.com/pmd/pmd/issues/2536): \[java] ClassWithOnlyPrivateConstructorsShouldBeFinal can't detect inner class + * [#3668](https://github.com/pmd/pmd/pull/3668): \[java] ClassWithOnlyPrivateConstructorsShouldBeFinal - fix FP with inner private classes + * [#3754](https://github.com/pmd/pmd/issues/3754): \[java] SingularField false positive with read in while condition + * [#3786](https://github.com/pmd/pmd/issues/3786): \[java] SimplifyBooleanReturns should consider operator precedence + * [#4238](https://github.com/pmd/pmd/pull/4238): \[java] Make LawOfDemeter not use the rulechain + * [#4254](https://github.com/pmd/pmd/issues/4254): \[java] ImmutableField - false positive with Lombok @Setter + * [#4477](https://github.com/pmd/pmd/issues/4477): \[java] SignatureDeclareThrowsException: false-positive with TestNG annotations + * [#4490](https://github.com/pmd/pmd/issues/4490): \[java] ImmutableField - false negative with Lombok @Getter +* java-documentation + * [#4369](https://github.com/pmd/pmd/pull/4369): \[java] Improve CommentSize + * [#4416](https://github.com/pmd/pmd/pull/4416): \[java] Fix reported line number in CommentContentRule +* java-errorprone + * [#659](https://github.com/pmd/pmd/issues/659): \[java] MissingBreakInSwitch - last default case does not contain a break + * [#1005](https://github.com/pmd/pmd/issues/1005): \[java] CloneMethodMustImplementCloneable triggers for interfaces + * [#1669](https://github.com/pmd/pmd/issues/1669): \[java] NullAssignment - FP with ternay and null as constructor argument + * [#1899](https://github.com/pmd/pmd/issues/1899): \[java] Recognize @SuppressWanings("fallthrough") for MissingBreakInSwitch + * [#2320](https://github.com/pmd/pmd/issues/2320): \[java] NullAssignment - FP with ternary and null as method argument + * [#2532](https://github.com/pmd/pmd/issues/2532): \[java] AvoidDecimalLiteralsInBigDecimalConstructor can not detect the case `new BigDecimal(Expression)` + * [#2579](https://github.com/pmd/pmd/issues/2579): \[java] MissingBreakInSwitch detects the lack of break in the last case + * [#2880](https://github.com/pmd/pmd/issues/2880): \[java] CompareObjectsWithEquals - false negative with type res + * [#2893](https://github.com/pmd/pmd/issues/2893): \[java] Remove special cases from rule EmptyCatchBlock + * [#2894](https://github.com/pmd/pmd/issues/2894): \[java] Improve MissingBreakInSwitch + * [#3071](https://github.com/pmd/pmd/issues/3071): \[java] BrokenNullCheck FP with PMD 6.30.0 + * [#3087](https://github.com/pmd/pmd/issues/3087): \[java] UnnecessaryBooleanAssertion overlaps with SimplifiableTestAssertion + * [#3100](https://github.com/pmd/pmd/issues/3100): \[java] UseCorrectExceptionLogging FP in 6.31.0 + * [#3173](https://github.com/pmd/pmd/issues/3173): \[java] UseProperClassLoader false positive + * [#3351](https://github.com/pmd/pmd/issues/3351): \[java] ConstructorCallsOverridableMethod ignores abstract methods + * [#3400](https://github.com/pmd/pmd/issues/3400): \[java] AvoidUsingOctalValues FN with underscores + * [#3843](https://github.com/pmd/pmd/issues/3843): \[java] UseEqualsToCompareStrings should consider return type + * [#4356](https://github.com/pmd/pmd/pull/4356): \[java] Fix NPE in CloseResourceRule + * [#4449](https://github.com/pmd/pmd/issues/4449): \[java] AvoidAccessibilityAlteration: Possible false positive in AvoidAccessibilityAlteration rule when using Lambda expression + * [#4493](https://github.com/pmd/pmd/issues/4493): \[java] MissingStaticMethodInNonInstantiatableClass: false-positive about @Inject + * [#4505](https://github.com/pmd/pmd/issues/4505): \[java] ImplicitSwitchFallThrough NPE in PMD 7.0.0-rc1 + * [#4513](https://github.com/pmd/pmd/issues/4513): \[java] UselessOperationOnImmutable various false negatives with String + * [#4514](https://github.com/pmd/pmd/issues/4514): \[java] AvoidLiteralsInIfCondition false positive and negative for String literals when ignoreExpressions=true +* java-multithreading + * [#2537](https://github.com/pmd/pmd/issues/2537): \[java] DontCallThreadRun can't detect the case that call run() in `this.run()` + * [#2538](https://github.com/pmd/pmd/issues/2538): \[java] DontCallThreadRun can't detect the case that call run() in `foo.bar.run()` + * [#2577](https://github.com/pmd/pmd/issues/2577): \[java] UseNotifyAllInsteadOfNotify falsely detect a special case with argument: `foo.notify(bar)` + * [#4483](https://github.com/pmd/pmd/issues/4483): \[java] NonThreadSafeSingleton false positive with double-checked locking +* java-performance + * [#1224](https://github.com/pmd/pmd/issues/1224): \[java] InefficientEmptyStringCheck false negative in anonymous class + * [#2587](https://github.com/pmd/pmd/issues/2587): \[java] AvoidArrayLoops could also check for list copy through iterated List.add() + * [#2712](https://github.com/pmd/pmd/issues/2712): \[java] SimplifyStartsWith false-positive with AssertJ + * [#3486](https://github.com/pmd/pmd/pull/3486): \[java] InsufficientStringBufferDeclaration: Fix NPE + * [#3848](https://github.com/pmd/pmd/issues/3848): \[java] StringInstantiation: false negative when using method result +* kotlin + * [#419](https://github.com/pmd/pmd/issues/419): \[kotlin] Add support for Kotlin + * [#4389](https://github.com/pmd/pmd/pull/4389): \[kotlin] Update grammar to version 1.8 +* swift + * [#1877](https://github.com/pmd/pmd/pull/1877): \[swift] Feature/swift rules + * [#1882](https://github.com/pmd/pmd/pull/1882): \[swift] UnavailableFunction Swift rule +* xml + * [#1800](https://github.com/pmd/pmd/pull/1800): \[xml] Unimplement org.w3c.dom.Node from the XmlNodeWrapper + +### ✨ External Contributions + +* [#1658](https://github.com/pmd/pmd/pull/1658): \[core] Node support for Antlr-based languages - [Matías Fraga](https://github.com/matifraga) (@matifraga) +* [#1698](https://github.com/pmd/pmd/pull/1698): \[core] [swift] Antlr Base Parser adapter and Swift Implementation - [Lucas Soncini](https://github.com/lsoncini) (@lsoncini) +* [#1774](https://github.com/pmd/pmd/pull/1774): \[core] Antlr visitor rules - [Lucas Soncini](https://github.com/lsoncini) (@lsoncini) +* [#1877](https://github.com/pmd/pmd/pull/1877): \[swift] Feature/swift rules - [Matías Fraga](https://github.com/matifraga) (@matifraga) +* [#1881](https://github.com/pmd/pmd/pull/1881): \[doc] Add ANTLR documentation - [Matías Fraga](https://github.com/matifraga) (@matifraga) +* [#1882](https://github.com/pmd/pmd/pull/1882): \[swift] UnavailableFunction Swift rule - [Tomás de Lucca](https://github.com/tomidelucca) (@tomidelucca) +* [#2830](https://github.com/pmd/pmd/pull/2830): \[apex] Apexlink POC - [Kevin Jones](https://github.com/nawforce) (@nawforce) +* [#3866](https://github.com/pmd/pmd/pull/3866): \[core] Add CLI Progress Bar - [@JerritEic](https://github.com/JerritEic) (@JerritEic) +* [#4402](https://github.com/pmd/pmd/pull/4402): \[javascript] CPD: add support for Typescript using antlr4 grammar - [Paul Guyot](https://github.com/pguyot) (@pguyot) +* [#4403](https://github.com/pmd/pmd/pull/4403): \[julia] CPD: Add support for Julia code duplication - [Wener](https://github.com/wener-tiobe) (@wener-tiobe) +* [#4412](https://github.com/pmd/pmd/pull/4412): \[doc] Added new error msg to ConstantsInInterface - [David Ljunggren](https://github.com/dague1) (@dague1) +* [#4428](https://github.com/pmd/pmd/pull/4428): \[apex] ApexBadCrypto bug fix for #4427 - inline detection of hard coded values - [Steven Stearns](https://github.com/sfdcsteve) (@sfdcsteve) +* [#4444](https://github.com/pmd/pmd/pull/4444): \[java] CommentDefaultAccessModifier - ignore org.junit.jupiter.api.extension.RegisterExtension by default - [Nirvik Patel](https://github.com/nirvikpatel) (@nirvikpatel) +* [#4450](https://github.com/pmd/pmd/pull/4450): \[java] Fix #4449 AvoidAccessibilityAlteration: Correctly handle Lambda expressions in PrivilegedAction scenarios - [Seren](https://github.com/mohui1999) (@mohui1999) +* [#4452](https://github.com/pmd/pmd/pull/4452): \[doc] Update PMD_APEX_ROOT_DIRECTORY documentation reference - [nwcm](https://github.com/nwcm) (@nwcm) +* [#4474](https://github.com/pmd/pmd/pull/4474): \[java] ImmutableField: False positive with lombok (fixes #4254) - [Pim van der Loos](https://github.com/PimvanderLoos) (@PimvanderLoos) +* [#4488](https://github.com/pmd/pmd/pull/4488): \[java] Fix #4477: A false-positive about SignatureDeclareThrowsException - [AnnaDev](https://github.com/LynnBroe) (@LynnBroe) +* [#4494](https://github.com/pmd/pmd/pull/4494): \[java] Fix #4487: A false-positive about UnnecessaryConstructor and @Inject and @Autowired - [AnnaDev](https://github.com/LynnBroe) (@LynnBroe) +* [#4495](https://github.com/pmd/pmd/pull/4495): \[java] Fix #4493: false-positive about MissingStaticMethodInNonInstantiatableClass and @Inject - [AnnaDev](https://github.com/LynnBroe) (@LynnBroe) +* [#4520](https://github.com/pmd/pmd/pull/4520): \[doc] Fix typo: missing closing quotation mark after CPD-END - [João Dinis Ferreira](https://github.com/joaodinissf) (@joaodinissf) + +### 📈 Stats +* 4557 commits +* 572 closed tickets & PRs +* Days since last release: 35 + + + ## 25-March-2023 - 7.0.0-rc1 We're excited to bring you the next major version of PMD! Since this is a big release, we provide here only a concise version of the release notes. We prepared a separate -page with the full [Detailed Release Notes for PMD 7.0.0](https://pmd.github.io/pmd-7.0.0-rc1/pmd_release_notes_pmd7.html). +page with the full [Detailed Release Notes for PMD 7.0.0](https://docs.pmd-code.org/pmd-doc-7.0.0-rc1/pmd_release_notes_pmd7.html).
ℹ️ Release Candidates @@ -57,7 +682,7 @@ for all.

The new official logo of PMD: -![New PMD Logo](https://pmd.github.io/pmd-7.0.0-rc1/images/logo/pmd-logo-300px.png) +![New PMD Logo](https://docs.pmd-code.org/pmd-doc-7.0.0-rc1/images/logo/pmd-logo-300px.png) #### Revamped Java module @@ -82,7 +707,7 @@ Contributors: [Clément Fournier](https://github.com/oowekyala) (@oowekyala), * progress bar support for `pmd check` * shell completion -![Demo](https://pmd.github.io/pmd-7.0.0-rc1/images/userdocs/pmd-demo.gif) +![Demo](https://docs.pmd-code.org/pmd-doc-7.0.0-rc1/images/userdocs/pmd-demo.gif) For more information, see the [Detailed Release Notes for PMD 7](pmd_release_notes_pmd7.html). @@ -136,46 +761,46 @@ Contributors: [Lucas Soncini](https://github.com/lsoncini) (@lsoncini), #### New Rules **Apex** -* [`UnusedMethod`](https://pmd.github.io/pmd-7.0.0-rc1/pmd_rules_apex_design.html#unusedmethod) finds unused methods in your code. +* [`UnusedMethod`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc1/pmd_rules_apex_design.html#unusedmethod) finds unused methods in your code. **Java** -* [`UnnecessaryBoxing`](https://pmd.github.io/pmd-7.0.0-rc1/pmd_rules_java_codestyle.html#unnecessaryboxing) reports boxing and unboxing conversions that may be made implicit. +* [`UnnecessaryBoxing`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc1/pmd_rules_java_codestyle.html#unnecessaryboxing) reports boxing and unboxing conversions that may be made implicit. **Kotlin** -* [`FunctionNameTooShort`](https://pmd.github.io/pmd-7.0.0-rc1/pmd_rules_kotlin_bestpractices.html#functionnametooshort) -* [`OverrideBothEqualsAndHashcode`](https://pmd.github.io/pmd-7.0.0-rc1/pmd_rules_kotlin_errorprone.html#overridebothequalsandhashcode) +* [`FunctionNameTooShort`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc1/pmd_rules_kotlin_bestpractices.html#functionnametooshort) +* [`OverrideBothEqualsAndHashcode`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc1/pmd_rules_kotlin_errorprone.html#overridebothequalsandhashcode) **Swift** -* [`ProhibitedInterfaceBuilder`](https://pmd.github.io/pmd-7.0.0-rc1/pmd_rules_swift_bestpractices.html#prohibitedinterfacebuilder) -* [`UnavailableFunction`](https://pmd.github.io/pmd-7.0.0-rc1/pmd_rules_swift_bestpractices.html#unavailablefunction) -* [`ForceCast`](https://pmd.github.io/pmd-7.0.0-rc1/pmd_rules_swift_errorprone.html#forcecast) -* [`ForceTry`](https://pmd.github.io/pmd-7.0.0-rc1/pmd_rules_swift_errorprone.html#forcetry) +* [`ProhibitedInterfaceBuilder`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc1/pmd_rules_swift_bestpractices.html#prohibitedinterfacebuilder) +* [`UnavailableFunction`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc1/pmd_rules_swift_bestpractices.html#unavailablefunction) +* [`ForceCast`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc1/pmd_rules_swift_errorprone.html#forcecast) +* [`ForceTry`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc1/pmd_rules_swift_errorprone.html#forcetry) #### Changed Rules **Java** -* [`UnnecessaryFullyQualifiedName`](https://pmd.github.io/pmd-7.0.0-rc1/pmd_rules_java_codestyle.html#unnecessaryfullyqualifiedname): the rule has two new properties, +* [`UnnecessaryFullyQualifiedName`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc1/pmd_rules_java_codestyle.html#unnecessaryfullyqualifiedname): the rule has two new properties, to selectively disable reporting on static field and method qualifiers. The rule also has been improved to be more precise. -* [`UselessParentheses`](https://pmd.github.io/pmd-7.0.0-rc1/pmd_rules_java_codestyle.html#uselessparentheses): the rule has two new properties which control how strict +* [`UselessParentheses`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc1/pmd_rules_java_codestyle.html#uselessparentheses): the rule has two new properties which control how strict the rule should be applied. With `ignoreClarifying` (default: true) parentheses that are strictly speaking not necessary are allowed, if they separate expressions of different precedence. The other property `ignoreBalancing` (default: true) is similar, in that it allows parentheses that help reading and understanding the expressions. -* [`LooseCoupling`](https://pmd.github.io/pmd-7.0.0-rc1/pmd_rules_java_bestpractices.html#loosecoupling): the rule has a new property to allow some types to be coupled +* [`LooseCoupling`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc1/pmd_rules_java_bestpractices.html#loosecoupling): the rule has a new property to allow some types to be coupled to (`allowedTypes`). -* [`EmptyCatchBlock`](https://pmd.github.io/pmd-7.0.0-rc1/pmd_rules_java_errorprone.html#emptycatchblock): `CloneNotSupportedException` and `InterruptedException` are not +* [`EmptyCatchBlock`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc1/pmd_rules_java_errorprone.html#emptycatchblock): `CloneNotSupportedException` and `InterruptedException` are not special-cased anymore. Rename the exception parameter to `ignored` to ignore them. -* [`DontImportSun`](https://pmd.github.io/pmd-7.0.0-rc1/pmd_rules_java_errorprone.html#dontimportsun): `sun.misc.Signal` is not special-cased anymore. -* [`UseDiamondOperator`](https://pmd.github.io/pmd-7.0.0-rc1/pmd_rules_java_codestyle.html#usediamondoperator): the property `java7Compatibility` is removed. The rule now +* [`DontImportSun`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc1/pmd_rules_java_errorprone.html#dontimportsun): `sun.misc.Signal` is not special-cased anymore. +* [`UseDiamondOperator`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc1/pmd_rules_java_codestyle.html#usediamondoperator): the property `java7Compatibility` is removed. The rule now handles Java 7 properly without a property. -* [`SingularField`](https://pmd.github.io/pmd-7.0.0-rc1/pmd_rules_java_design.html#singularfield): Properties `checkInnerClasses` and `disallowNotAssignment` are removed. +* [`SingularField`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc1/pmd_rules_java_design.html#singularfield): Properties `checkInnerClasses` and `disallowNotAssignment` are removed. The rule is now more precise and will check these cases properly. -* [`UseUtilityClass`](https://pmd.github.io/pmd-7.0.0-rc1/pmd_rules_java_design.html#useutilityclass): The property `ignoredAnnotations` has been removed. -* [`LawOfDemeter`](https://pmd.github.io/pmd-7.0.0-rc1/pmd_rules_java_design.html#lawofdemeter): the rule has a new property `trustRadius`. This defines the maximum degree +* [`UseUtilityClass`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc1/pmd_rules_java_design.html#useutilityclass): The property `ignoredAnnotations` has been removed. +* [`LawOfDemeter`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc1/pmd_rules_java_design.html#lawofdemeter): the rule has a new property `trustRadius`. This defines the maximum degree of trusted data. The default of 1 is the most restrictive. -* [`CommentContent`](https://pmd.github.io/pmd-7.0.0-rc1/pmd_rules_java_documentation.html#commentcontent): The properties `caseSensitive` and `disallowedTerms` are removed. The +* [`CommentContent`](https://docs.pmd-code.org/pmd-doc-7.0.0-rc1/pmd_rules_java_documentation.html#commentcontent): The properties `caseSensitive` and `disallowedTerms` are removed. The new property `fobiddenRegex` can be used now to define the disallowed terms with a single regular expression. @@ -453,6 +1078,7 @@ version `20-preview`: ./run.sh pmd --use-version java-20-preview ... #### T-SQL support + Thanks to the contribution from [Paul Guyot](https://github.com/pguyot) PMD now has CPD support for T-SQL (Transact-SQL). diff --git a/docs/pages/release_notes_pmd7.md b/docs/pages/release_notes_pmd7.md index 9f74c26e59..9f69feb730 100644 --- a/docs/pages/release_notes_pmd7.md +++ b/docs/pages/release_notes_pmd7.md @@ -441,6 +441,18 @@ Contributors: [Lucas Soncini](https://github.com/lsoncini) (@lsoncini), [Matías Fraga](https://github.com/matifraga) (@matifraga), [Tomás De Lucca](https://github.com/tomidelucca) (@tomidelucca) +### Updated PMD Designer + +This PMD release ships a new version of the pmd-designer. +For the changes, see [PMD Designer Changelog](https://github.com/pmd/pmd-designer/releases/tag/7.0.0-rc1). + +#### New CPD report format cpdhtml-v2.xslt + +Thanks to @mohan-chinnappan-n a new CPD report format has been added which features a data table. +It uses an XSLT stylesheet to convert CPD's XML format into HTML. + +See [the example report](report-examples/cpdhtml-v2.html). + ## 🎉 Language Related Changes ### New: Swift support @@ -483,6 +495,28 @@ We are shipping the following rules: Contributors: [Jeroen Borgers](https://github.com/jborgers) (@jborgers), [Peter Paul Bakker](https://github.com/stokpop) (@stokpop) +### New: CPD support for TypeScript + +Thanks to a contribution, CPD now supports the TypeScript language. It is shipped +with the rest of the JavaScript support in the module `pmd-javascript`. + +Contributors: [Paul Guyot](https://github.com/pguyot) (@pguyot) + +### New: CPD support for Julia + +Thanks to a contribution, CPD now supports the Julia language. It is shipped +in the new module `pmd-julia`. + +Contributors: [Wener](https://github.com/wener-tiobe) (@wener-tiobe) + +### New: CPD support for Coco + +Thanks to a contribution, CPD now supports Coco, a modern programming language +designed specifically for building event-driven software. It is shipped in the new +module `pmd-coco`. + +Contributors: [Wener](https://github.com/wener-tiobe) (@wener-tiobe) + ### Changed: JavaScript support The JS specific parser options have been removed. The parser now always retains comments and uses version ES6. @@ -525,31 +559,116 @@ Related issue: [[core] Explicitly name all language versions (#4120)](https://gi ### Changed Rules -**Java** +**General changes** -* {% rule "java/codestyle/UnnecessaryFullyQualifiedName" %}: the rule has two new properties, +* All statistical rules (like ExcessiveClassLength, ExcessiveParameterList) have been simplified and unified. + The properties `topscore` and `sigma` have been removed. The property `minimum` is still there, however the type is not + a decimal number anymore but has been changed to an integer. This affects rules in the languages Apex, Java, PLSQL + and Velocity Template Language (vm): + * Apex: {% rule apex/design/ExcessiveClassLength %}, {% rule apex/design/ExcessiveParameterList %}, + {% rule apex/design/ExcessivePublicCount %}, {% rule apex/design/NcssConstructorCount %}, + {% rule apex/design/NcssMethodCount %}, {% rule apex/design/NcssTypeCount %} + * Java: {% rule java/design/ExcessiveImports %}, {% rule java/design/ExcessiveParameterList %}, + {% rule java/design/ExcessivePublicCount %}, {% rule java/design/SwitchDensity %} + * PLSQL: {% rule plsql/design/ExcessiveMethodLength %}, {% rule plsql/design/ExcessiveObjectLength %}, + {% rule plsql/design/ExcessivePackageBodyLength %}, {% rule plsql/design/ExcessivePackageSpecificationLength %}, + {% rule plsql/design/ExcessiveParameterList %}, {% rule plsql/design/ExcessiveTypeLength %}, + {% rule plsql/design/NcssMethodCount %}, {% rule plsql/design/NcssObjectCount %}, + {% rule plsql/design/NPathComplexity %} + * VM: {% rule vm/design/ExcessiveTemplateLength %} + +* The general property `violationSuppressXPath` which is available for all rules to + [suppress warnings](pmd_userdocs_suppressing_warnings.html) now uses XPath version 3.1 by default. + This version of the XPath language is mostly identical to XPath 2.0. In PMD 6, XPath 1.0 has been used. + If you upgrade from PMD 6, you need to verify your `violationSuppressXPath` properties. + +**Apex General changes** + +* The properties `cc_categories`, `cc_remediation_points_multiplier`, `cc_block_highlighting` have been removed + from all rules. These properties have been deprecated since PMD 6.13.0. + See [issue #1648](https://github.com/pmd/pmd/issues/1648) for more details. + +**Java General changes** + +* Violations reported on methods or classes previously reported the line range of the entire method + or class. With PMD 7.0.0, the reported location is now just the identifier of the method or class. + This affects various rules, e.g. {% rule java/design/CognitiveComplexity %}. + + The report location is controlled by the overrides of the method {% jdoc core::lang.ast.Node#getReportLocation() %} + in different node types. + + See [issue #4439](https://github.com/pmd/pmd/issues/4439) and [issue #730](https://github.com/pmd/pmd/issues/730) + for more details. + +**Java Best Practices** + +* {% rule java/bestpractices/ArrayIsStoredDirectly %}: Violations are now reported on the assignment and not + anymore on the formal parameter. The reported line numbers will probably move. +* {% rule java/bestpractices/AvoidReassigningLoopVariables %}: This rule might not report anymore all + reassignments of the control variable in for-loops when the property `forReassign` is set to `skip`. + See [issue #4500](https://github.com/pmd/pmd/issues/4500) for more details. +* {% rule java/bestpractices/LooseCoupling %}: The rule has a new property to allow some types to be coupled + to (`allowedTypes`). +* {% rule java/bestpractices/UnusedLocalVariable %}: This rule has some important false-negatives fixed + and finds many more cases now. For details see issues [#2130](https://github.com/pmd/pmd/issues/2130), + [#4516](https://github.com/pmd/pmd/issues/4516), and [#4517](https://github.com/pmd/pmd/issues/4517). + +**Java Codestyle** + +* {% rule java/codestyle/MethodNamingConventions %}: The property `checkNativeMethods` has been removed. The + property was deprecated since PMD 6.3.0. Use the property `nativePattern` to control whether native methods + should be considered or not. +* {% rule java/codestyle/ShortVariable %}: This rule now also reports short enum constant names. +* {% rule java/codestyle/UseDiamondOperator %}: The property `java7Compatibility` has been removed. The rule now + handles Java 7 properly without a property. +* {% rule java/codestyle/UnnecessaryFullyQualifiedName %}: The rule has two new properties, to selectively disable reporting on static field and method qualifiers. The rule also has been improved to be more precise. -* {% rule "java/codestyle/UselessParentheses" %}: the rule has two new properties which control how strict +* {% rule java/codestyle/UselessParentheses %}: The rule has two new properties which control how strict the rule should be applied. With `ignoreClarifying` (default: true) parentheses that are strictly speaking not necessary are allowed, if they separate expressions of different precedence. The other property `ignoreBalancing` (default: true) is similar, in that it allows parentheses that help reading and understanding the expressions. -* {% rule "java/bestpractices/LooseCoupling" %}: the rule has a new property to allow some types to be coupled - to (`allowedTypes`). -* {% rule "java/errorprone/EmptyCatchBlock" %}: `CloneNotSupportedException` and `InterruptedException` are not - special-cased anymore. Rename the exception parameter to `ignored` to ignore them. -* {% rule "java/errorprone/DontImportSun" %}: `sun.misc.Signal` is not special-cased anymore. -* {% rule "java/codestyle/UseDiamondOperator" %}: the property `java7Compatibility` is removed. The rule now - handles Java 7 properly without a property. -* {% rule "java/design/SingularField" %}: Properties `checkInnerClasses` and `disallowNotAssignment` are removed. - The rule is now more precise and will check these cases properly. -* {% rule "java/design/UseUtilityClass" %}: The property `ignoredAnnotations` has been removed. -* {% rule "java/design/LawOfDemeter" %}: the rule has a new property `trustRadius`. This defines the maximum degree + +**Java Design** + +* {% rule java/design/CyclomaticComplexity %}: The property `reportLevel` has been removed. The property was + deprecated since PMD 6.0.0. The report level can now be configured separated for classes and methods using + `classReportLevel` and `methodReportLevel` instead. +* {% rule java/design/ImmutableField %}: The property `ignoredAnnotations` has been removed. The property was + deprecated since PMD 6.52.0. +* {% rule java/design/LawOfDemeter %}: The rule has a new property `trustRadius`. This defines the maximum degree of trusted data. The default of 1 is the most restrictive. -* {% rule "java/documentation/CommentContent" %}: The properties `caseSensitive` and `disallowedTerms` are removed. The - new property `fobiddenRegex` can be used now to define the disallowed terms with a single regular +* {% rule java/design/NPathComplexity %}: The property `minimum` has been removed. It was deprecated since PMD 6.0.0. + Use the property `reportLevel` instead. +* {% rule java/design/SingularField %}: The properties `checkInnerClasses` and `disallowNotAssignment` have been removed. + The rule is now more precise and will check these cases properly. +* {% rule java/design/UseUtilityClass %}: The property `ignoredAnnotations` has been removed. + +**Java Documentation** + +* {% rule java/documentation/CommentContent %}: The properties `caseSensitive` and `disallowedTerms` are removed. The + new property `forbiddenRegex` can be used now to define the disallowed terms with a single regular expression. +* {% rule java/documentation/CommentRequired %}: + * Overridden methods are now detected even without the `@Override` + annotation. This is relevant for the property `methodWithOverrideCommentRequirement`. + See also [pull request #3757](https://github.com/pmd/pmd/pull/3757). + * Elements in annotation types are now detected as well. This might lead to an increased number of violations + for missing public method comments. +* {% rule java/documentation/CommentSize %}: When determining the line-length of a comment, the leading comment + prefix markers (e.g. `*` or `//`) are ignored and don't add up to the line-length. + See also [pull request #4369](https://github.com/pmd/pmd/pull/4369). + +**Java Error Prone** + +* {% rule java/errorprone/AvoidDuplicateLiterals %}: The property `exceptionfile` has been removed. The property was + deprecated since PMD 6.10.0. Use the property `exceptionList` instead. +* {% rule java/errorprone/DontImportSun %}: `sun.misc.Signal` is not special-cased anymore. +* {% rule java/errorprone/EmptyCatchBlock %}: `CloneNotSupportedException` and `InterruptedException` are not + special-cased anymore. Rename the exception parameter to `ignored` to ignore them. +* {% rule java/errorprone/ImplicitSwitchFallThrough %}: Violations are now reported on the case statements + rather than on the switch statements. This is more accurate but might result in more violations now. ### Deprecated Rules @@ -750,6 +869,13 @@ until the next major release, but it is recommended to stop using them. * {% jdoc core::util.IteratorUtil %} * {% jdoc core::util.StringUtil %} +* Moved the two classes {% jdoc core::cpd.impl.AntlrTokenizer %} and {% jdoc core::cpd.impl.JavaCCTokenizer %} from + `internal` package into package {% jdoc_package core::cpd.impl %}. These two classes are part of the API and + are base classes for CPD language implementations. Since 7.0.0-rc2. +* `AntlrBaseRule` is gone in favor of {% jdoc core::lang.rule.AbstractVisitorRule %}. Since 7.0.0-rc2. +* The classes {% jdoc kotlin::lang.kotlin.ast.KotlinInnerNode %} and {% jdoc swift::lang.swift.ast.SwiftInnerNode %} + are package-private now. Since 7.0.0-rc2. + ### XPath 3.1 support Support for XPath versions 1.0, 1.0-compatibility was removed, support for XPath 2.0 is deprecated. The default @@ -847,6 +973,15 @@ Related issue: [[core] Language lifecycle (#3782)](https://github.com/pmd/pmd/is ### API removals +#### 7.0.0-rc2 + +* The following previously deprecated classes have been removed: + * pmd-core + * `net.sourceforge.pmd.PMD` + * `net.sourceforge.pmd.cli.PMDCommandLineInterface` + * `net.sourceforge.pmd.cli.PMDParameters` + * `net.sourceforge.pmd.cli.PmdParametersParseResult` + #### 6.55.0 **Go** diff --git a/docs/report-examples/cpdhtml-v2.html b/docs/report-examples/cpdhtml-v2.html new file mode 100644 index 0000000000..0e3b43baf5 --- /dev/null +++ b/docs/report-examples/cpdhtml-v2.html @@ -0,0 +1,175 @@ + + + + + + + + + + + + +
+
+
+

Summary of duplicated code

+

This page summarizes the code fragments that have been found to be replicated in the code.

+ + + + + + + +
# DuplicationsTotal linesTotal tokensApproximate number of bytes
2493491396
+
+
+
+
+

Details of duplicated code

+
+ + + + + + + + + + + + + + +
linestokensfilescodefragment
33239 + + + + + + + + + + +
columnendcolumnlineendlinepath
29753264/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/RuleReferenceTest.java
377568100/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/RuleReferenceTest.java
+
+
    public void testOverride() {
+        final StringProperty PROPERTY1_DESCRIPTOR = new StringProperty("property1", "Test property", null, 0f);
+        MockRule rule = new MockRule();
+        rule.definePropertyDescriptor(PROPERTY1_DESCRIPTOR);
+        rule.setLanguage(LanguageRegistry.getLanguage(Dummy2LanguageModule.NAME));
+        rule.setName("name1");
+        rule.setProperty(PROPERTY1_DESCRIPTOR, "value1");
+        rule.setMessage("message1");
+        rule.setDescription("description1");
+        rule.addExample("example1");
+        rule.setExternalInfoUrl("externalInfoUrl1");
+        rule.setPriority(RulePriority.HIGH);
+
+        final StringProperty PROPERTY2_DESCRIPTOR = new StringProperty("property2", "Test property", null, 0f);
+        RuleReference ruleReference = new RuleReference();
+        ruleReference.setRule(rule);
+        ruleReference.definePropertyDescriptor(PROPERTY2_DESCRIPTOR);
+        ruleReference.setLanguage(LanguageRegistry.getLanguage(DummyLanguageModule.NAME));
+        ruleReference
+                .setMinimumLanguageVersion(LanguageRegistry.getLanguage(DummyLanguageModule.NAME).getVersion("1.3"));
+        ruleReference
+                .setMaximumLanguageVersion(LanguageRegistry.getLanguage(DummyLanguageModule.NAME).getVersion("1.7"));
+        ruleReference.setDeprecated(true);
+        ruleReference.setName("name2");
+        ruleReference.setProperty(PROPERTY1_DESCRIPTOR, "value2");
+        ruleReference.setProperty(PROPERTY2_DESCRIPTOR, "value3");
+        ruleReference.setMessage("message2");
+        ruleReference.setDescription("description2");
+        ruleReference.addExample("example2");
+        ruleReference.setExternalInfoUrl("externalInfoUrl2");
+        ruleReference.setPriority(RulePriority.MEDIUM_HIGH);
+
+        validateOverriddenValues(PROPERTY1_DESCRIPTOR, PROPERTY2_DESCRIPTOR, ruleReference);
+
16110 + + + + + + + + + + + + + +
columnendcolumnlineendlinepath
9286681/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/JaxenXPathRuleQueryTest.java
92888103/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/JaxenXPathRuleQueryTest.java
928110125/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/JaxenXPathRuleQueryTest.java
+
+
        JaxenXPathRuleQuery query = createQuery(xpath);
+        List<String> ruleChainVisits = query.getRuleChainVisits();
+        Assert.assertEquals(2, ruleChainVisits.size());
+        Assert.assertTrue(ruleChainVisits.contains("dummyNode"));
+        // Note: Having AST_ROOT in the rule chain visits is probably a mistake. But it doesn't hurt, it shouldn't
+        // match a real node name.
+        Assert.assertTrue(ruleChainVisits.contains(JaxenXPathRuleQuery.AST_ROOT));
+
+        DummyNodeWithListAndEnum dummy = new DummyNodeWithListAndEnum(1);
+        RuleContext data = new RuleContext();
+        data.setLanguageVersion(LanguageRegistry.findLanguageByTerseName("dummy").getDefaultVersion());
+
+        query.evaluate(dummy, data);
+        // note: the actual xpath queries are only available after evaluating
+        Assert.assertEquals(2, query.nodeNameToXPaths.size());
+        Assert.assertEquals("self::node()[(attribute::Test1 = \"false\")][(attribute::Test2 = \"true\")]", query.nodeNameToXPaths.get("dummyNode").get(0).toString());
+
+
+
+ + + diff --git a/docs/report-examples/cpdhtml.html b/docs/report-examples/cpdhtml.html new file mode 100644 index 0000000000..7cc527c602 --- /dev/null +++ b/docs/report-examples/cpdhtml.html @@ -0,0 +1,111 @@ + + + + + + + + + +

Summary of duplicated code

+ This page summarizes the code fragments that have been found to be replicated in the code. + Only those fragments longer than 30 lines of code are shown. +

+ + + + + + + +
# duplicationsTotal linesTotal tokensApprox # bytes
133239956
+

+ You expand and collapse the code fragments using the + buttons. You can also navigate to the source code by clicking + on the file names. +

+ + + + + + + + + + + + + +
IDFilesLines
1 + + + + + + + +
/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/RuleReferenceTest.java line 32
/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/RuleReferenceTest.java line 68
+
# lines : 33
+ + + + +
+
+
+
+ + diff --git a/docs/report-examples/pmd-report.sarif.json b/docs/report-examples/pmd-report.sarif.json index e785af258d..005c000c90 100644 --- a/docs/report-examples/pmd-report.sarif.json +++ b/docs/report-examples/pmd-report.sarif.json @@ -7,7 +7,7 @@ "driver": { "name": "PMD", "version": "", - "informationUri": "https://pmd.github.io/pmd/", + "informationUri": "https://docs.pmd-code.org/latest/", "rules": [ { "id": "ApexSharingViolations", @@ -17,7 +17,7 @@ "fullDescription": { "text": "Detect classes declared without explicit sharing mode if DML methods are used. This forces the developer to take access restrictions into account before modifying objects." }, - "helpUri": "https://pmd.github.io/pmd/pmd_rules_apex_security.html#apexsharingviolations", + "helpUri": "https://docs.pmd-code.org/latest/pmd_rules_apex_security.html#apexsharingviolations", "help": { "text": "Detect classes declared without explicit sharing mode if DML methods are used. This forces the developer to take access restrictions into account before modifying objects." }, @@ -37,7 +37,7 @@ "fullDescription": { "text": "This rule validates that: ApexDoc comments are present for classes, methods, and properties that are public or global, excluding overrides and test classes (as well as the contents of test classes)." }, - "helpUri": "https://pmd.github.io/pmd/pmd_rules_apex_documentation.html#apexdoc", + "helpUri": "https://docs.pmd-code.org/latest/pmd_rules_apex_documentation.html#apexdoc", "help": { "text": "This rule validates that: ApexDoc comments are present for classes, methods, and properties that are public or global, excluding overrides and test classes (as well as the contents of test classes)." }, @@ -152,4 +152,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/docs/sitemap.xml b/docs/sitemap.xml index 38a04d6c4e..5a1d7dc52e 100644 --- a/docs/sitemap.xml +++ b/docs/sitemap.xml @@ -1,24 +1,42 @@ --- layout: none search: exclude +# https://www.sitemaps.org/protocol.html +# Priority is relative to the website, can be chosen in {0.1, 0.2, ..., 1} +# Default priority is 0.5 +latestPriority: 0.8 --- + + {{site.url}}/index.html + 0.9 + monthly + {{ site.time | date: "%Y-%m-%d" }} + + + {% for post in site.posts %} {% unless post.search == "exclude" %} {{site.url}}{{post.url}} + {{page.latestPriority}} + monthly + {{ site.time | date: "%Y-%m-%d" }} {% endunless %} {% endfor %} - {% for page in site.pages %} - {% unless page.search == "exclude" %} + {% for p in site.pages %} + {% unless p.search == "exclude" %} - {{site.url}}{{ page.url}} + {{site.url}}{{ p.url}} + {{page.latestPriority}} + monthly + {{ site.time | date: "%Y-%m-%d" }} {% endunless %} {% endfor %} - \ No newline at end of file + diff --git a/docs/sitemap_generator.sh b/docs/sitemap_generator.sh deleted file mode 100755 index 03e25a0bcf..0000000000 --- a/docs/sitemap_generator.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env bash - -# Sitemap generator for pmd.github.io main landing page. -# Assumes we have the latest version of the site under "latest" -# https://www.sitemaps.org/protocol.html - -WEBSITE_PREFIX="https://pmd.github.io/" -DOC_PREFIX="latest/" -DATE=`date +%Y-%m-%d` -# Priority is relative to the website, can be chosen in {0.1, 0.2, ..., 1} -# Default priority is 0.5 -LATEST_PRIORITY=0.8 - - -# Writes to standard output - -cat << HEADER_END - - - - - ${WEBSITE_PREFIX}index.html - 1 - monthly - $DATE - - - - ${WEBSITE_PREFIX}${DOC_PREFIX}index.html - 0.9 - monthly - $DATE - - - - -HEADER_END - - -for page in ${DOC_PREFIX}pmd_*.html -do - - cat << ENTRY_END - - ${WEBSITE_PREFIX}$page - $LATEST_PRIORITY - monthly - $DATE - - -ENTRY_END - -done - -echo "" - diff --git a/pmd-ant/pom.xml b/pmd-ant/pom.xml index 7001eeddfc..26e41e525d 100644 --- a/pmd-ant/pom.xml +++ b/pmd-ant/pom.xml @@ -3,9 +3,7 @@ ~ BSD-style license; for more info see http://pmd.sourceforge.net/license.html --> - + pmd net.sourceforge.pmd diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/multifile/ApexMultifileAnalysis.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/multifile/ApexMultifileAnalysis.java index a9aebddf01..335fb06084 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/multifile/ApexMultifileAnalysis.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/multifile/ApexMultifileAnalysis.java @@ -71,7 +71,16 @@ public final class ApexMultifileAnalysis { // FIXME: Syntax & Semantic errors found during Org loading are not currently being reported. These // should be routed to the new SemanticErrorReporter but that is not available for use just yet. } - } catch (Exception e) { + } catch (Exception | ExceptionInInitializerError | NoClassDefFoundError e) { + // Note: Org.newOrg() will try to find the base Apex Types through the current classloader + // in package "com.nawforce.runforce". This requires, that directory listings can be retrievied + // on the URL that the classloader returns from getResource("/com/nawforce/runforce"): + // https://github.com/nawforce/apex-link/blob/7688adcb7a2d7f8aa28d0618ffb2a3aa81151858/apexlink/src/main/scala/com/nawforce/apexlink/types/platform/PlatformTypeDeclaration.scala#L260-L273 + // However, when running as an Eclipse plugin, we have a special bundle classloader, that returns + // URIs in the form "bundleresource://...". For the schema "bundleresource", no FileSystemProvider can be + // found, so we get a java.nio.file.ProviderNotFoundException. Since all this happens during initialization of the class + // com.nawforce.apexlink.types.platform.PlatformTypeDeclaration we get a ExceptionInInitializerError + // and later NoClassDefFoundErrors, because PlatformTypeDeclaration couldn't be loaded. LOG.error("Exception while initializing Apexlink ({})", e.getMessage(), e); LOG.error("PMD will not attempt to initialize Apexlink further, this can cause rules like UnusedMethod to be dysfunctional"); org = null; diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/ExcessivePublicCountRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/ExcessivePublicCountRule.java index 5be16d0783..b833424ced 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/ExcessivePublicCountRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/ExcessivePublicCountRule.java @@ -52,4 +52,8 @@ public class ExcessivePublicCountRule extends AbstractCounterCheckRule { protected boolean isIgnored(ASTMethod node) { return node.isConstructor(); } + + @Override + protected Object[] getViolationParameters(ASTMethod node, int metric, int limit) { + return new Object[]{ node.getImage(), metric, limit }; + } } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/internal/AbstractCounterCheckRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/internal/AbstractCounterCheckRule.java index 8e4ff77025..3879f3fd07 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/internal/AbstractCounterCheckRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/internal/AbstractCounterCheckRule.java @@ -48,9 +48,8 @@ public abstract class AbstractCounterCheckRule> extends Ab protected abstract int defaultReportLevel(); - - protected Object[] getViolationParameters(T node, int metric) { - return new Object[] {metric}; + protected Object[] getViolationParameters(T node, int metric, int limit) { + return new Object[] {metric, limit}; } @@ -70,8 +69,9 @@ public abstract class AbstractCounterCheckRule> extends Ab if (!isIgnored(t)) { int metric = getMetric(t); - if (metric >= getProperty(reportLevel)) { - addViolation(data, node, getViolationParameters(t, metric)); + int limit = getProperty(reportLevel); + if (metric >= limit) { + addViolation(data, node, getViolationParameters(t, metric, limit)); } } diff --git a/pmd-apex/src/main/resources/category/apex/design.xml b/pmd-apex/src/main/resources/category/apex/design.xml index 6f34471e41..808ceb08b7 100644 --- a/pmd-apex/src/main/resources/category/apex/design.xml +++ b/pmd-apex/src/main/resources/category/apex/design.xml @@ -48,13 +48,13 @@ Avoid having unused methods since they make understanding and maintaining code h This rule finds not only unused private methods, but public methods as well. [ApexLink](https://github.com/nawforce/ApexLink) is used to make this possible and this needs -additional configuration. The environment variable `PMD_APEX_ROOTDIRECTORY` needs to be set prior to executing +additional configuration. The environment variable `PMD_APEX_ROOT_DIRECTORY` needs to be set prior to executing PMD. With this variable the root directory of the Salesforce metadata, where `sfdx-project.json` resides, is specified. ApexLink can then load all the classes in the project and figure out, whether a method is used or not. -For an accurate analysis it is important that the `PMD_APEX_ROOTDIRECTORY` contains a complete set of metadata that +For an accurate analysis it is important that the `PMD_APEX_ROOT_DIRECTORY` contains a complete set of metadata that may be referenced from the Apex source code, such as Custom Objects, Visualforce Pages, Flows and Labels. The -`PMD_APEX_ROOTDIRECTORY` directory must contain a `sfdx-project.json`, but metadata may be either in the +`PMD_APEX_ROOT_DIRECTORY` directory must contain a `sfdx-project.json`, but metadata may be either in the [SFDX Source format](https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_source_file_format.htm) or the older MDAPI format. The `packageDirectories` entries in `sfdx-project.json` are used to determine which directories to search for metadata, if a `.forceignore` file is present it will be respected. @@ -281,7 +281,7 @@ public void addPerson(Date birthdate, BodyMeasurements measurements, int ssn) { @@ -340,7 +340,7 @@ public class Foo extends Bar { diff --git a/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/design/xml/ExcessivePublicCount.xml b/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/design/xml/ExcessivePublicCount.xml index 45e7fe4a93..e529fac558 100644 --- a/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/design/xml/ExcessivePublicCount.xml +++ b/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/design/xml/ExcessivePublicCount.xml @@ -113,4 +113,29 @@ public class SomeClass { } ]]> + + + #4509 class with inner classes + 1 + 2 + 1,5 + + The class OuterClass has 2 public methods and attributes (limit: 1) + The class InnerClass has 4 public methods and attributes (limit: 1) + + + diff --git a/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/design/xml/NcssMethodCount.xml b/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/design/xml/NcssMethodCount.xml index 6562dcb876..b278b7299b 100644 --- a/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/design/xml/NcssMethodCount.xml +++ b/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/design/xml/NcssMethodCount.xml @@ -70,6 +70,9 @@ public class Foo { long method 13 1 + + The method 'foo()' has an NCSS line count of 13 (limit: 13) + diff --git a/pmd-cli/pom.xml b/pmd-cli/pom.xml index 5d65824a77..2df635e272 100644 --- a/pmd-cli/pom.xml +++ b/pmd-cli/pom.xml @@ -38,7 +38,7 @@ -Dpicocli.autocomplete.systemExitOnError -cp - + picocli.AutoComplete --force --completionScript @@ -78,168 +78,15 @@ ${project.version} - - + net.sourceforge.pmd - pmd-apex - ${project.version} - runtime - - - net.sourceforge.pmd - pmd-cpp - ${project.version} - runtime - - - net.sourceforge.pmd - pmd-cs - ${project.version} - runtime - - - net.sourceforge.pmd - pmd-dart - ${project.version} - runtime - - - net.sourceforge.pmd - pmd-fortran - ${project.version} - runtime - - - net.sourceforge.pmd - pmd-gherkin - ${project.version} - runtime - - - net.sourceforge.pmd - pmd-go - ${project.version} - runtime - - - net.sourceforge.pmd - pmd-groovy - ${project.version} - runtime - - - net.sourceforge.pmd - pmd-html - ${project.version} - runtime - - - net.sourceforge.pmd - pmd-lua - ${project.version} - runtime - - - net.sourceforge.pmd - pmd-java - ${project.version} - runtime - - - net.sourceforge.pmd - pmd-javascript - ${project.version} - runtime - - - net.sourceforge.pmd - pmd-jsp - ${project.version} - runtime - - - net.sourceforge.pmd - pmd-kotlin - ${project.version} - runtime - - - net.sourceforge.pmd - pmd-matlab - ${project.version} - runtime - - - net.sourceforge.pmd - pmd-modelica - ${project.version} - runtime - - - net.sourceforge.pmd - pmd-perl - ${project.version} - runtime - - - net.sourceforge.pmd - pmd-objectivec - ${project.version} - runtime - - - net.sourceforge.pmd - pmd-php - ${project.version} - runtime - - - net.sourceforge.pmd - pmd-plsql - ${project.version} - runtime - - - net.sourceforge.pmd - pmd-python - ${project.version} - runtime - - - net.sourceforge.pmd - pmd-ruby - ${project.version} - runtime - - - net.sourceforge.pmd - pmd-scala_2.13 - ${project.version} - runtime - - - net.sourceforge.pmd - pmd-swift - ${project.version} - runtime - - - net.sourceforge.pmd - pmd-visualforce - ${project.version} - runtime - - - net.sourceforge.pmd - pmd-vm - ${project.version} - runtime - - - net.sourceforge.pmd - pmd-xml + pmd-languages-deps ${project.version} + pom runtime diff --git a/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/CpdCommand.java b/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/CpdCommand.java index daef0b559c..175ff84656 100644 --- a/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/CpdCommand.java +++ b/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/CpdCommand.java @@ -100,7 +100,6 @@ public class CpdCommand extends AbstractAnalysisPmdSubcommand { */ public CPDConfiguration toConfiguration() { final CPDConfiguration configuration = new CPDConfiguration(); - configuration.setDebug(debug); configuration.setExcludes(excludes); configuration.setFailOnViolation(failOnViolation); configuration.setFileListPath(fileListPath == null ? null : fileListPath.toString()); diff --git a/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/PmdCommand.java b/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/PmdCommand.java index 41472cff12..ac9f295265 100644 --- a/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/PmdCommand.java +++ b/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/PmdCommand.java @@ -282,7 +282,6 @@ public class PmdCommand extends AbstractAnalysisPmdSubcommand { configuration.setIgnoreFilePath(ignoreListPath); configuration.setInputUri(uri); configuration.setReportFormat(format); - configuration.setDebug(debug); configuration.setSourceEncoding(encoding.getEncoding().name()); configuration.setMinimumPriority(minimumPriority); configuration.setReportFile(reportFile); diff --git a/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/TreeExportCommand.java b/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/TreeExportCommand.java index c034682f07..f9733ec230 100644 --- a/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/TreeExportCommand.java +++ b/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/TreeExportCommand.java @@ -75,7 +75,7 @@ public class TreeExportCommand extends AbstractPmdSubcommand { @Option(names = "-P", description = "Key-value pair defining a property for the report format.%n" + "Supported values for each report format:%n${sys:pmd-cli.tree-export.report.properties.help}", completionCandidates = TreeExportReportPropertiesCandidates.class) - private Properties properties; + private Properties properties = new Properties(); @Option(names = "--file", description = "The file to parse and dump.") private Path file; @@ -85,7 +85,6 @@ public class TreeExportCommand extends AbstractPmdSubcommand { public TreeExportConfiguration toConfiguration() { final TreeExportConfiguration configuration = new TreeExportConfiguration(); - configuration.setDebug(debug); configuration.setFile(file); configuration.setFormat(format); configuration.setLanguage(language); diff --git a/pmd-coco/pom.xml b/pmd-coco/pom.xml new file mode 100644 index 0000000000..5350b5b8d3 --- /dev/null +++ b/pmd-coco/pom.xml @@ -0,0 +1,59 @@ + + + 4.0.0 + pmd-coco + PMD Coco + + + net.sourceforge.pmd + pmd + 7.0.0-SNAPSHOT + ../pom.xml + + + + + + org.antlr + antlr4-maven-plugin + + + + maven-resources-plugin + + false + + ${*} + + + + + + + + + net.sourceforge.pmd + pmd-core + + + org.antlr + antlr4-runtime + + + + org.junit.jupiter + junit-jupiter + test + + + net.sourceforge.pmd + pmd-test + test + + + net.sourceforge.pmd + pmd-lang-test + test + + + diff --git a/pmd-coco/src/main/antlr4/net/sourceforge/pmd/lang/coco/ast/Coco.g4 b/pmd-coco/src/main/antlr4/net/sourceforge/pmd/lang/coco/ast/Coco.g4 new file mode 100644 index 0000000000..32a867b8b2 --- /dev/null +++ b/pmd-coco/src/main/antlr4/net/sourceforge/pmd/lang/coco/ast/Coco.g4 @@ -0,0 +1,607 @@ +//////////////////////////////////////////////////////////////////////////////// +//// Coco 1.2 ANTLR4 grammar definition file +//// Reversed engineered by Dimitri van Heesch +/////////////////////////////////////////////////////////////////////////////// + +grammar Coco; + +module : (declaration)* EOF + ; + +declaration + : attribute* + ( importDeclaration + | variableDeclaration + | enumDeclaration + | structDeclaration + | typeAliasDeclaration + | functionDeclaration + | instanceDeclaration // COCOTEC: this is not documented. Also class declaration is mentioned and traits? + | portDeclaration + | componentDeclaration + | externalConstantDeclaration + | externalFunctionDeclaration + | externalTypeDeclaration + | attributeDeclaration // COCOTEC: this is not documented. + ) + ; + +attribute + : AT dotIdentifierList ( LP expressions RP )? + ; + +attributeDeclaration + : ATTRIBUTE AT dotIdentifierList ( LP parameters? RP )? + ; + +importDeclaration + : IMPORT UNQUALIFIED? dotIdentifierList (AS IDENTIFIER)? + ; + +variableDeclaration + : PRIVATE? (VAR | VAL) IDENTIFIER genericTypeDeclaration? (COLON type)? (ASSIGN expression)? + ; + +enumDeclaration + : ENUM IDENTIFIER genericTypeDeclaration? LC enumElement* RC + ; + +structDeclaration + : STRUCT IDENTIFIER genericTypeDeclaration? LC structElement* RC + ; + +typeAliasDeclaration + : TYPE IDENTIFIER genericTypeDeclaration? ASSIGN type + ; + +functionDeclaration + : FUNCTION IDENTIFIER genericTypeDeclaration? LP parameters? RP COLON type ASSIGN expression + ; + +instanceDeclaration + : INSTANCE IDENTIFIER genericTypeDeclaration? LP parameters RP blockExpression_ + ; + +portDeclaration + : PORT IDENTIFIER (COLON types)? FINAL? LC portElement* RC + ; + +componentDeclaration + : EXTERNAL? COMPONENT IDENTIFIER (COLON type)? LC componentElement* RC + ; + +externalConstantDeclaration + : EXTERNAL VAL IDENTIFIER COLON type ASSIGN expression + ; + +externalTypeDeclaration + : EXTERNAL TYPE IDENTIFIER ( LC externalTypeElement* RC )? + ; + +externalTypeElement + : staticMemberDeclaration + | variableDeclaration + | (MUT | MUTATING)? externalFunctionDeclaration + ; + +externalFunctionDeclaration + : EXTERNAL FUNCTION IDENTIFIER LP parameters? RP COLON type ASSIGN expression + ; + + // COCOTEC: this is not documented at the places it can be applied. The generic section mentions it + // can be used for Function/Enum/Struct/Type. Seems also applicable to Instances + // Is the WHERE part correctly placed here, so should it be at genericType? +genericTypeDeclaration + : LT genericTypes (WHERE expressions)? GT + ; + +genericTypes + : genericType ( COMMA genericType )* + ; + +genericType + : VAL? IDENTIFIER (COLON type)? + ; + +enumElement + : enumCase + | (MUT | MUTATING)? functionDeclaration + | staticMemberDeclaration + ; + +enumCase + : CASE IDENTIFIER ( LP caseParameters? RP )? (ASSIGN expression)? + ; + +caseParameters + : caseParameter (COMMA caseParameter)* + ; + +caseParameter + : IDENTIFIER COLON type + ; + +structElement + : + (fieldDeclaration + | (MUT | MUTATING)? functionDeclaration + | staticMemberDeclaration + ) ';'? // COCOTEC: the semicolon seems to be allowed here + ; + +fieldDeclaration // COCOTEC: the VAL/VAR seems optional in case a ; is added + : (VAL | VAR)? IDENTIFIER COLON type ( ASSIGN expression )? + ; + +componentElement // COCOTEC: optional attributes are not documented + : attribute* + ( fieldDeclaration + | variableDeclaration + | constructorDeclaration + | stateMachineDeclaration + | staticMemberDeclaration + ) ';'? // COCOTEC: semi colon seems to be allowed? + ; + +staticMemberDeclaration + : STATIC VAL IDENTIFIER COLON type ASSIGN expression + ; + +constructorDeclaration + : INIT LP parameters? RP ASSIGN blockExpression_ + ; + +expression // COCOTEC: what are the precedence/associativity rules? + : literalExpression_ # LiteralExpression + | EXTERNAL BACKTICK_LITERAL # ExternalLiteral // COCOTEC: this is not documented + | externalFunctionDeclaration # ExternalFunction // COCOTEC: this is not documented + | dotIdentifierList (LT genericTypes GT)? # VariableReferenceExpression + | expression DOT IDENTIFIER # MemberReferenceExpression + | stateInvariant # StateInvariantExpression // COCOTEC: this is not documented + | expression LP expressions? RP # CallExpression + | expression LB expression RB # ArraySubscriptExpression + | expression LC fieldAssignments RC # StructLiteralExpression + | expression QM # TryOperatorExpression + | (MINUS | EXCL | AMP) expression # UnaryOperatorExpression + | expression AS type # CastExpression + | expression (MUL | DIV | MOD) expression # ArithmicOrLogicalExpression + | expression (PLUS | MINUS) expression # ArithmicOrLogicalExpression + | expression (EQ | NE | OR | AND | LT | LE | GT | GE) expression # ArithmicOrLogicalExpression + | expression ASSIGN expression # AssignmentExpression + | ifExpression_ # IfExpression + | matchExpression_ # MatchExpression + | DOT IDENTIFIER # ImplicitMemberExpression + | LP expressions RP # GroupedExpression // COCOTEC: this is not documented + | LB expression RB # ArrayLiteralExpression + | nondetExpression_ # NondetExpression + | OPTIONAL expression # OptionalExpression + | blockExpression_ # BlockExpression + ; + +blockExpression_ + : LC statement* ( expression )? RC + ; + +ifExpression_ + : IF LP expression RP expression ( ELSE expression )? + ; + +matchExpression_ // COCOTEC: the COLON is missing in the documentation + : (IDENTIFIER COLON)? MATCH LP expression RP LC matchClauses RC + ; + +nondetExpression_ + : NONDET LC nondetClauses ( OTHERWISE expression )? (COMMA|SEMI)? RC + ; + +fieldAssignments + : fieldAssignment (COMMA fieldAssignment )* COMMA? + ; + +fieldAssignment + : IDENTIFIER ASSIGN expression + ; + +nondetClauses + : nondetClause ((COMMA|SEMI) nondetClause )* (COMMA|SEMI)? + ; + +nondetClause + : ( IF LP expression RP )? expression + ; + +matchClauses // COCOTEC: both comma and semicolon seem to be allowed (trailing one can be omited), only comma is documented + : matchClause ((COMMA|SEMI) matchClause )* (COMMA|SEMI)? + ; + +matchClause + : pattern IMPL expression + ; + +pattern : enumCasePattern + | literalExpression_ + | variableDeclarationPattern + //| variablePattern // this is already handled by enumCasePattern + //| wildcardPattern // this is already handled by enumCasePattern + ; + +enumCasePattern + : idParameterPatterns ( IF LP expression RP )? + ; + +idParameterPatterns + : idParameterPattern (DOT idParameterPattern)* + | DOT idParameterPattern (DOT idParameterPattern)* + ; + +idParameterPattern + : IDENTIFIER ( LP parameterPatterns? RP )? + ; + +variableDeclarationPattern + : (VAL | DOT) IDENTIFIER ( COLON type )? + ; + +parameterPatterns + : parameterPattern ( COMMA parameterPattern )* + ; + +parameterPattern + : VAR? IDENTIFIER + ; + +expressions + : expression ( COMMA expression )* + ; + +statement + : attribute* // COCOTEC: optional attributes are not documented + ( expression SEMI? + | stateInvariant SEMI? // COCOTEC: this rule is not documented + | declarationStatement + | returnStatement + | becomeStatement + | whileStatement + | forStatement + | breakStatement + | continueStatement + ) + ; + +declarationStatement + : variableDeclaration SEMI + ; + +returnStatement + : RETURN expression SEMI + ; + +becomeStatement + : BECOME expression SEMI + ; + +whileStatement + : ( IDENTIFIER COLON)? WHILE LP expression RP blockExpression_ + ; + +forStatement + : ( IDENTIFIER COLON)? FOR IDENTIFIER (COLON type)? IN expression blockExpression_ + ; + +breakStatement + : BREAK IDENTIFIER? SEMI + ; + +continueStatement + : CONTINUE IDENTIFIER? SEMI + ; + +portElement + : attribute* // COCOTEC: optional attributes are not documented + ( enumDeclaration + | functionInterfaceDeclaration + | signalDeclaration + | fieldDeclaration + | stateMachineDeclaration + | portDeclaration + | staticMemberDeclaration + | structDeclaration + | typeAliasDeclaration + | externalTypeDeclaration + ) + ; + +functionInterfaceDeclaration + : FUNCTION IDENTIFIER LP parameters? RP COLON type + ; + +signalDeclaration + : OUTGOING SIGNAL IDENTIFIER LP parameters? RP + ; + +stateMachineDeclaration + : MACHINE IDENTIFIER? (COLON IDENTIFIER)? LC stateMachineElement* RC + ; + +stateMachineElement + : attribute* // COCOTEC: optional attributes are not documented + ( enumDeclaration // COCOTEC: this is missing in the documentation + | entryFunctionDeclaration // COCOTEC: this is missing in the documentation + | exitFunctionDeclaration // COCOTEC: this is missing in the documentation + | functionDeclaration + | stateInvariant // COCOTEC: this is missing in the documentation + | stateDeclaration + | staticMemberDeclaration + | typeAliasDeclaration // COCOTEC: this is listed in the documentation (but no clickable) + | variableDeclaration + | transitionDeclaration // COCOTEC: this is missing in the documentation + ) + ; + +stateDeclaration + : eventStateDeclaration + | executionStateDeclaration + ; + +eventStateDeclaration + : STATE IDENTIFIER ( LP parameters? RP )? LC eventStateElement* RC + ; + +executionStateDeclaration // COCOTEC: the documentation lists explicit { } around a blockExpression which is wrong + : EXECUTION STATE IDENTIFIER ( LP parameters? RP )? blockExpression_ + ; + +eventStateElement + : attribute* // COCOTEC: optional attributes are not documented + ( enumDeclaration + | entryFunctionDeclaration + | exitFunctionDeclaration + | functionDeclaration + | stateDeclaration + | stateInvariant + | staticMemberDeclaration + | structDeclaration + | transitionDeclaration + | typeAliasDeclaration + | variableDeclaration + ) + ; + +entryFunctionDeclaration + : ENTRY LP RP ASSIGN expression + ; + +exitFunctionDeclaration + : EXIT LP RP ASSIGN expression + ; + +stateInvariant + : ASSERT LP expression RP + ; + +transitionDeclaration + : eventTransition + | spontaneousTransition + | timerTransition + // | unusedTransition // special case of eventTransition + ; + +eventTransition // COCOTEC: the (DOT IDENTIFIER)* part is not documented + : (IF LP expression RP )? ( eventSource DOT)* dotIdentifierList LP parameters? RP ASSIGN eventHandler + ; + +eventSource + : IDENTIFIER (LB pattern (PIPE expression)? RB)? + ; + +spontaneousTransition + : (IF LP expression RP )? SPONTANEOUS ASSIGN expression + ; + +timerTransition + : (AFTER | PERIODIC) LP expression RP ASSIGN expression + ; + +eventHandler + : expression + | ILLEGAL + | offer + ; + // COCOTEC: the comma seems to be optional +offer : OFFER LC offerClauses ( OTHERWISE eventHandler COMMA? )? RC + ; + + // COCOTEC: a trailing comma seems to be optional +offerClauses + : offerClause (COMMA offerClause)* COMMA? + ; + +offerClause // COCOTEC: the optional attributes are not documented + : attribute* ( IF LP expression RP )? eventHandler + ; + +parameters + : parameter (COMMA parameter)* + ; + +parameter // COCOTEC: the optional ellipsis is not documented + : VAR? IDENTIFIER ELLIP? (COLON type)? + | IDENTIFIER genericTypeDeclaration + ; + +literalExpression_ + : INTEGER + | CHAR_LITERAL + | STRING_LITERAL + ; + +type : type (MUL | DIV | MOD) type # BinaryType + | type (PLUS | MINUS) type # BinaryType + | LP type RP # GroupType // COCOTEC: this is not documented + | dotIdentifierList (LT types GT)? (DOT IDENTIFIER)? # TypeReference // also InstantiatedType / DependentMemberType + | LP types RP ARROW type # FunctionType + | literalExpression_ # LiteralType + | AMP ( MUT | OUT)? type # ReferenceType + | MINUS type # UnaryType + ; + +types : type (COMMA type)* + ; + +dotIdentifierList + : IDENTIFIER (DOT IDENTIFIER )* + ; + +////////////////////////// LEXER PART (order of rules is important) /////////////////////////////////// + +// keywords +AFTER : 'after'; +AS : 'as'; +ASSERT : 'assert'; +ATTRIBUTE : 'attribute'; +BECOME : 'become'; +BREAK : 'break'; +CASE : 'case'; +COMPONENT : 'component'; +CONTINUE : 'continue'; +ELSE : 'else'; +ENUM : 'enum'; +ENTRY : 'entry'; +EXECUTION : 'execution'; +EXIT : 'exit'; +EXTERNAL : 'external'; +FINAL : 'final'; +FOR : 'for'; +FUNCTION : 'function'; +IF : 'if'; +ILLEGAL : 'illegal'; +IMPORT : 'import'; +IN : 'in'; +INIT : 'init'; +INSTANCE : 'instance'; +MACHINE : 'machine'; +MATCH : 'match'; +MUT : 'mut'; +MUTATING : 'mutating'; +NONDET : 'nondet'; +OFFER : 'offer'; +OPTIONAL : 'optional'; +OTHERWISE : 'otherwise'; +OUT : 'out'; +OUTGOING : 'outgoing'; +PERIODIC : 'periodic'; +PORT : 'port'; +PRIVATE : 'private'; +RETURN : 'return'; +SIGNAL : 'signal'; +SPONTANEOUS : 'spontaneous'; +STATE : 'state'; +STATIC : 'static'; +STRUCT : 'struct'; +TYPE : 'type'; +UNQUALIFIED : 'unqualified'; +VAL : 'val'; +VAR : 'var'; +WHERE : 'where'; +WHILE : 'while'; + +// general non-keyword identifier +IDENTIFIER : Identifier; + +// symbols +AT : '@'; // AT symbol +ASSIGN: '='; // ASSIGNment operator +COLON : ':'; // COLON +LP : '('; // Left Parentheses +RP : ')'; // Right Parentheses +LC : '{'; // Left Curly bracket +RC : '}'; // Right Curly bracket +LB : '['; // Left square Bracket +RB : ']'; // Right square Bracket +COMMA : ','; // COMMA +SEMI : ';'; // SEMIcolon +DOT : '.'; // DOT +LT : '<'; // Less Than +GT : '>'; // Greater Than +MUL : '*'; // MULtiplication +DIV : '/'; // DIVision +MINUS : '-'; // MINUS +MOD : '%'; // MODulo +PLUS : '+'; // PLUS +IMPL : '=>'; // IMPLication +ARROW : '->'; // right arrow +AMP : '&'; // AMPersand +QM : '?'; // Question Mark +PIPE : '|'; // PIPE symbol +EXCL : '!'; // EXCLamation mark +ELLIP : '...'; // Ellipsis +EQ : '=='; // EQual +NE : '!='; // Not Equal +OR : '||'; // logical OR +AND : '&&'; // logical AND +LE : '<='; // Less or Equal +GE : '>='; // Greater or Equal + +WHITESPACE + : [ \t]+ -> channel(HIDDEN) + ; + +NEWLINE : + ( '\r' '\n'? + | '\n' + ) -> channel(HIDDEN) + ; + +LINE_COMMENT + : '//' ~[\r\n]* -> channel(HIDDEN) + ; + +BLOCK_COMMENT + : '/*' .*? '*/' -> channel(HIDDEN) + ; + +INTEGER : [0-9]+ + ; + +BACKTICK_LITERAL + : '`' + ( + ~[`\n] + )* '`' + ; + +CHAR_LITERAL + : '\'' + ( + ~['\\\n\r\t] + | QUOTE_ESCAPE + ) '\'' + ; + +STRING_LITERAL + : '"' + ( + ~["] + | QUOTE_ESCAPE + )* '"' + ; + +fragment QUOTE_ESCAPE + : '\\' ['"nrt0\\] + ; + +fragment Identifier + : Letter LetterOrDigit* + ; + +fragment LetterOrDigit + : Letter + | [0-9] + ; + +fragment Letter + : [a-zA-Z_] // these are the "letters" below 0x7F + | ~[\u0000-\u007F\uD800-\uDBFF] // covers all characters above 0x7F which are not a surrogate + | [\uD800-\uDBFF] [\uDC00-\uDFFF] // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF + ; + diff --git a/pmd-coco/src/main/java/net/sourceforge/pmd/lang/coco/ast/package-info.java b/pmd-coco/src/main/java/net/sourceforge/pmd/lang/coco/ast/package-info.java new file mode 100644 index 0000000000..fd65d07f3a --- /dev/null +++ b/pmd-coco/src/main/java/net/sourceforge/pmd/lang/coco/ast/package-info.java @@ -0,0 +1,8 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +/** + * Contains the Antlr grammar for Coco. + */ +package net.sourceforge.pmd.lang.coco.ast; diff --git a/pmd-coco/src/main/java/net/sourceforge/pmd/lang/coco/cpd/CocoLanguage.java b/pmd-coco/src/main/java/net/sourceforge/pmd/lang/coco/cpd/CocoLanguage.java new file mode 100644 index 0000000000..b3c1cd1b97 --- /dev/null +++ b/pmd-coco/src/main/java/net/sourceforge/pmd/lang/coco/cpd/CocoLanguage.java @@ -0,0 +1,20 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.coco.cpd; + +import net.sourceforge.pmd.cpd.AbstractLanguage; + +/** + * Language implementation for Coco. + */ +public class CocoLanguage extends AbstractLanguage { + + /** + * Creates a new Coco Language instance. + */ + public CocoLanguage() { + super("Coco", "coco", new CocoTokenizer(), ".coco"); + } +} diff --git a/pmd-coco/src/main/java/net/sourceforge/pmd/lang/coco/cpd/CocoTokenizer.java b/pmd-coco/src/main/java/net/sourceforge/pmd/lang/coco/cpd/CocoTokenizer.java new file mode 100644 index 0000000000..2467db44a0 --- /dev/null +++ b/pmd-coco/src/main/java/net/sourceforge/pmd/lang/coco/cpd/CocoTokenizer.java @@ -0,0 +1,22 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.coco.cpd; + +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.Lexer; + +import net.sourceforge.pmd.cpd.impl.AntlrTokenizer; +import net.sourceforge.pmd.lang.coco.ast.CocoLexer; + +/** + * The Coco Tokenizer. + */ +public class CocoTokenizer extends AntlrTokenizer { + + @Override + protected Lexer getLexerForSource(CharStream charStream) { + return new CocoLexer(charStream); + } +} diff --git a/pmd-coco/src/main/java/net/sourceforge/pmd/lang/coco/cpd/package-info.java b/pmd-coco/src/main/java/net/sourceforge/pmd/lang/coco/cpd/package-info.java new file mode 100644 index 0000000000..4d41f7e07b --- /dev/null +++ b/pmd-coco/src/main/java/net/sourceforge/pmd/lang/coco/cpd/package-info.java @@ -0,0 +1,8 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +/** + * Contains Coco tokenizer and language classes. + */ +package net.sourceforge.pmd.lang.coco.cpd; diff --git a/pmd-coco/src/main/resources/META-INF/services/net.sourceforge.pmd.cpd.Language b/pmd-coco/src/main/resources/META-INF/services/net.sourceforge.pmd.cpd.Language new file mode 100644 index 0000000000..9e031cfdd5 --- /dev/null +++ b/pmd-coco/src/main/resources/META-INF/services/net.sourceforge.pmd.cpd.Language @@ -0,0 +1 @@ +net.sourceforge.pmd.lang.coco.cpd.CocoLanguage diff --git a/pmd-coco/src/test/java/net/sourceforge/pmd/cpd/CocoTokenizerTest.java b/pmd-coco/src/test/java/net/sourceforge/pmd/cpd/CocoTokenizerTest.java new file mode 100644 index 0000000000..19f83ec462 --- /dev/null +++ b/pmd-coco/src/test/java/net/sourceforge/pmd/cpd/CocoTokenizerTest.java @@ -0,0 +1,39 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.cpd; + +import java.util.Properties; + +import org.junit.jupiter.api.Test; + +import net.sourceforge.pmd.cpd.test.CpdTextComparisonTest; +import net.sourceforge.pmd.lang.coco.cpd.CocoTokenizer; + +class CocoTokenizerTest extends CpdTextComparisonTest { + CocoTokenizerTest() { + super(".coco"); + } + + @Override + protected String getResourcePrefix() { + return "../lang/coco/cpd/testdata"; + } + + @Override + public Tokenizer newTokenizer(Properties properties) { + CocoTokenizer tok = new CocoTokenizer(); + return tok; + } + + @Test + void testAnnotatedSource() { + doTest("simple_machine"); + } + + @Test + void testDocstring() { + doTest("enum"); + } +} diff --git a/pmd-coco/src/test/resources/net/sourceforge/pmd/lang/coco/cpd/testdata/enum.coco b/pmd-coco/src/test/resources/net/sourceforge/pmd/lang/coco/cpd/testdata/enum.coco new file mode 100644 index 0000000000..9f68c06430 --- /dev/null +++ b/pmd-coco/src/test/resources/net/sourceforge/pmd/lang/coco/cpd/testdata/enum.coco @@ -0,0 +1,125 @@ +import unqualified ComponentDef +import unqualified ExternalTypes +import unqualified ExternalComponent + +@runtime(Runtime.SingleThreaded) +component ComponentDefImpl { + val componentInst : Provided + val rExternalComponent : Required + + init() = {} + + @ignoreWarning(Warning.Unreachable) + machine M { + enum CompEnum { + case Unknown + case Value1 + case Value2 + } + + var compEnum_ : CompEnum = CompEnum.Unknown + + entry() = { + setNextState(InitialState); + } + + function FunctionA(inputVal : ExternalComponent.value) : Nil = { + + @ignoreWarning(Warning.IncompleteMatch) + match (inputVal) { + .Scenario1 => { + if (compEnum_ == CompEnum.Value1) { + componentInst.doStuff(); + setNextState(StateA); + return nil; + } else if (compEnum_ == CompEnum.Value2) { + ExternalComponent.doOtherStuff(); + setNextState(StateB); + return nil; + }; + }, + .Scenario2 => { + if (compEnum_ == CompEnum.Value1) { + ExternalComponent.doOtherStuff(); + setNextState(StateB); + return nil; + } else if (compEnum_ == CompEnum.Value2) { + componentInst.doStuff(); + setNextState(StateA); + return nil; + }; + }, + } + abort(); + } + + function FunctionB(inputVal : ExternalComponent.value) : Nil = { + + @ignoreWarning(Warning.IncompleteMatch) + match (inputVal) { + .Scenario1 => { + compEnum_ = CompEnum.Value1; + setNextState(StateA); + return nil; + }, + .Scenario2 => { + compEnum_ = CompEnum.Value2; + setNextState(StateA); + return nil; + }, + } + abort(); + } + + state InitialState { + assert(compEnum_ == CompEnum.Unknown) + + componentInst.initialize() = { + FunctionB(ExternalComponent.doYourThing()); + } + } + + state StateA { + assert(compEnum_ != CompEnum.Unknown) + + componentInst.run() = { + FunctionA(ExternalComponent.doYourThing()); + } + componentInst.initialize() = { + FunctionB(ExternalComponent.doYourThing()); + } + } + + state StateB { + ExternalComponent.doOtherStuff() = { + componentInst.run(); + compEnum_ = CompEnum.Unknown; + setNextState(InitialState); + } + ExternalComponent.doOtherStuffAgain() = { + ExternalComponent.process(); + setNextState(StateC); + } + } + + state StateC { + ExternalComponent.process() = { + componentInst.run(); + compEnum_ = CompEnum.Unknown; + setNextState(InitialState); + } + ExternalComponent.processAgain() = offer { + if (compEnum_ == CompEnum.Value1) { + componentInst.doStuff(); + compEnum_ = CompEnum.Value2; + setNextState(StateA); + }, + if (compEnum_ == CompEnum.Value2) { + componentInst.doStuff(); + compEnum_ = CompEnum.Value1; + setNextState(StateA); + }, + } + } + } +} diff --git a/pmd-coco/src/test/resources/net/sourceforge/pmd/lang/coco/cpd/testdata/enum.txt b/pmd-coco/src/test/resources/net/sourceforge/pmd/lang/coco/cpd/testdata/enum.txt new file mode 100644 index 0000000000..42401754d9 --- /dev/null +++ b/pmd-coco/src/test/resources/net/sourceforge/pmd/lang/coco/cpd/testdata/enum.txt @@ -0,0 +1,623 @@ + [Image] or [Truncated image[ Bcol Ecol +L1 + [import] 1 7 + [unqualified] 8 19 + [ComponentDef] 20 32 +L2 + [import] 1 7 + [unqualified] 8 19 + [ExternalTypes] 20 33 +L3 + [import] 1 7 + [unqualified] 8 19 + [ExternalComponent] 20 37 +L5 + [@] 1 2 + [runtime] 2 9 + [(] 9 10 + [Runtime] 10 17 + [.] 17 18 + [SingleThreaded] 18 32 + [)] 32 33 +L6 + [component] 1 10 + [ComponentDefImpl] 11 27 + [{] 28 29 +L7 + [val] 3 6 + [componentInst] 7 20 + [:] 21 22 + [Provided] 23 31 + [<] 31 32 + [ComponentDef] 32 44 + [>] 44 45 +L8 + [val] 3 6 + [rExternalComponent] 7 25 + [:] 26 27 + [Required] 28 36 + [<] 36 37 + [ExternalComponent] 37 54 + [>] 54 55 +L10 + [init] 3 7 + [(] 7 8 + [)] 8 9 + [=] 10 11 + [{] 12 13 + [}] 13 14 +L12 + [@] 3 4 + [ignoreWarning] 4 17 + [(] 17 18 + [Warning] 18 25 + [.] 25 26 + [Unreachable] 26 37 + [)] 37 38 +L13 + [machine] 3 10 + [M] 11 12 + [{] 13 14 +L14 + [enum] 5 9 + [CompEnum] 10 18 + [{] 19 20 +L15 + [case] 7 11 + [Unknown] 12 19 +L16 + [case] 7 11 + [Value1] 12 18 +L17 + [case] 7 11 + [Value2] 12 18 +L18 + [}] 5 6 +L20 + [var] 5 8 + [compEnum_] 9 18 + [:] 19 20 + [CompEnum] 21 29 + [=] 30 31 + [CompEnum] 32 40 + [.] 40 41 + [Unknown] 41 48 +L22 + [entry] 5 10 + [(] 10 11 + [)] 11 12 + [=] 13 14 + [{] 15 16 +L23 + [setNextState] 7 19 + [(] 19 20 + [InitialState] 20 32 + [)] 32 33 + [;] 33 34 +L24 + [}] 5 6 +L26 + [function] 5 13 + [FunctionA] 14 23 + [(] 23 24 + [inputVal] 24 32 + [:] 33 34 + [ExternalComponent] 35 52 + [.] 52 53 + [value] 53 58 + [)] 58 59 + [:] 60 61 + [Nil] 62 65 + [=] 66 67 + [{] 68 69 +L28 + [@] 7 8 + [ignoreWarning] 8 21 + [(] 21 22 + [Warning] 22 29 + [.] 29 30 + [IncompleteMatch] 30 45 + [)] 45 46 +L29 + [match] 7 12 + [(] 13 14 + [inputVal] 14 22 + [)] 22 23 + [{] 24 25 +L30 + [.] 9 10 + [Scenario1] 10 19 + [=>] 20 22 + [{] 23 24 +L31 + [if] 11 13 + [(] 14 15 + [compEnum_] 15 24 + [==] 25 27 + [CompEnum] 28 36 + [.] 36 37 + [Value1] 37 43 + [)] 43 44 + [{] 45 46 +L32 + [componentInst] 13 26 + [.] 26 27 + [doStuff] 27 34 + [(] 34 35 + [)] 35 36 + [;] 36 37 +L33 + [setNextState] 13 25 + [(] 25 26 + [StateA] 26 32 + [)] 32 33 + [;] 33 34 +L34 + [return] 13 19 + [nil] 20 23 + [;] 23 24 +L35 + [}] 11 12 + [else] 13 17 + [if] 18 20 + [(] 21 22 + [compEnum_] 22 31 + [==] 32 34 + [CompEnum] 35 43 + [.] 43 44 + [Value2] 44 50 + [)] 50 51 + [{] 52 53 +L36 + [ExternalComponent] 13 30 + [.] 30 31 + [doOtherStuff] 31 43 + [(] 43 44 + [)] 44 45 + [;] 45 46 +L37 + [setNextState] 13 25 + [(] 25 26 + [StateB] 26 32 + [)] 32 33 + [;] 33 34 +L38 + [return] 13 19 + [nil] 20 23 + [;] 23 24 +L39 + [}] 11 12 + [;] 12 13 +L40 + [}] 9 10 + [,] 10 11 +L41 + [.] 9 10 + [Scenario2] 10 19 + [=>] 20 22 + [{] 23 24 +L42 + [if] 11 13 + [(] 14 15 + [compEnum_] 15 24 + [==] 25 27 + [CompEnum] 28 36 + [.] 36 37 + [Value1] 37 43 + [)] 43 44 + [{] 45 46 +L43 + [ExternalComponent] 13 30 + [.] 30 31 + [doOtherStuff] 31 43 + [(] 43 44 + [)] 44 45 + [;] 45 46 +L44 + [setNextState] 13 25 + [(] 25 26 + [StateB] 26 32 + [)] 32 33 + [;] 33 34 +L45 + [return] 13 19 + [nil] 20 23 + [;] 23 24 +L46 + [}] 11 12 + [else] 13 17 + [if] 18 20 + [(] 21 22 + [compEnum_] 22 31 + [==] 32 34 + [CompEnum] 35 43 + [.] 43 44 + [Value2] 44 50 + [)] 50 51 + [{] 52 53 +L47 + [componentInst] 13 26 + [.] 26 27 + [doStuff] 27 34 + [(] 34 35 + [)] 35 36 + [;] 36 37 +L48 + [setNextState] 13 25 + [(] 25 26 + [StateA] 26 32 + [)] 32 33 + [;] 33 34 +L49 + [return] 13 19 + [nil] 20 23 + [;] 23 24 +L50 + [}] 11 12 + [;] 12 13 +L51 + [}] 9 10 + [,] 10 11 +L52 + [}] 7 8 +L53 + [abort] 7 12 + [(] 12 13 + [)] 13 14 + [;] 14 15 +L54 + [}] 5 6 +L56 + [function] 5 13 + [FunctionB] 14 23 + [(] 23 24 + [inputVal] 24 32 + [:] 33 34 + [ExternalComponent] 35 52 + [.] 52 53 + [value] 53 58 + [)] 58 59 + [:] 60 61 + [Nil] 62 65 + [=] 66 67 + [{] 68 69 +L58 + [@] 7 8 + [ignoreWarning] 8 21 + [(] 21 22 + [Warning] 22 29 + [.] 29 30 + [IncompleteMatch] 30 45 + [)] 45 46 +L59 + [match] 7 12 + [(] 13 14 + [inputVal] 14 22 + [)] 22 23 + [{] 24 25 +L60 + [.] 9 10 + [Scenario1] 10 19 + [=>] 20 22 + [{] 23 24 +L61 + [compEnum_] 11 20 + [=] 21 22 + [CompEnum] 23 31 + [.] 31 32 + [Value1] 32 38 + [;] 38 39 +L62 + [setNextState] 11 23 + [(] 23 24 + [StateA] 24 30 + [)] 30 31 + [;] 31 32 +L63 + [return] 11 17 + [nil] 18 21 + [;] 21 22 +L64 + [}] 9 10 + [,] 10 11 +L65 + [.] 9 10 + [Scenario2] 10 19 + [=>] 20 22 + [{] 23 24 +L66 + [compEnum_] 11 20 + [=] 21 22 + [CompEnum] 23 31 + [.] 31 32 + [Value2] 32 38 + [;] 38 39 +L67 + [setNextState] 11 23 + [(] 23 24 + [StateA] 24 30 + [)] 30 31 + [;] 31 32 +L68 + [return] 11 17 + [nil] 18 21 + [;] 21 22 +L69 + [}] 9 10 + [,] 10 11 +L70 + [}] 7 8 +L71 + [abort] 7 12 + [(] 12 13 + [)] 13 14 + [;] 14 15 +L72 + [}] 5 6 +L74 + [state] 5 10 + [InitialState] 11 23 + [{] 24 25 +L75 + [assert] 7 13 + [(] 13 14 + [compEnum_] 14 23 + [==] 24 26 + [CompEnum] 27 35 + [.] 35 36 + [Unknown] 36 43 + [)] 43 44 +L77 + [componentInst] 7 20 + [.] 20 21 + [initialize] 21 31 + [(] 31 32 + [)] 32 33 + [=] 34 35 + [{] 36 37 +L78 + [FunctionB] 9 18 + [(] 18 19 + [ExternalComponent] 19 36 + [.] 36 37 + [doYourThing] 37 48 + [(] 48 49 + [)] 49 50 + [)] 50 51 + [;] 51 52 +L79 + [}] 7 8 +L80 + [}] 5 6 +L82 + [state] 5 10 + [StateA] 11 17 + [{] 18 19 +L83 + [assert] 7 13 + [(] 13 14 + [compEnum_] 14 23 + [!=] 24 26 + [CompEnum] 27 35 + [.] 35 36 + [Unknown] 36 43 + [)] 43 44 +L85 + [componentInst] 7 20 + [.] 20 21 + [run] 21 24 + [(] 24 25 + [)] 25 26 + [=] 27 28 + [{] 29 30 +L86 + [FunctionA] 9 18 + [(] 18 19 + [ExternalComponent] 19 36 + [.] 36 37 + [doYourThing] 37 48 + [(] 48 49 + [)] 49 50 + [)] 50 51 + [;] 51 52 +L87 + [}] 7 8 +L88 + [componentInst] 7 20 + [.] 20 21 + [initialize] 21 31 + [(] 31 32 + [)] 32 33 + [=] 34 35 + [{] 36 37 +L89 + [FunctionB] 9 18 + [(] 18 19 + [ExternalComponent] 19 36 + [.] 36 37 + [doYourThing] 37 48 + [(] 48 49 + [)] 49 50 + [)] 50 51 + [;] 51 52 +L90 + [}] 7 8 +L91 + [}] 5 6 +L93 + [state] 5 10 + [StateB] 11 17 + [{] 18 19 +L94 + [ExternalComponent] 7 24 + [.] 24 25 + [doOtherStuff] 25 37 + [(] 37 38 + [)] 38 39 + [=] 40 41 + [{] 42 43 +L95 + [componentInst] 9 22 + [.] 22 23 + [run] 23 26 + [(] 26 27 + [)] 27 28 + [;] 28 29 +L96 + [compEnum_] 9 18 + [=] 19 20 + [CompEnum] 21 29 + [.] 29 30 + [Unknown] 30 37 + [;] 37 38 +L97 + [setNextState] 9 21 + [(] 21 22 + [InitialState] 22 34 + [)] 34 35 + [;] 35 36 +L98 + [}] 7 8 +L99 + [ExternalComponent] 7 24 + [.] 24 25 + [doOtherStuffAgain] 25 42 + [(] 42 43 + [)] 43 44 + [=] 45 46 + [{] 47 48 +L100 + [ExternalComponent] 9 26 + [.] 26 27 + [process] 27 34 + [(] 34 35 + [)] 35 36 + [;] 36 37 +L101 + [setNextState] 9 21 + [(] 21 22 + [StateC] 22 28 + [)] 28 29 + [;] 29 30 +L102 + [}] 7 8 +L103 + [}] 5 6 +L105 + [state] 5 10 + [StateC] 11 17 + [{] 18 19 +L106 + [ExternalComponent] 7 24 + [.] 24 25 + [process] 25 32 + [(] 32 33 + [)] 33 34 + [=] 35 36 + [{] 37 38 +L107 + [componentInst] 9 22 + [.] 22 23 + [run] 23 26 + [(] 26 27 + [)] 27 28 + [;] 28 29 +L108 + [compEnum_] 9 18 + [=] 19 20 + [CompEnum] 21 29 + [.] 29 30 + [Unknown] 30 37 + [;] 37 38 +L109 + [setNextState] 9 21 + [(] 21 22 + [InitialState] 22 34 + [)] 34 35 + [;] 35 36 +L110 + [}] 7 8 +L111 + [ExternalComponent] 7 24 + [.] 24 25 + [processAgain] 25 37 + [(] 37 38 + [)] 38 39 + [=] 40 41 + [offer] 42 47 + [{] 48 49 +L112 + [if] 9 11 + [(] 12 13 + [compEnum_] 13 22 + [==] 23 25 + [CompEnum] 26 34 + [.] 34 35 + [Value1] 35 41 + [)] 41 42 + [{] 43 44 +L113 + [componentInst] 11 24 + [.] 24 25 + [doStuff] 25 32 + [(] 32 33 + [)] 33 34 + [;] 34 35 +L114 + [compEnum_] 11 20 + [=] 21 22 + [CompEnum] 23 31 + [.] 31 32 + [Value2] 32 38 + [;] 38 39 +L115 + [setNextState] 11 23 + [(] 23 24 + [StateA] 24 30 + [)] 30 31 + [;] 31 32 +L116 + [}] 9 10 + [,] 10 11 +L117 + [if] 9 11 + [(] 12 13 + [compEnum_] 13 22 + [==] 23 25 + [CompEnum] 26 34 + [.] 34 35 + [Value2] 35 41 + [)] 41 42 + [{] 43 44 +L118 + [componentInst] 11 24 + [.] 24 25 + [doStuff] 25 32 + [(] 32 33 + [)] 33 34 + [;] 34 35 +L119 + [compEnum_] 11 20 + [=] 21 22 + [CompEnum] 23 31 + [.] 31 32 + [Value1] 32 38 + [;] 38 39 +L120 + [setNextState] 11 23 + [(] 23 24 + [StateA] 24 30 + [)] 30 31 + [;] 31 32 +L121 + [}] 9 10 + [,] 10 11 +L122 + [}] 7 8 +L123 + [}] 5 6 +L124 + [}] 3 4 +L125 + [}] 1 2 +EOF diff --git a/pmd-coco/src/test/resources/net/sourceforge/pmd/lang/coco/cpd/testdata/simple_machine.coco b/pmd-coco/src/test/resources/net/sourceforge/pmd/lang/coco/cpd/testdata/simple_machine.coco new file mode 100644 index 0000000000..c8e9b2d23d --- /dev/null +++ b/pmd-coco/src/test/resources/net/sourceforge/pmd/lang/coco/cpd/testdata/simple_machine.coco @@ -0,0 +1,54 @@ +import unqualified ExternalTypes + +port Example_Device { + function do_something(instanceId : TypeId) : Nil + + outgoing signal signal_a(instanceId : TypeId) + outgoing signal signal_b(instanceId : TypeId, errorId : ErrorId) + outgoing signal trigger() + + + machine M { + var num_items_ : Bounded<0, 10> = 0 + val upper_bound_ : Bounded<0, 10> = 10 + val lower_bound_ : Bounded<0, 10> = 0 + + if (num_items_ > lower_bound_) + spontaneous = { + nondet { + signal_a(_), + signal_b(_, _), + } + num_items_ = num_items_ - 1; + } + + state Init { + if (num_items_ < upper_bound_) do_something(_ : TypeId) = nondet { + { + setNextState(AddItem) + }, + { + trigger(); + num_items_ = num_items_ + 1; + }, + } + } + + state AddItem { + spontaneous = { + nondet { + { + trigger(); + num_items_ = num_items_ + 1; + }, + } + setNextState(Init); + } + } + } +} + +@runtime(.SingleThreaded) +external component Example_Device_Base { + val ExampleDevice : Required +} \ No newline at end of file diff --git a/pmd-coco/src/test/resources/net/sourceforge/pmd/lang/coco/cpd/testdata/simple_machine.txt b/pmd-coco/src/test/resources/net/sourceforge/pmd/lang/coco/cpd/testdata/simple_machine.txt new file mode 100644 index 0000000000..0fe7503f34 --- /dev/null +++ b/pmd-coco/src/test/resources/net/sourceforge/pmd/lang/coco/cpd/testdata/simple_machine.txt @@ -0,0 +1,244 @@ + [Image] or [Truncated image[ Bcol Ecol +L1 + [import] 1 7 + [unqualified] 8 19 + [ExternalTypes] 20 33 +L3 + [port] 1 5 + [Example_Device] 6 20 + [{] 21 22 +L4 + [function] 3 11 + [do_something] 12 24 + [(] 24 25 + [instanceId] 25 35 + [:] 36 37 + [TypeId] 38 44 + [)] 44 45 + [:] 46 47 + [Nil] 48 51 +L6 + [outgoing] 3 11 + [signal] 12 18 + [signal_a] 19 27 + [(] 27 28 + [instanceId] 28 38 + [:] 39 40 + [TypeId] 41 47 + [)] 47 48 +L7 + [outgoing] 3 11 + [signal] 12 18 + [signal_b] 19 27 + [(] 27 28 + [instanceId] 28 38 + [:] 39 40 + [TypeId] 41 47 + [,] 47 48 + [errorId] 49 56 + [:] 57 58 + [ErrorId] 59 66 + [)] 66 67 +L8 + [outgoing] 3 11 + [signal] 12 18 + [trigger] 19 26 + [(] 26 27 + [)] 27 28 +L11 + [machine] 3 10 + [M] 11 12 + [{] 13 14 +L12 + [var] 5 8 + [num_items_] 9 19 + [:] 20 21 + [Bounded] 22 29 + [<] 29 30 + [0] 30 31 + [,] 31 32 + [10] 33 35 + [>] 35 36 + [=] 37 38 + [0] 39 40 +L13 + [val] 5 8 + [upper_bound_] 9 21 + [:] 22 23 + [Bounded] 24 31 + [<] 31 32 + [0] 32 33 + [,] 33 34 + [10] 35 37 + [>] 37 38 + [=] 39 40 + [10] 41 43 +L14 + [val] 5 8 + [lower_bound_] 9 21 + [:] 22 23 + [Bounded] 24 31 + [<] 31 32 + [0] 32 33 + [,] 33 34 + [10] 35 37 + [>] 37 38 + [=] 39 40 + [0] 41 42 +L16 + [if] 5 7 + [(] 8 9 + [num_items_] 9 19 + [>] 20 21 + [lower_bound_] 22 34 + [)] 34 35 +L17 + [spontaneous] 5 16 + [=] 17 18 + [{] 19 20 +L18 + [nondet] 7 13 + [{] 14 15 +L19 + [signal_a] 9 17 + [(] 17 18 + [_] 18 19 + [)] 19 20 + [,] 20 21 +L20 + [signal_b] 9 17 + [(] 17 18 + [_] 18 19 + [,] 19 20 + [_] 21 22 + [)] 22 23 + [,] 23 24 +L21 + [}] 7 8 +L22 + [num_items_] 7 17 + [=] 18 19 + [num_items_] 20 30 + [-] 31 32 + [1] 33 34 + [;] 34 35 +L23 + [}] 5 6 +L25 + [state] 5 10 + [Init] 11 15 + [{] 16 17 +L26 + [if] 7 9 + [(] 10 11 + [num_items_] 11 21 + [<] 22 23 + [upper_bound_] 24 36 + [)] 36 37 + [do_something] 38 50 + [(] 50 51 + [_] 51 52 + [:] 53 54 + [TypeId] 55 61 + [)] 61 62 + [=] 63 64 + [nondet] 65 71 + [{] 72 73 +L27 + [{] 9 10 +L28 + [setNextState] 11 23 + [(] 23 24 + [AddItem] 24 31 + [)] 31 32 +L29 + [}] 9 10 + [,] 10 11 +L30 + [{] 9 10 +L31 + [trigger] 11 18 + [(] 18 19 + [)] 19 20 + [;] 20 21 +L32 + [num_items_] 11 21 + [=] 22 23 + [num_items_] 24 34 + [+] 35 36 + [1] 37 38 + [;] 38 39 +L33 + [}] 9 10 + [,] 10 11 +L34 + [}] 7 8 +L35 + [}] 5 6 +L37 + [state] 5 10 + [AddItem] 11 18 + [{] 19 20 +L38 + [spontaneous] 7 18 + [=] 19 20 + [{] 21 22 +L39 + [nondet] 9 15 + [{] 16 17 +L40 + [{] 11 12 +L41 + [trigger] 13 20 + [(] 20 21 + [)] 21 22 + [;] 22 23 +L42 + [num_items_] 13 23 + [=] 24 25 + [num_items_] 26 36 + [+] 37 38 + [1] 39 40 + [;] 40 41 +L43 + [}] 11 12 + [,] 12 13 +L44 + [}] 9 10 +L45 + [setNextState] 9 21 + [(] 21 22 + [Init] 22 26 + [)] 26 27 + [;] 27 28 +L46 + [}] 7 8 +L47 + [}] 5 6 +L48 + [}] 3 4 +L49 + [}] 1 2 +L51 + [@] 1 2 + [runtime] 2 9 + [(] 9 10 + [.] 10 11 + [SingleThreaded] 11 25 + [)] 25 26 +L52 + [external] 1 9 + [component] 10 19 + [Example_Device_Base] 20 39 + [{] 40 41 +L53 + [val] 3 6 + [ExampleDevice] 7 20 + [:] 21 22 + [Required] 23 31 + [<] 31 32 + [Example_Device] 32 46 + [>] 46 47 +L54 + [}] 1 2 +EOF diff --git a/pmd-core/etc/xslt/cpdhtml-v2.xslt b/pmd-core/etc/xslt/cpdhtml-v2.xslt new file mode 100644 index 0000000000..c1862d9cba --- /dev/null +++ b/pmd-core/etc/xslt/cpdhtml-v2.xslt @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
columnendcolumnlineendlinepath
+ +
+ +
+
+ +
diff --git a/pmd-core/etc/xslt/cpdhtml.xslt b/pmd-core/etc/xslt/cpdhtml.xslt index e298e17cdf..ef6e9ac94f 100644 --- a/pmd-core/etc/xslt/cpdhtml.xslt +++ b/pmd-core/etc/xslt/cpdhtml.xslt @@ -1,13 +1,14 @@ - + - + +30 + -