diff --git a/.travis/release.sh b/.travis/release.sh index f11b56fdb7..bbc16fbd20 100755 --- a/.travis/release.sh +++ b/.travis/release.sh @@ -117,7 +117,7 @@ mkdir pmd.github.io log_info "Uploading the new release to pmd.sourceforge.net which serves as an archive..." - travis_wait rsync -ah --stats docs/pmd-doc-${RELEASE_VERSION}/ ${PMD_SF_USER}@web.sourceforge.net:/home/project-web/pmd/htdocs/pmd-${RELEASE_VERSION}/ + .travis/travis_wait "rsync -ah --stats docs/pmd-doc-${RELEASE_VERSION}/ ${PMD_SF_USER}@web.sourceforge.net:/home/project-web/pmd/htdocs/pmd-${RELEASE_VERSION}/" if [ $? -ne 0 ]; then log_error "Uploading documentation to pmd.sourceforge.net failed..." diff --git a/.travis/travis_wait b/.travis/travis_wait new file mode 100755 index 0000000000..013cea97df --- /dev/null +++ b/.travis/travis_wait @@ -0,0 +1,322 @@ +#!/usr/bin/env bash + +# The MIT License (MIT) + +# Copyright (c) 2015 +# m3t (96bd6c8bb869fe632b3650fb7156c797ef8c2a055d31dde634565f3edda485b) + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# Available from https://github.com/m3t/travis_wait +# Please report bugs at https://github.com/m3t/travis_wait/issues + +# Coding (Style) Guidelines: +# https://www.chromium.org/chromium-os/shell-style-guidelines +# http://mywiki.wooledge.org/BashGuide/Practices +# http://wiki.bash-hackers.org/scripting/style + + +# bash available? +if [ -z "$BASH_VERSINFO" ]; then + echo "Please make sure you're using bash!" + exit 1 +fi + + +# INITIALIZE CONSTANTS AND GLOBALS +# Only lower case, esp. for export! +# That ensures that system vars stay untouched in any case +readonly prog_name=$(basename "$0") + + +is_writeable() { + local var="$1" + + is_writeable_empty "${var}" 0 +} + +is_writeable_empty() { + local var="$1" + local empty="$2" + [[ -z "${empty}" ]] && empty=1 + + # http://mywiki.wooledge.org/BashGuide/TestsAndConditionals + # "touch" creates file, if it doesn't exist, + # so further tests won't fail at the beginning + if { touch -a "${var}" >/dev/null 2>&1; }; then + if [[ ! -s "${var}" ]]; then + if [[ ! -w "${var}" ]]; then + #show_warning "${var} is not writeable" + return 1 + fi + else + #show_warning "${var} is not empty" + [[ "${empty}" -eq 1 ]] && return 1 + fi + else + #show_warning "Destination for ${var} is not accessible at all" + return 1 + fi + + return 0 +} + +is_number() { + local int="$1" + # http://mywiki.wooledge.org/BashFAQ/054 + [[ "$int" != *[!0-9]* ]] +} + +is_empty() { + local var="$1" + + [[ -z "$var" ]] +} + +show_error() { + printf "\n%s\n" "${prog_name}: error: $*" >&2 + exit 1 +} + +show_warning() { + printf "\n%s\n" "${prog_name}: $*" >&2 +} + +show_help() { + # http://wiki.bash-hackers.org/syntax/redirection#here_documents + cat <<- EOF + + Usage: ${prog_name} [options] [] + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor + incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, + quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse + cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat + non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. + + Arguments: + Slowpoke command + Where 's output will be saved + Default: \$RANDOM-output.log + + Options: + -i, --interval Refresh interval in sec. + Default: 30 + + -l, --limit Limit execution time in sec. + Default: 0 (Off) + + -x, --exit-code Force the exit code + Default: -1 (Off) + + -a, --append PRN append output to existing logfile + Off: 0 (Default) + On: 1 + + -h This help screen + + + Copyright (C) 2015 m3t + The MIT License (MIT) + +EOF + + exit 0 +} + +cleanup() { + kill -0 ${pid_slowpoke} >/dev/null 2>&1 && kill ${pid_slowpoke} >/dev/null 2>&1 +} + +main() { + + # INITIALIZE LOCAL VARIABLES + # Variables to be evaluated as shell arithmetic should be initialized + # to a default or validated beforehand. + # CAUTION: Arguments' (not options) default values will be overwritten here anyway + # So they are set in VALIDATE INPUT + local i=0 + local msg="" + local time_passed=0 + local pid_slowpoke=0 + local exit_slowpoke=0 + # Options: + local interval=30 + local time_limit=0 + local exit_force=-1 + local append=0 + # Arguments: + local cmd_slowpoke="" + local file_log="" + + + # SIGNAL HANDLING + # http://mywiki.wooledge.org/SignalTrap + # http://mywiki.wooledge.org/SignalTrap#Special_Note_On_SIGINT + trap 'cleanup; trap - INT; kill -INT $$' INT QUIT # CTRL+C OR CTRL+\ + trap 'cleanup; exit 1' TERM # kill's default signal + + + # COMMAND-LINE ARGUMENTS AND OPTIONS + # http://mywiki.wooledge.org/BashFAQ/035 + msg="requires a non-empty option argument." + while :; do + case "$1" in + -h|-\?|--help) + show_help + exit + ;; + -l|--limit) + if [ -n "$2" ]; then + time_limit="$2" + shift 2 + continue + else + show_error "--limit ${msg}" + fi + ;; + --limit=?*) + time_limit="${1#*=}" + ;; + --limit=) + show_error "--limit ${msg}" + ;; + -i|--interval) + if [ -n "$2" ]; then + interval="$2" + shift 2 + continue + else + show_error "--interval ${msg}" + fi + ;; + --interval=?*) + interval="${1#*=}" + ;; + --interval=) + show_error "--interval ${msg}" + ;; + -x|--exit-code) + if [ -n "$2" ]; then + exit_force="$2" + shift 2 + continue + else + show_error "--exit-code ${msg}" + fi + ;; + --exit-code=?*) + exit_force="${1#*=}" + ;; + --exit-code=) + show_error "--exit-code ${msg}" + ;; + -a|--append) + if [ -n "$2" ]; then + append="$2" + shift 2 + continue + else + show_error "--append ${msg}" + fi + ;; + --append=?*) + append="${1#*=}" + ;; + --append=) + show_error "--append ${msg}" + ;; + --) # End of all options. + shift + break + ;; + -?*) + show_warning "Unknown option (ignored): $1" + ;; + *) # Default case: If no more options then break out of the loop. + break + esac + + shift + done + # Arguments following the options + # will remain in the "$@" positional parameters. + cmd_slowpoke="$1" + file_log="$2" + + + # VALIDATE INPUT + is_number "${interval}" || show_error "Interval is not a valid number" + is_number "${time_limit}" || show_error "Limit is not a valid number" + is_empty "${cmd_slowpoke}" && show_error "Command to execute is not given. See --help." + is_empty "${file_log}" && file_log="$RANDOM-output.log" # http://mywiki.wooledge.org/BashFAQ/062 + + # START CMD + # http://mywiki.wooledge.org/ProcessManagement + if [[ "${append}" -ne 1 ]]; then + is_writeable_empty "${file_log}" || show_error "${file_log} is not writeable or not empty." + ${cmd_slowpoke} > "${file_log}" & pid_slowpoke=$! + else + is_writeable "${file_log}" || show_error "${file_log} is not writeable." + ${cmd_slowpoke} >> "${file_log}" & pid_slowpoke=$! + fi + + + # WAIT + # Terminates when $cmd_slowpoke is finished + # OR + # $time_limit has reached + i=0 + while kill -0 ${pid_slowpoke} >/dev/null 2>&1; do + : $(( time_passed = i * interval )) + + printf "%s\n" \ + "Still waiting for about ${time_passed} seconds" \ + "Used disk space: $(du -sh .)" + + # Output last line from $file_log + tail -1 "${file_log}" + + # $time_limit + if [[ "${time_limit}" -ne 0 ]] && [[ "${time_passed}" -ge "${time_limit}" ]]; then + cleanup + break + fi + + sleep ${interval} + + : $(( i += 1 )) + done + + + # FINISHED + # Shall I fake the exit code? + if ! is_number "${exit_force}"; then + # Get exit code from child process that is terminated already, see above + wait ${pid_slowpoke}; exit_slowpoke=$? + else + exit_slowpoke=${exit_force} + fi + show_warning "Your given command has terminated with exit code $exit_slowpoke. So do I." + exit ${exit_slowpoke} + +} + +main "$@" diff --git a/Gemfile b/Gemfile index 2b9ab0d121..65d6075bae 100644 --- a/Gemfile +++ b/Gemfile @@ -9,6 +9,7 @@ gem 'danger', '~> 5.6', '>= 5.6' group :release_notes_preprocessing do gem 'liquid', '>=4.0.0' gem 'safe_yaml', '>=1.0' + gem 'rouge', '>= 1.7', '< 4' end # vim: syntax=ruby diff --git a/docs/_config.yml b/docs/_config.yml index 8fcdabf962..e6fee403f1 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -1,9 +1,9 @@ repository: pmd/pmd pmd: - version: 6.10.0 - previous_version: 6.9.0 - date: ??-????-2018 + version: 6.11.0 + previous_version: 6.10.0 + date: ??-January-2019 release_type: minor output: web diff --git a/docs/_plugins/javadoc_tag.rb b/docs/_plugins/javadoc_tag.rb index dc68c67036..7bdf60560c 100644 --- a/docs/_plugins/javadoc_tag.rb +++ b/docs/_plugins/javadoc_tag.rb @@ -137,6 +137,7 @@ class JavadocTag < Liquid::Tag # Expand FQCN of arguments @member_suffix.gsub!(JDocNamespaceDeclaration::NAMESPACED_FQCN_REGEX) {|fqcn| JDocNamespaceDeclaration::parse_fqcn(fqcn, var_ctx)[1]} + @member_suffix.gsub!(JDocNamespaceDeclaration::SYM_REGEX) {|fqcn| JDocNamespaceDeclaration::parse_fqcn(fqcn, var_ctx)[1]} visible_name = JavadocTag::get_visible_name(@opts, @type_fqcn, @member_suffix, @is_package_ref) diff --git a/docs/_plugins/jdoc_namespace_tag.rb b/docs/_plugins/jdoc_namespace_tag.rb index 019864de31..b4b1f06a13 100644 --- a/docs/_plugins/jdoc_namespace_tag.rb +++ b/docs/_plugins/jdoc_namespace_tag.rb @@ -94,7 +94,9 @@ class JDocNamespaceDeclaration < Liquid::Tag private JDOC_NAMESPACE_MAP = "jdoc_nspaces" - RESERVED_NSPACES = ['core', 'java', 'apex', 'dist', 'doc', 'xml', 'visualforce', 'ui', 'test'].flat_map {|m| [m, "pmd-" + m]} + RESERVED_NSPACES = ['apex', 'core', 'cpp', 'cs', 'dist', 'doc', 'fortran', 'go', 'groovy', 'java', 'javascript', 'jsp', + 'kotlin', 'matlab', 'objectivec', 'perl', 'php', 'plsql', 'python', 'ruby', 'scala', 'swift', 'test', 'ui', + 'visualforce', 'vm', 'xml'].flat_map {|m| [m, "pmd-" + m]} def self.make_base_namespaces res = {} diff --git a/docs/pages/next_major_development.md b/docs/pages/next_major_development.md index c7abcaa68c..3c4946718a 100644 --- a/docs/pages/next_major_development.md +++ b/docs/pages/next_major_development.md @@ -73,6 +73,202 @@ the breaking API changes will be performed in 7.0.0. an API is tagged as `@Deprecated` or not in the latest minor release. During the development of 7.0.0, we may decide to remove some APIs that were not tagged as deprecated, though we'll try to avoid it." %} +#### 6.10.0 + +##### Properties framework + +{% jdoc_nspace :props core::properties %} +{% jdoc_nspace :PDr props::PropertyDescriptor %} +{% jdoc_nspace :PF props::PropertyFactory %} + +The properties framework is about to get a lifting, and for that reason, we need to deprecate a lot of APIs +to remove them in 7.0.0. The proposed changes to the API are described [on the wiki](https://github.com/pmd/pmd/wiki/Property-framework-7-0-0) + +###### Changes to how you define properties + +* Construction of property descriptors has been possible through builders since 6.0.0. The 7.0.0 API will only allow +construction through builders. The builder hierarchy, currently found in the package {% jdoc_package props::builders %}, +is being replaced by the simpler {% jdoc props::PropertyBuilder %}. Their APIs enjoy a high degree of source compatibility. + +* Concrete property classes like {% jdoc props::IntegerProperty %} and {% jdoc props::StringMultiProperty %} will gradually +all be deprecated until 7.0.0. Their usages should be replaced by direct usage of the {% jdoc props::PropertyDescriptor %} +interface, e.g. `PropertyDescriptor` or `PropertyDescriptor>`. + +* Instead of spreading properties across countless classes, the utility class {% jdoc :PF %} will become +from 7.0.0 on the only provider for property descriptor builders. Each current property type will be replaced +by a corresponding method on `PropertyFactory`: + * {% jdoc props::IntegerProperty %} is replaced by {% jdoc !c!:PF#intProperty(java.lang.String) %} + * {% jdoc props::IntegerMultiProperty %} is replaced by {% jdoc !c!:PF#intListProperty(java.lang.String) %} + + * {% jdoc props::FloatProperty %} and {% jdoc props::DoubleProperty %} are both replaced by {% jdoc !c!:PF#doubleProperty(java.lang.String) %}. + Having a separate property for floats wasn't that useful. + * Similarly, {% jdoc props::FloatMultiProperty %} and {% jdoc props::DoubleMultiProperty %} are replaced by {% jdoc !c!:PF#doubleListProperty(java.lang.String) %}. + + * {% jdoc props::StringProperty %} is replaced by {% jdoc !c!:PF#stringProperty(java.lang.String) %} + * {% jdoc props::StringMultiProperty %} is replaced by {% jdoc !c!:PF#stringListProperty(java.lang.String) %} + + * {% jdoc props::RegexProperty %} is replaced by {% jdoc !c!:PF#regexProperty(java.lang.String) %} + + * {% jdoc props::EnumeratedProperty %} is replaced by {% jdoc !c!:PF#enumProperty(java.lang.String,java.util.Map) %} + * {% jdoc props::EnumeratedProperty %} is replaced by {% jdoc !c!:PF#enumListProperty(java.lang.String,java.util.Map) %} + + * {% jdoc props::BooleanProperty %} is replaced by {% jdoc !c!:PF#booleanProperty(java.lang.String) %} + * Its multi-valued counterpart, {% jdoc props::BooleanMultiProperty %}, is not replaced, because it doesn't have a use case. + + * {% jdoc props::CharacterProperty %} is replaced by {% jdoc !c!:PF#charProperty(java.lang.String) %} + * {% jdoc props::CharacterMultiProperty %} is replaced by {% jdoc !c!:PF#charListProperty(java.lang.String) %} + + * {% jdoc props::LongProperty %} is replaced by {% jdoc !c!:PF#longIntProperty(java.lang.String) %} + * {% jdoc props::LongMultiProperty %} is replaced by {% jdoc !c!:PF#longIntListProperty(java.lang.String) %} + + * {% jdoc props::MethodProperty %}, {% jdoc props::FileProperty %}, {% jdoc props::TypeProperty %} and their multi-valued counterparts + are discontinued for lack of a use-case, and have no planned replacement in 7.0.0 for now. + + + +Here's an example: +```java +// Before 7.0.0, these are equivalent: +IntegerProperty myProperty = new IntegerProperty("score", "Top score value", 1, 100, 40, 3.0f); +IntegerProperty myProperty = IntegerProperty.named("score").desc("Top score value").range(1, 100).defaultValue(40).uiOrder(3.0f); + +// They both map to the following in 7.0.0 +PropertyDescriptor myProperty = PropertyFactory.intProperty("score").desc("Top score value").require(inRange(1, 100)).defaultValue(40); +``` + +You're highly encouraged to migrate to using this new API as soon as possible, to ease your migration to 7.0.0. + + + +###### Architectural simplifications + +* {% jdoc props::EnumeratedPropertyDescriptor %}, {% jdoc props::NumericPropertyDescriptor %}, {% jdoc props::PackagedPropertyDescriptor %}, +and the related builders (in {% jdoc_package props::builders %}) will be removed. +These specialized interfaces allowed additional constraints to be enforced on the +value of a property, but made the property class hierarchy very large and impractical +to maintain. Their functionality will be mapped uniformly to {% jdoc props::constraints.PropertyConstraint %}s, +which will allow virtually any constraint to be defined, and improve documentation and error reporting. The +related methods {% jdoc !c!props::PropertyTypeId#isPropertyNumeric() %} and +{% jdoc !c!props::PropertyTypeId#isPropertyPackaged() %} are also deprecated. + +* {% jdoc props::MultiValuePropertyDescriptor %} and {% jdoc props::SingleValuePropertyDescriptor %} +are deprecated. 7.0.0 will introduce a new XML syntax which will remove the need for such a divide +between single- and multi-valued properties. The method {% jdoc !c!:PDr#isMultiValue() %} will be removed +accordingly. + +###### Changes to the PropertyDescriptor interface + +* {% jdoc :PDr#preferredRowCount() %} is deprecated with no intended replacement. It was never implemented, and does not belong + in this interface. The methods {% jdoc :PDr#uiOrder() %} and `compareTo(PropertyDescriptor)` are deprecated for the + same reason. These methods mix presentation logic with business logic and are not necessary for PropertyDescriptors to work. + `PropertyDescriptor` will not extend `Comparable` anymore come 7.0.0. +* The method {% jdoc :PDr#propertyErrorFor(core::Rule) %} is deprecated and will be removed with no intended + replacement. It's really just a shortcut for `prop.errorFor(rule.getProperty(prop))`. +* `T `{% jdoc !a!:PDr#valueFrom(java.lang.String) %} and `String `{% jdoc :PDr#asDelimitedString(java.lang.Object) %}`(T)` are deprecated and will be removed. These were + used to serialize and deserialize properties to/from a string, but 7.0.0 will introduce a more flexible + XML syntax which will make them obsolete. +* {% jdoc :PDr#isMultiValue() %} and {% jdoc :PDr#type() %} are deprecated and won't be replaced. The new XML syntax will remove the need + for a divide between multi- and single-value properties, and will allow arbitrary types to be represented. + Since arbitrary types may be represented, `type` will become obsolete as it can't represent generic types, + which will nevertheless be representable with the XML syntax. It was only used for documentation, but a + new way to document these properties exhaustively will be added with 7.0.0. +* {% jdoc :PDr#errorFor(java.lang.Object) %} is deprecated as its return type will be changed to `Optional` with the shift to Java 8. + +##### Deprecated APIs + +{% jdoc_nspace :xpath core::lang.ast.xpath %} +{% jdoc_nspace :jast java::lang.java.ast %} +{% jdoc_nspace :rule core::Rule %} +{% jdoc_nspace :lvh core::lang.LanguageVersionHandler %} +{% jdoc_nspace :rset core::RuleSet %} +{% jdoc_nspace :rsets core::RuleSets %} + +###### For internalization + +* The implementation of the adapters for the XPath engines Saxon and Jaxen (package {% jdoc_package :xpath %}) + are now deprecated. They'll be moved to an internal package come 7.0.0. Only {% jdoc xpath::Attribute %} remains public API. + +* The classes {% jdoc props::PropertyDescriptorField %}, {% jdoc props::builders.PropertyDescriptorBuilderConversionWrapper %}, and the methods + {% jdoc !c!:PDr#attributeValuesById %}, {% jdoc !c!:PDr#isDefinedExternally() %} and {% jdoc !c!props::PropertyTypeId#getFactory() %}. + These were used to read and write properties to and from XML, but were not intended as public API. + +* The class {% jdoc props::ValueParserConstants %} and the interface {% jdoc props::ValueParser %}. + +* All classes from {% jdoc_package java::lang.java.metrics.impl.visitors %} are now considered internal API. They're deprecated + and will be moved into an internal package with 7.0.0. To implement your own metrics visitors, + {% jdoc jast::JavaParserVisitorAdapter %} should be directly subclassed. + +* {% jdoc !ac!:lvh#getDataFlowHandler() %}, {% jdoc !ac!:lvh#getDFAGraphRule() %} + +* {% jdoc core::lang.VisitorStarter %} + +###### For removal + +* All classes from {% jdoc_package props::modules %} will be removed. + +* The interface {% jdoc jast::Dimensionable %} has been deprecated. + It gets in the way of a grammar change for 7.0.0 and won't be needed anymore (see [#997](https://github.com/pmd/pmd/issues/997)). + +* Several methods from {% jdoc jast::ASTLocalVariableDeclaration %} and {% jdoc jast::ASTFieldDeclaration %} have + also been deprecated: + + * {% jdoc jast::ASTFieldDeclaration %} won't be a {% jdoc jast::TypeNode %} come 7.0.0, so + {% jdoc jast::ASTFieldDeclaration#getType() %} and + {% jdoc jast::ASTFieldDeclaration#getTypeDefinition() %} are deprecated. + + * The method `getVariableName` on those two nodes will be removed, too. + + All these are deprecated because those nodes may declare several variables at once, possibly + with different types (and obviously with different names). They both implement `Iterator<`{% jdoc jast::ASTVariableDeclaratorId %}`>` + though, so you should iterate on each declared variable. See [#910](https://github.com/pmd/pmd/issues/910). + +* Visitor decorators are now deprecated and will be removed in PMD 7.0.0. They were originally a way to write + composable visitors, used in the metrics framework, but they didn't prove cost-effective. + + * In {% jdoc_package :jast %}: {% jdoc jast::JavaParserDecoratedVisitor %}, {% jdoc jast::JavaParserControllessVisitor %}, + {% jdoc jast::JavaParserControllessVisitorAdapter %}, and {% jdoc jast::JavaParserVisitorDecorator %} are deprecated with no intended replacement. + + +* The LanguageModules of several languages, that only support CPD execution, have been deprecated. These languages + are not fully supported by PMD, so having a language module does not make sense. The functionality of CPD is + not affected by this change. The following classes have been deprecated and will be removed with PMD 7.0.0: + + * {% jdoc cpp::lang.cpp.CppHandler %} + * {% jdoc cpp::lang.cpp.CppLanguageModule %} + * {% jdoc cpp::lang.cpp.CppParser %} + * {% jdoc cs::lang.cs.CsLanguageModule %} + * {% jdoc fortran::lang.fortran.FortranLanguageModule %} + * {% jdoc groovy::lang.groovy.GroovyLanguageModule %} + * {% jdoc matlab::lang.matlab.MatlabHandler %} + * {% jdoc matlab::lang.matlab.MatlabLanguageModule %} + * {% jdoc matlab::lang.matlab.MatlabParser %} + * {% jdoc objectivec::lang.objectivec.ObjectiveCHandler %} + * {% jdoc objectivec::lang.objectivec.ObjectiveCLanguageModule %} + * {% jdoc objectivec::lang.objectivec.ObjectiveCParser %} + * {% jdoc php::lang.php.PhpLanguageModule %} + * {% jdoc python::lang.python.PythonHandler %} + * {% jdoc python::lang.python.PythonLanguageModule %} + * {% jdoc python::lang.python.PythonParser %} + * {% jdoc ruby::lang.ruby.RubyLanguageModule %} + * {% jdoc scala::lang.scala.ScalaLanguageModule %} + * {% jdoc swift::lang.swift.SwiftLanguageModule %} + + +* Optional AST processing stages like symbol table, type resolution or data-flow analysis will be reified +in 7.0.0 to factorise common logic and make them extensible. Further explanations about this change can be +found on [#1426](https://github.com/pmd/pmd/pull/1426). Consequently, the following APIs are deprecated for +removal: + * In {% jdoc :rule %}: {% jdoc !a!:rule#isDfa() %}, {% jdoc !a!:rule#isTypeResolution() %}, {% jdoc !a!:rule#isMultifile() %} and their + respective setters. + * In {% jdoc :rset %}: {% jdoc !a!:rset#usesDFA(core::lang.Language) %}, {% jdoc !a!:rset#usesTypeResolution(core::lang.Language) %}, {% jdoc !a!:rset#usesMultifile(core::lang.Language) %} + * In {% jdoc :rsets %}: {% jdoc !a!:rsets#usesDFA(core::lang.Language) %}, {% jdoc !a!:rsets#usesTypeResolution(core::lang.Language) %}, {% jdoc !a!:rsets#usesMultifile(core::lang.Language) %} + * In {% jdoc :lvh %}: {% jdoc !a!:lvh#getDataFlowFacade() %}, {% jdoc !a!:lvh#getSymbolFacade() %}, {% jdoc !a!:lvh#getSymbolFacade(java.lang.ClassLoader) %}, + {% jdoc !a!:lvh#getTypeResolutionFacade(java.lang.ClassLoader) %}, {% jdoc !a!:lvh#getQualifiedNameResolutionFacade(java.lang.ClassLoader) %} + +#### 6.9.0 + +No changes. + #### 6.8.0 * A couple of methods and fields in `net.sourceforge.pmd.properties.AbstractPropertySource` have been diff --git a/docs/pages/pmd/rules/apex/codestyle.md b/docs/pages/pmd/rules/apex/codestyle.md index 5fc2a9d226..a158925f87 100644 --- a/docs/pages/pmd/rules/apex/codestyle.md +++ b/docs/pages/pmd/rules/apex/codestyle.md @@ -265,20 +265,20 @@ public class Foo { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|parameterSuffix||Method parameter variable suffixes|yes. Delimiter is ','.| -|parameterPrefix||Method parameter variable prefixes|yes. Delimiter is ','.| -|localSuffix||Local variable suffixes|yes. Delimiter is ','.| -|localPrefix||Local variable prefixes|yes. Delimiter is ','.| -|memberSuffix||Member variable suffixes|yes. Delimiter is ','.| -|memberPrefix||Member variable prefixes|yes. Delimiter is ','.| -|staticSuffix||Static variable suffixes|yes. Delimiter is ','.| -|staticPrefix||Static variable prefixes|yes. Delimiter is ','.| -|checkParameters|true|Check constructor and method parameter variables|no| -|checkLocals|true|Check local variables|no| |cc\_categories|Style|Code Climate Categories|yes. Delimiter is '\|'.| |cc\_remediation\_points\_multiplier|1|Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Code Climate Block Highlighting|no| |checkMembers|true|Check member variables|no| +|checkLocals|true|Check local variables|no| +|checkParameters|true|Check constructor and method parameter variables|no| +|staticPrefix||Static variable prefixes|yes. Delimiter is ','.| +|staticSuffix||Static variable suffixes|yes. Delimiter is ','.| +|memberPrefix||Member variable prefixes|yes. Delimiter is ','.| +|memberSuffix||Member variable suffixes|yes. Delimiter is ','.| +|localPrefix||Local variable prefixes|yes. Delimiter is ','.| +|localSuffix||Local variable suffixes|yes. Delimiter is ','.| +|parameterPrefix||Method parameter variable prefixes|yes. Delimiter is ','.| +|parameterSuffix||Method parameter variable suffixes|yes. Delimiter is ','.| **Use this rule by referencing it:** ``` xml diff --git a/docs/pages/pmd/rules/apex/design.md b/docs/pages/pmd/rules/apex/design.md index 5a82766001..b370a38063 100644 --- a/docs/pages/pmd/rules/apex/design.md +++ b/docs/pages/pmd/rules/apex/design.md @@ -437,12 +437,12 @@ public class Foo { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|showMethodsComplexity|true|Add method average violations to the report|no| -|showClassesComplexity|true|Add class average violations to the report|no| |cc\_categories|Style|Code Climate Categories|yes. Delimiter is '\|'.| |cc\_remediation\_points\_multiplier|1|Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Code Climate Block Highlighting|no| |reportLevel|10|Cyclomatic Complexity reporting threshold|no| +|showClassesComplexity|true|Add class average violations to the report|no| +|showMethodsComplexity|true|Add method average violations to the report|no| **Use this rule by referencing it:** ``` xml diff --git a/docs/pages/pmd/rules/java.md b/docs/pages/pmd/rules/java.md index cf9f0b9812..c38ef43bc1 100644 --- a/docs/pages/pmd/rules/java.md +++ b/docs/pages/pmd/rules/java.md @@ -146,7 +146,7 @@ folder: pmd/rules * [ExcessivePublicCount](pmd_rules_java_design.html#excessivepubliccount): Classes with large numbers of public methods and attributes require disproportionate testing effo... * [FinalFieldCouldBeStatic](pmd_rules_java_design.html#finalfieldcouldbestatic): If a final field is assigned to a compile-time constant, it could be made static, thus saving ove... * [GodClass](pmd_rules_java_design.html#godclass): The God Class rule detects the God Class design flaw using metrics. God classes do too many thing... -* [ImmutableField](pmd_rules_java_design.html#immutablefield): Identifies private fields whose values never change once they are initialized either in the decla... +* [ImmutableField](pmd_rules_java_design.html#immutablefield): Identifies private fields whose values never change once object initialization ends either in the... * [LawOfDemeter](pmd_rules_java_design.html#lawofdemeter): The Law of Demeter is a simple rule, that says "only talk to friends". It helps to reduce couplin... * [LogicInversion](pmd_rules_java_design.html#logicinversion): Use opposite operator instead of negating the whole expression with a logic complement operator. * [LoosePackageCoupling](pmd_rules_java_design.html#loosepackagecoupling): Avoid using classes from the configured package hierarchy outside of the package hierarchy, excep... diff --git a/docs/pages/pmd/rules/java/bestpractices.md b/docs/pages/pmd/rules/java/bestpractices.md index a0b1516ca3..bbd571f307 100644 --- a/docs/pages/pmd/rules/java/bestpractices.md +++ b/docs/pages/pmd/rules/java/bestpractices.md @@ -250,7 +250,7 @@ public class Foo { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|checkAddressTypes|IPv4 \| IPv6 \| IPv4 mapped IPv6|Check for IP address types.|yes. Delimiter is '\|'.| +|checkAddressTypes|IPv4 mapped IPv6 \| IPv6 \| IPv4|Check for IP address types.|yes. Delimiter is '\|'.| **Use this rule by referencing it:** ``` xml @@ -436,8 +436,8 @@ otherwise skip the associate String creation and manipulation. |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|guardsMethods|isTraceEnabled , isDebugEnabled , isInfoEnabled , isWarnEnabled , isErrorEnabled , isLoggable|method use to guard the log statement|yes. Delimiter is ','.| |logLevels|trace , debug , info , warn , error , log , finest , finer , fine , info , warning , severe|LogLevels to guard|yes. Delimiter is ','.| +|guardsMethods|isTraceEnabled , isDebugEnabled , isInfoEnabled , isWarnEnabled , isErrorEnabled , isLoggable|Method use to guard the log statement|yes. Delimiter is ','.| **Use this rule by referencing it:** ``` xml @@ -872,6 +872,7 @@ can lead to quite messy code. This rule looks for several declarations on the sa **This rule is defined by the following XPath expression:** ``` xpath //LocalVariableDeclaration + [not(parent::ForInit)] [count(VariableDeclarator) > 1] [$strictMode or count(distinct-values(VariableDeclarator/@BeginLine)) != count(VariableDeclarator)] | diff --git a/docs/pages/pmd/rules/java/codestyle.md b/docs/pages/pmd/rules/java/codestyle.md index fa2b23d8ce..d85dfaa1d6 100644 --- a/docs/pages/pmd/rules/java/codestyle.md +++ b/docs/pages/pmd/rules/java/codestyle.md @@ -463,8 +463,8 @@ public class Foo { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|regex|\\/\\\*\\s+(default\|package)\\s+\\\*\\/|Regular expression|no| |ignoredAnnotations|com.google.common.annotations.VisibleForTesting \| android.support.annotation.VisibleForTesting|Fully qualified names of the annotation types that should be ignored by this rule|yes. Delimiter is '\|'.| +|regex|\\/\\\*\\s+(default\|package)\\s+\\\*\\/|Regular expression|no| **Use this rule by referencing it:** ``` xml @@ -753,9 +753,9 @@ public class HelloWorldBean { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|ignoreInterfaceDeclarations|false|Ignore Interface Declarations that precede fields.|no| -|ignoreAnonymousClassDeclarations|true|Ignore Field Declarations, that are initialized with anonymous class declarations|no| |ignoreEnumDeclarations|true|Ignore Enum Declarations that precede fields.|no| +|ignoreAnonymousClassDeclarations|true|Ignore Field Declarations, that are initialized with anonymous class declarations|no| +|ignoreInterfaceDeclarations|false|Ignore Interface Declarations that precede fields.|no| **Use this rule by referencing it:** ``` xml @@ -1145,16 +1145,16 @@ public class LinguisticNaming { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|booleanFieldPrefixes|is \| has \| can \| have \| will \| should|The prefixes of fields and variables that indicate boolean.|yes. Delimiter is '\|'.| -|checkVariables|true|Check local variable names and types for inconsistent naming.|no| -|checkFields|true|Check field names and types for inconsistent naming.|no| -|transformMethodNames|to \| as|The prefixes and infixes that indicate a transform method.|yes. Delimiter is '\|'.| -|booleanMethodPrefixes|is \| has \| can \| have \| will \| should|The prefixes of methods that return boolean.|yes. Delimiter is '\|'.| +|checkBooleanMethod|true|Check method names and types for inconsistent naming.|no| +|checkGetters|true|Check return type of getters.|no| +|checkSetters|true|Check return type of setters.|no| |checkPrefixedTransformMethods|true|Check return type of methods whose names start with the configured prefix (see transformMethodNames property).|no| |checkTransformMethods|false|Check return type of methods which contain the configured infix in their name (see transformMethodNames property).|no| -|checkSetters|true|Check return type of setters.|no| -|checkGetters|true|Check return type of getters.|no| -|checkBooleanMethod|true|Check method names and types for inconsistent naming.|no| +|booleanMethodPrefixes|is \| has \| can \| have \| will \| should|The prefixes of methods that return boolean.|yes. Delimiter is '\|'.| +|transformMethodNames|to \| as|The prefixes and infixes that indicate a transform method.|yes. Delimiter is '\|'.| +|checkFields|true|Check field names and types for inconsistent naming.|no| +|checkVariables|true|Check local variable names and types for inconsistent naming.|no| +|booleanFieldPrefixes|is \| has \| can \| have \| will \| should|The prefixes of fields and variables that indicate boolean.|yes. Delimiter is '\|'.| **Use this rule by referencing it:** ``` xml @@ -1254,6 +1254,12 @@ public class Bar { } ``` +**This rule has the following properties:** + +|Name|Default Value|Description|Multivalued| +|----|-------------|-----------|-----------| +|ignoreForEachDecl|false|Ignore non-final loop variables in a for-each statement.|no| + **Use this rule by referencing it:** ``` xml @@ -2295,11 +2301,11 @@ public class Foo { |memberSuffix||Member variable suffixes|yes. Delimiter is ','.| |memberPrefix||Member variable prefixes|yes. Delimiter is ','.| |staticSuffix||Static variable suffixes|yes. Delimiter is ','.| +|staticPrefix||Static variable prefixes|yes. Delimiter is ','.| +|checkMembers|true|Check member variables|no| +|checkLocals|true|Check local variables|no| |checkParameters|true|Check constructor and method parameter variables|no| |checkNativeMethodParameters|true|Check method parameter of native methods|no| -|staticPrefix||Static variable prefixes|yes. Delimiter is ','.| -|checkLocals|true|Check local variables|no| -|checkMembers|true|Check member variables|no| **Use this rule by referencing it:** ``` xml diff --git a/docs/pages/pmd/rules/java/design.md b/docs/pages/pmd/rules/java/design.md index 758dce0ba1..0fbd7f263d 100644 --- a/docs/pages/pmd/rules/java/design.md +++ b/docs/pages/pmd/rules/java/design.md @@ -457,9 +457,9 @@ class Foo { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|cycloOptions||Choose options for the computation of Cyclo|yes. Delimiter is '\|'.| |classReportLevel|80|Total class complexity reporting threshold|no| |methodReportLevel|10|Cyclomatic complexity reporting threshold|no| +|cycloOptions||Choose options for the computation of Cyclo|yes. Delimiter is '\|'.| |reportLevel|10|Deprecated Cyclomatic Complexity reporting threshold|no| **Use this rule by referencing it:** @@ -824,7 +824,7 @@ of Object-Oriented Systems. Springer, Berlin, 1 edition, October 2006. Page 80. **Priority:** Medium (3) -Identifies private fields whose values never change once they are initialized either in the declaration +Identifies private fields whose values never change once object initialization ends either in the declaration of the field or by a constructor. This helps in converting existing classes to becoming immutable ones. **This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.design.ImmutableFieldRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ImmutableFieldRule.java) @@ -965,8 +965,8 @@ public class Bar { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|classes||Allowed classes|yes. Delimiter is ','.| |packages||Restricted packages|yes. Delimiter is ','.| +|classes||Allowed classes|yes. Delimiter is ','.| **Use this rule by referencing it:** ``` xml @@ -1134,9 +1134,9 @@ class Foo { // +1, total Ncss = 12 |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|ncssOptions||Choose options for the calculation of Ncss|yes. Delimiter is '\|'.| |methodReportLevel|60|NCSS reporting threshold for methods|no| |classReportLevel|1500|NCSS reporting threshold for classes|no| +|ncssOptions||Choose options for the computation of Ncss|yes. Delimiter is '\|'.| **Use this rule by referencing it:** ``` xml @@ -1292,8 +1292,8 @@ public class Foo { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|minimum|200.0|Deprecated Minimum reporting threshold|no| |reportLevel|200|N-Path Complexity reporting threshold|no| +|minimum|200.0|Deprecated Minimum reporting threshold|no| **Use this rule by referencing it:** ``` xml @@ -1577,9 +1577,9 @@ public class Foo { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|disallowNotAssignment|false|Disallow violations where the first usage is not an assignment|no| -|checkInnerClasses|false|Check inner classes|no| |ignoredAnnotations|lombok.Setter \| lombok.Getter \| lombok.Builder \| lombok.Data \| lombok.RequiredArgsConstructor \| lombok.AllArgsConstructor \| lombok.Value \| lombok.NoArgsConstructor|Fully qualified names of the annotation types that should be ignored by this rule|yes. Delimiter is '\|'.| +|checkInnerClasses|false|Check inner classes|no| +|disallowNotAssignment|false|Disallow violations where the first usage is not an assignment|no| **Use this rule by referencing it:** ``` xml diff --git a/docs/pages/pmd/rules/java/documentation.md b/docs/pages/pmd/rules/java/documentation.md index 5a9a0014e3..0cdedbf1a5 100644 --- a/docs/pages/pmd/rules/java/documentation.md +++ b/docs/pages/pmd/rules/java/documentation.md @@ -29,8 +29,8 @@ A rule for the politically correct... we don't want to offend anyone. |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|disallowedTerms|idiot \| jerk|Illegal terms or phrases|yes. Delimiter is '\|'.| |caseSensitive|false|Case sensitive|no| +|disallowedTerms|idiot \| jerk|Illegal terms or phrases|yes. Delimiter is '\|'.| **Use this rule by referencing it:** ``` xml @@ -61,14 +61,14 @@ Denotes whether comments are required (or unwanted) for specific language elemen |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|serialVersionUIDCommentRequired|Ignored|Serial version UID comments. Possible values: \[Required, Ignored, Unwanted\]|no| -|enumCommentRequirement|Required|Enum comments. Possible values: \[Required, Ignored, Unwanted\]|no| -|protectedMethodCommentRequirement|Required|Protected method constructor comments. Possible values: \[Required, Ignored, Unwanted\]|no| -|publicMethodCommentRequirement|Required|Public method and constructor comments. Possible values: \[Required, Ignored, Unwanted\]|no| -|fieldCommentRequirement|Required|Field comments. Possible values: \[Required, Ignored, Unwanted\]|no| -|headerCommentRequirement|Required|Header comments. Possible values: \[Required, Ignored, Unwanted\]|no| |methodWithOverrideCommentRequirement|Ignored|Comments on @Override methods. Possible values: \[Required, Ignored, Unwanted\]|no| |accessorCommentRequirement|Ignored|Comments on getters and setters". Possible values: \[Required, Ignored, Unwanted\]|no| +|headerCommentRequirement|Required|Header comments. Possible values: \[Required, Ignored, Unwanted\]|no| +|fieldCommentRequirement|Required|Field comments. Possible values: \[Required, Ignored, Unwanted\]|no| +|publicMethodCommentRequirement|Required|Public method and constructor comments. Possible values: \[Required, Ignored, Unwanted\]|no| +|protectedMethodCommentRequirement|Required|Protected method constructor comments. Possible values: \[Required, Ignored, Unwanted\]|no| +|enumCommentRequirement|Required|Enum comments. Possible values: \[Required, Ignored, Unwanted\]|no| +|serialVersionUIDCommentRequired|Ignored|Serial version UID comments. Possible values: \[Required, Ignored, Unwanted\]|no| **Use this rule by referencing it:** ``` xml diff --git a/docs/pages/pmd/rules/java/errorprone.md b/docs/pages/pmd/rules/java/errorprone.md index f121824376..173243fa7a 100644 --- a/docs/pages/pmd/rules/java/errorprone.md +++ b/docs/pages/pmd/rules/java/errorprone.md @@ -34,10 +34,10 @@ public void bar() { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|allowIncrementDecrement|false|Allow increment or decrement operators within the conditional expression of an if, for, or while statement|no| -|allowWhile|false|Allow assignment within the conditional expression of a while statement|no| -|allowFor|false|Allow assignment within the conditional expression of a for statement|no| |allowIf|false|Allow assignment within the conditional expression of an if statement|no| +|allowFor|false|Allow assignment within the conditional expression of a for statement|no| +|allowWhile|false|Allow assignment within the conditional expression of a while statement|no| +|allowIncrementDecrement|false|Allow increment or decrement operators within the conditional expression of an if, for, or while statement|no| **Use this rule by referencing it:** ``` xml @@ -205,9 +205,9 @@ for (int i = 0; i < 10; i++) { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|checkReturnLoopTypes|for \| do \| while|Check for return statements in loop types|yes. Delimiter is '\|'.| -|checkContinueLoopTypes|for \| do \| while|Check for continue statements in loop types|yes. Delimiter is '\|'.| -|checkBreakLoopTypes|for \| do \| while|Check for break statements in loop types|yes. Delimiter is '\|'.| +|checkBreakLoopTypes|for \| do \| while|List of loop types in which break statements will be checked|yes. Delimiter is '\|'.| +|checkContinueLoopTypes|for \| do \| while|List of loop types in which continue statements will be checked|yes. Delimiter is '\|'.| +|checkReturnLoopTypes|for \| do \| while|List of loop types in which return statements will be checked|yes. Delimiter is '\|'.| **Use this rule by referencing it:** ``` xml @@ -382,12 +382,12 @@ private void buz(String x) {} |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|exceptionfile||File containing strings to skip (one string per line), only used if ignore list is not set. File must be UTF-8 encoded.|no| +|exceptionfile||Deprecated (Use 'exceptionList' property) File containing strings to skip (one string per line), only used if ignore list is not set. File must be UTF-8 encoded.|no| |separator|,|Ignore list separator|no| -|exceptionList||Strings to ignore|no| |maxDuplicateLiterals|4|Max duplicate literals|no| |minimumLength|3|Minimum string length to check|no| |skipAnnotations|false|Skip literals within annotations|no| +|exceptionList||List of literals to ignore. A literal is ignored if its image can be found in this list. Components of this list should not be surrounded by double quotes.|no| **Use this rule by referencing it:** ``` xml @@ -1124,9 +1124,9 @@ public class Bar { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|closeAsDefaultTarget|true|Consider 'close' as a target by default|no| -|types|java.sql.Connection , java.sql.Statement , java.sql.ResultSet|Affected types|yes. Delimiter is ','.| |closeTargets||Methods which may close this resource|yes. Delimiter is ','.| +|types|java.sql.Connection , java.sql.Statement , java.sql.ResultSet|Affected types|yes. Delimiter is ','.| +|closeAsDefaultTarget|true|Consider 'close' as a target by default|no| **Use this rule by referencing it:** ``` xml @@ -1232,8 +1232,8 @@ public void foo() { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|maxViolations|100|Maximum number of anomalies per class|no| |maxPaths|1000|Maximum number of checked paths per method. A lower value will increase the performance of the rule but may decrease anomalies found.|no| +|maxViolations|100|Maximum number of anomalies per class|no| **Use this rule by referencing it:** ``` xml @@ -2790,7 +2790,7 @@ Avoid returning from a finally block, this can discard exceptions. **This rule is defined by the following XPath expression:** ``` xpath -//FinallyStatement//ReturnStatement +//FinallyStatement//ReturnStatement except //FinallyStatement//(MethodDeclaration|LambdaExpression)//ReturnStatement ``` **Example(s):** diff --git a/docs/pages/pmd/rules/java/multithreading.md b/docs/pages/pmd/rules/java/multithreading.md index 5f7d2684a9..4a26764383 100644 --- a/docs/pages/pmd/rules/java/multithreading.md +++ b/docs/pages/pmd/rules/java/multithreading.md @@ -265,8 +265,8 @@ public static Foo getFoo() { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|checkNonStaticFields|false|Check for non-static fields. Do not set this to true and checkNonStaticMethods to false.|no| |checkNonStaticMethods|true|Check for non-static methods. Do not set this to false and checkNonStaticFields to true.|no| +|checkNonStaticFields|false|Check for non-static fields. Do not set this to true and checkNonStaticMethods to false.|no| **Use this rule by referencing it:** ``` xml diff --git a/docs/pages/pmd/rules/java/performance.md b/docs/pages/pmd/rules/java/performance.md index 80ca0ca67f..adb891150c 100644 --- a/docs/pages/pmd/rules/java/performance.md +++ b/docs/pages/pmd/rules/java/performance.md @@ -121,15 +121,23 @@ public class Test { **Minimum Language Version:** Java 1.7 -The FileInputStream and FileOutputStream classes contains a finalizer method which will cause garbage collection pauses. See [JDK-8080225](https://bugs.openjdk.java.net/browse/JDK-8080225) for details. +The FileInputStream and FileOutputStream classes contains a finalizer method which will cause garbage +collection pauses. +See [JDK-8080225](https://bugs.openjdk.java.net/browse/JDK-8080225) for details. -The FileReader and FileWriter constructors instantiate FileInputStream and FileOutputStream, again causing garbage collection issues while finalizer methods are called. +The FileReader and FileWriter constructors instantiate FileInputStream and FileOutputStream, +again causing garbage collection issues while finalizer methods are called. * Use `Files.newInputStream(Paths.get(fileName))` instead of `new FileInputStream(fileName)`. * Use `Files.newOutputStream(Paths.get(fileName))` instead of `new FileOutputStream(fileName)`. * Use `Files.newBufferedReader(Paths.get(fileName))` instead of `new FileReader(fileName)`. * Use `Files.newBufferedWriter(Paths.get(fileName))` instead of `new FileWriter(fileName)`. +Please note, that the `java.nio` API does not throw a `FileNotFoundException` anymore, instead +it throws a `NoSuchFileException`. If your code dealt explicitly with a `FileNotFoundException`, +then this needs to be adjusted. Both exceptions are subclasses of `IOException`, so catching +that one covers both. + **This rule is defined by the following XPath expression:** ``` xpath //PrimaryPrefix/AllocationExpression/ClassOrInterfaceType[ diff --git a/docs/pages/pmd/userdocs/extending/metrics_howto.md b/docs/pages/pmd/userdocs/extending/metrics_howto.md index 5320ca2580..896bf1e409 100644 --- a/docs/pages/pmd/userdocs/extending/metrics_howto.md +++ b/docs/pages/pmd/userdocs/extending/metrics_howto.md @@ -248,11 +248,6 @@ the Java framework but it's symmetrical in the Apex framework. or [NCSS](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/NcssMetric.java). Additionnally, it makes your metric more easily generalisable to other node types. - {%include tip.html - content="All visitor metrics shipped with PMD define their visitor - publicly, so that you may extend it to override its behaviour - easily. You can find them in the package `n.s.pmd.lang..metrics.impl.visitors`." %} - * *Signature matching metrics:* That's even more straightforward when you want to count the number of methods or fields that match a specific signature, e.g. public static final fields. Basically a signature is an object that describes diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 40a3244a78..02bcd29228 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -19,118 +19,29 @@ This is a {{ site.pmd.release_type }} release. ### New and noteworthy -#### Kotlin support for CPD - -Thanks to [Maikel Steneker](https://github.com/maikelsteneker), CPD now supports [Kotlin](https://kotlinlang.org/). -This means, you can use CPD to find duplicated code in your Kotlin projects. - -#### New Rules - -* The new Java rule {% rule "java/codestyle/UseUnderscoresInNumericLiterals" %} (`java-codestyle`) - verifies that numeric literals over a given length (4 chars by default, but configurable) are using - underscores every 3 digits for readability. The rule only applies to Java 7+ codebases. - #### Modified Rules -* The Java rule {% rule "java/bestpractices/JUnitTestsShouldIncludeAssert" %} (`java-bestpractices`) - now also detects [Soft Assertions](https://github.com/joel-costigliola/assertj-core). +* The Java rule {% rule "java/codestyle/LocalVariableCouldBeFinal" %} (`java-codestyle`) has a new + property `ignoreForEachDecl`, which is by default disabled. The new property allows for ignoring + non-final loop variables in a for-each statement. ### Fixed Issues -* all - * [#1284](https://github.com/pmd/pmd/issues/1284): \[doc] Keep record of every currently deprecated API - * [#1318](https://github.com/pmd/pmd/issues/1318): \[test] Kotlin DSL to ease test writing - * [#1328](https://github.com/pmd/pmd/issues/1328): \[ci] Building docs for release fails - * [#1341](https://github.com/pmd/pmd/issues/1341): \[doc] Documentation Error with Regex Properties - * [#1468](https://github.com/pmd/pmd/issues/1468): \[doc] Missing escaping leads to XSS -* java - * [#1460](https://github.com/pmd/pmd/issues/1460): \[java] Intermittent PMD failure : PMD processing errors while no violations reported + * java-bestpractices - * [#1435](https://github.com/pmd/pmd/issues/1435): \[java] JUnitTestsShouldIncludeAssert: Support AssertJ soft assertions + * [#658](https://github.com/pmd/pmd/issues/658): \[java] OneDeclarationPerLine: False positive for loops * java-codestyle - * [#1232](https://github.com/pmd/pmd/issues/1232): \[java] Detector for large numbers not separated by _ - * [#1372](https://github.com/pmd/pmd/issues/1372): \[java] false positive for UselessQualifiedThis - * [#1440](https://github.com/pmd/pmd/issues/1440): \[java] CommentDefaultAccessModifierRule shows incorrect message + * [#1513](https://github.com/pmd/pmd/issues/1513): \[java] LocalVariableCouldBeFinal: allow excluding the variable in a for-each loop +* java-errorprone + * [#1035](https://github.com/pmd/pmd/issues/1035): \[java] ReturnFromFinallyBlock: False positive on lambda expression in finally block ### API Changes -#### Properties framework - -The properties framework is about to get a lifting, and for that reason, the following APIs are -now deprecated until 7.0.0. The proposed changes to the API are described [on the wiki](https://github.com/pmd/pmd/wiki/Property-framework-7-0-0) - -* Several classes and interfaces from the properties framework are now deprecated and will be removed with 7.0.0. - * `MethodProperty`, `FloatProperty`, `FileProperty`, `TypeProperty` and their multi-valued counterparts - are discontinued for lack of a use-case, and will probably not be replaced with 7.0.0. - Users of `FloatProperty` should consider using a `DoubleProperty`. - * `EnumeratedPropertyDescriptor`, `NumericPropertyDescriptor`, `PackagedPropertyDescriptor`, and the related builders - (in `net.sourceforge.pmd.properties.builders`) will be removed. In the future, these interfaces won't be around - but their functionality will, under another form. The related methods `PropertyTypeId#isPropertyNumeric` and - `PropertyTypeId#isPropertyPackaged` are also deprecated. - * All classes of net.sourceforge.pmd.properties.modules are deprecated and will be removed. They were - never intended as public api. - * The classes `PropertyDescriptorField`, `PropertyDescriptorBuilderConversionWrapper`, and the methods - `PropertyDescriptor#attributeValuesById`, `PropertyDescriptor#isDefinedExternally` and `PropertyTypeId#getFactory` are deprecated with no - intended replacement. These were used to read and write properties to and from XML, and were never - intended as public API. - * The class `ValueParserConstants` and the interface `ValueParser` are deprecated with no intended replacement, - they were not intended as public API. - * Methods from `PropertyDescriptor`: - * `preferredRowCount` is deprecated with no intended replacement. It was never implemented, and does not belong - in this interface. The methods `uiOrder` and `compareTo` are deprecated for the same reason. These methods mix presentation logic - with business logic and are not necessary for PropertyDescriptors to work. `PropertyDescriptor` will not - extend `Comparable` anymore come 7.0.0. - * The method `PropertyDescriptor#propertyErrorFor` is deprecated and will be removed with no intended - replacement. It's really just a shortcut for `prop.errorFor(rule.getProperty(prop))`. - * `T valueFrom(String)` and `String asDelimitedString(T)` are deprecated and will be removed. These were - used to serialize and deserialize properties to/from a string, but 7.0.0 will introduce a more flexible - XML syntax which will make them obsolete. - * `isMultiValue` and `type` are deprecated and won't be replaced. The new XML syntax will remove the need - for a divide between multi- and single-value properties, and will allow arbitrary types to be represented. - Since arbitrary types may be represented, `type` will become obsolete as it can't represent generic types, - which will nevertheless be representable with the XML syntax. It was only used for documentation, but a - new way to document these properties exhaustively will be added with 7.0.0. - * `errorFor` is deprecated as its return type will be changed to `Optional` with the shift to Java 8. - -#### Deprecated APIs - -{% jdoc_nspace :xpath core::lang.ast.xpath %} -{% jdoc_nspace :jast java::lang.java.ast %} - -* The implementation of the adapters for the XPath engines Saxon and Jaxen (package {% jdoc_package :xpath %}) - are now deprecated. They'll be moved to an internal package come 7.0.0. Only {% jdoc xpath::Attribute %} remains public API. - -* The interface {% jdoc jast::Dimensionable %} has been deprecated. - It gets in the way of a grammar change for 7.0.0 and won't be needed anymore (see [#997](https://github.com/pmd/pmd/issues/997)). - -* Several methods from {% jdoc jast::ASTLocalVariableDeclaration %} and {% jdoc jast::ASTFieldDeclaration %} have - also been deprecated: - - * {% jdoc jast::ASTFieldDeclaration %} won't be a {% jdoc jast::TypeNode %} come 7.0.0, so - {% jdoc jast::ASTFieldDeclaration#getType() %} and - {% jdoc jast::ASTFieldDeclaration#getTypeDefinition() %} are deprecated. - - * The method `getVariableName` on those two nodes will be removed, too. - - All these are deprecated because those nodes may declare several variables at once, possibly - with different types (and obviously with different names). They both implement `Iterator<`{% jdoc jast::ASTVariableDeclaratorId %}`>` - though, so you should iterate on each declared variable. See [#910](https://github.com/pmd/pmd/issues/910). - ### External Contributions -* [#1384](https://github.com/pmd/pmd/pull/1384): \[java] New Rule - UseUnderscoresInNumericLiterals - [RajeshR](https://github.com/rajeshggwp) -* [#1424](https://github.com/pmd/pmd/pull/1424): \[doc] #1341 Updating Regex Values in default Value Property - [avishvat](https://github.com/vishva007) -* [#1428](https://github.com/pmd/pmd/pull/1428): \[core] Upgrading JCommander from 1.48 to 1.72 - [Thunderforge](https://github.com/Thunderforge) -* [#1430](https://github.com/pmd/pmd/pull/1430): \[doc] Who really knows regex? - [Dem Pilafian](https://github.com/dpilafian) -* [#1434](https://github.com/pmd/pmd/pull/1434): \[java] JUnitTestsShouldIncludeAssert: Recognize AssertJ soft assertions as valid assert statements - [Loïc Ledoyen](https://github.com/ledoyen) -* [#1441](https://github.com/pmd/pmd/pull/1441): \[kotlin] [cpd] Added CPD support for Kotlin - [Maikel Steneker](https://github.com/maikelsteneker) -* [#1447](https://github.com/pmd/pmd/pull/1447): \[fortran] Use diamond operator in impl - [reudismam](https://github.com/reudismam) -* [#1453](https://github.com/pmd/pmd/pull/1453): \[java] Adding the fix for #1440. Showing correct message for CommentDefaultAccessmodifier. - [Rohit Kumar](https://github.com/stationeros) -* [#1464](https://github.com/pmd/pmd/pull/1464): \[doc] Fix XSS on documentation web page - [Maxime Robert](https://github.com/marob) -* [#1469](https://github.com/pmd/pmd/pull/1469): \[core] Configurable max loops in DAAPathFinder - [Alberto Fernández](https://github.com/albfernandez) +* [#1503](https://github.com/pmd/pmd/pull/1503): \[java] Fix for ReturnFromFinallyBlock false-positives - [RishabhDeep Singh](https://github.com/rishabhdeepsingh) +* [#1514](https://github.com/pmd/pmd/pull/1514): \[java] LocalVariableCouldBeFinal: allow excluding the variable in a for-each loop - [Kris Scheibe](https://github.com/kris-scheibe) +* [#1516](https://github.com/pmd/pmd/pull/1516): \[java] OneDeclarationPerLine: Don't report multiple variables in a for statement. - [Kris Scheibe](https://github.com/kris-scheibe) +* [#1521](https://github.com/pmd/pmd/pull/1521): \[java] Upgrade to ASM7 for JDK 11 support - [Mark Pritchard](https://github.com/markpritchard) {% endtocmaker %} -{% unless is_release_notes_processor %} - {% include note.html content="The release notes of previous versions are available [here](pmd_release_notes_old.html)" %} -{% endunless %} - diff --git a/docs/pages/release_notes_old.md b/docs/pages/release_notes_old.md index d7110b6473..f158cc99c3 100644 --- a/docs/pages/release_notes_old.md +++ b/docs/pages/release_notes_old.md @@ -5,6 +5,287 @@ permalink: pmd_release_notes_old.html Previous versions of PMD can be downloaded here: https://github.com/pmd/pmd/releases +## 09-December-2018 - 6.10.0 + +The PMD team is pleased to announce PMD 6.10.0. + +This is a minor release. + +### Table Of Contents + +* [New and noteworthy](#new-and-noteworthy) + * [Kotlin support for CPD](#kotlin-support-for-cpd) + * [New Rules](#new-rules) + * [Modified Rules](#modified-rules) +* [Fixed Issues](#fixed-issues) +* [API Changes](#api-changes) + * [Properties framework](#properties-framework) + * [Changes to how you define properties](#changes-to-how-you-define-properties) + * [Architectural simplifications](#architectural-simplifications) + * [Changes to the PropertyDescriptor interface](#changes-to-the-propertydescriptor-interface) + * [Deprecated APIs](#deprecated-apis) + * [For internalization](#for-internalization) + * [For removal](#for-removal) +* [External Contributions](#external-contributions) + +### New and noteworthy + +#### Kotlin support for CPD + +Thanks to [Maikel Steneker](https://github.com/maikelsteneker), CPD now supports [Kotlin](https://kotlinlang.org/). +This means, you can use CPD to find duplicated code in your Kotlin projects. + +#### New Rules + +* The new Java rule [`UseUnderscoresInNumericLiterals`](https://pmd.github.io/pmd-6.10.0/pmd_rules_java_codestyle.html#useunderscoresinnumericliterals) (`java-codestyle`) + verifies that numeric literals over a given length (4 chars by default, but configurable) are using + underscores every 3 digits for readability. The rule only applies to Java 7+ codebases. + +#### Modified Rules + +* The Java rule [`JUnitTestsShouldIncludeAssert`](https://pmd.github.io/pmd-6.10.0/pmd_rules_java_bestpractices.html#junittestsshouldincludeassert) (`java-bestpractices`) + now also detects [Soft Assertions](https://github.com/joel-costigliola/assertj-core). + +* The property `exceptionfile` of the rule [`AvoidDuplicateLiterals`](https://pmd.github.io/pmd-6.10.0/pmd_rules_java_errorprone.html#avoidduplicateliterals) (`java-errorprone`) + has been deprecated and will be removed with 7.0.0. Please use `exceptionList` instead. + +### Fixed Issues +* all + * [#1284](https://github.com/pmd/pmd/issues/1284): \[doc] Keep record of every currently deprecated API + * [#1318](https://github.com/pmd/pmd/issues/1318): \[test] Kotlin DSL to ease test writing + * [#1328](https://github.com/pmd/pmd/issues/1328): \[ci] Building docs for release fails + * [#1341](https://github.com/pmd/pmd/issues/1341): \[doc] Documentation Error with Regex Properties + * [#1468](https://github.com/pmd/pmd/issues/1468): \[doc] Missing escaping leads to XSS + * [#1471](https://github.com/pmd/pmd/issues/1471): \[core] XMLRenderer: ProcessingErrors from exceptions without a message missing + * [#1477](https://github.com/pmd/pmd/issues/1477): \[core] Analysis cache fails with wildcard classpath entries +* java + * [#1460](https://github.com/pmd/pmd/issues/1460): \[java] Intermittent PMD failure : PMD processing errors while no violations reported +* java-bestpractices + * [#647](https://github.com/pmd/pmd/issues/647): \[java] JUnitTestsShouldIncludeAssertRule should support `this.exception` as well as just `exception` + * [#1435](https://github.com/pmd/pmd/issues/1435): \[java] JUnitTestsShouldIncludeAssert: Support AssertJ soft assertions +* java-codestyle + * [#1232](https://github.com/pmd/pmd/issues/1232): \[java] Detector for large numbers not separated by _ + * [#1372](https://github.com/pmd/pmd/issues/1372): \[java] false positive for UselessQualifiedThis + * [#1440](https://github.com/pmd/pmd/issues/1440): \[java] CommentDefaultAccessModifierRule shows incorrect message +* java-design + * [#1151](https://github.com/pmd/pmd/issues/1151): \[java] ImmutableField false positive with multiple constructors + * [#1483](https://github.com/pmd/pmd/issues/1483): \[java] Cyclo metric should count conditions of for statements correctly +* java-errorprone + * [#1512](https://github.com/pmd/pmd/issues/1512): \[java] InvalidSlf4jMessageFormatRule causes NPE in lambda and static blocks +* plsql + * [#1454](https://github.com/pmd/pmd/issues/1454): \[plsql] ParseException for IF/CASE statement with >=, <=, != + + +### API Changes + +#### Properties framework + + + + + +The properties framework is about to get a lifting, and for that reason, we need to deprecate a lot of APIs +to remove them in 7.0.0. The proposed changes to the API are described [on the wiki](https://github.com/pmd/pmd/wiki/Property-framework-7-0-0) + +##### Changes to how you define properties + + +* Construction of property descriptors has been possible through builders since 6.0.0. The 7.0.0 API will only allow +construction through builders. The builder hierarchy, currently found in the package [`net.sourceforge.pmd.properties.builders`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/builders/package-summary.html#), +is being replaced by the simpler [`PropertyBuilder`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/PropertyBuilder.html#). Their APIs enjoy a high degree of source compatibility. + +* Concrete property classes like [`IntegerProperty`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/IntegerProperty.html#) and [`StringMultiProperty`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/StringMultiProperty.html#) will gradually +all be deprecated until 7.0.0. Their usages should be replaced by direct usage of the [`PropertyDescriptor`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/PropertyDescriptor.html#) +interface, e.g. `PropertyDescriptor` or `PropertyDescriptor>`. + +* Instead of spreading properties across countless classes, the utility class [`PropertyFactory`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/PropertyFactory.html#) will become +from 7.0.0 on the only provider for property descriptor builders. Each current property type will be replaced +by a corresponding method on `PropertyFactory`: + * [`IntegerProperty`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/IntegerProperty.html#) is replaced by [`PropertyFactory#intProperty`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/PropertyFactory.html#intProperty(java.lang.String)) + * [`IntegerMultiProperty`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/IntegerMultiProperty.html#) is replaced by [`PropertyFactory#intListProperty`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/PropertyFactory.html#intListProperty(java.lang.String)) + + * [`FloatProperty`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/FloatProperty.html#) and [`DoubleProperty`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/DoubleProperty.html#) are both replaced by [`PropertyFactory#doubleProperty`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/PropertyFactory.html#doubleProperty(java.lang.String)). + Having a separate property for floats wasn't that useful. + * Similarly, [`FloatMultiProperty`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/FloatMultiProperty.html#) and [`DoubleMultiProperty`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/DoubleMultiProperty.html#) are replaced by [`PropertyFactory#doubleListProperty`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/PropertyFactory.html#doubleListProperty(java.lang.String)). + + * [`StringProperty`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/StringProperty.html#) is replaced by [`PropertyFactory#stringProperty`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/PropertyFactory.html#stringProperty(java.lang.String)) + * [`StringMultiProperty`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/StringMultiProperty.html#) is replaced by [`PropertyFactory#stringListProperty`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/PropertyFactory.html#stringListProperty(java.lang.String)) + + * [`RegexProperty`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/RegexProperty.html#) is replaced by [`PropertyFactory#regexProperty`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/PropertyFactory.html#regexProperty(java.lang.String)) + + * [`EnumeratedProperty`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/EnumeratedProperty.html#) is replaced by [`PropertyFactory#enumProperty`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/PropertyFactory.html#enumProperty(java.lang.String,java.util.Map)) + * [`EnumeratedProperty`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/EnumeratedProperty.html#) is replaced by [`PropertyFactory#enumListProperty`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/PropertyFactory.html#enumListProperty(java.lang.String,java.util.Map)) + + * [`BooleanProperty`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/BooleanProperty.html#) is replaced by [`PropertyFactory#booleanProperty`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/PropertyFactory.html#booleanProperty(java.lang.String)) + * Its multi-valued counterpart, [`BooleanMultiProperty`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/BooleanMultiProperty.html#), is not replaced, because it doesn't have a use case. + + * [`CharacterProperty`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/CharacterProperty.html#) is replaced by [`PropertyFactory#charProperty`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/PropertyFactory.html#charProperty(java.lang.String)) + * [`CharacterMultiProperty`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/CharacterMultiProperty.html#) is replaced by [`PropertyFactory#charListProperty`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/PropertyFactory.html#charListProperty(java.lang.String)) + + * [`LongProperty`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/LongProperty.html#) is replaced by [`PropertyFactory#longIntProperty`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/PropertyFactory.html#longIntProperty(java.lang.String)) + * [`LongMultiProperty`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/LongMultiProperty.html#) is replaced by [`PropertyFactory#longIntListProperty`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/PropertyFactory.html#longIntListProperty(java.lang.String)) + + * [`MethodProperty`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/MethodProperty.html#), [`FileProperty`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/FileProperty.html#), [`TypeProperty`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/TypeProperty.html#) and their multi-valued counterparts + are discontinued for lack of a use-case, and have no planned replacement in 7.0.0 for now. + + + +Here's an example: +```java +// Before 7.0.0, these are equivalent: +IntegerProperty myProperty = new IntegerProperty("score", "Top score value", 1, 100, 40, 3.0f); +IntegerProperty myProperty = IntegerProperty.named("score").desc("Top score value").range(1, 100).defaultValue(40).uiOrder(3.0f); + +// They both map to the following in 7.0.0 +PropertyDescriptor myProperty = PropertyFactory.intProperty("score").desc("Top score value").require(inRange(1, 100)).defaultValue(40); +``` + +You're highly encouraged to migrate to using this new API as soon as possible, to ease your migration to 7.0.0. + + + +##### Architectural simplifications + +* [`EnumeratedPropertyDescriptor`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/EnumeratedPropertyDescriptor.html#), [`NumericPropertyDescriptor`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/NumericPropertyDescriptor.html#), [`PackagedPropertyDescriptor`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/PackagedPropertyDescriptor.html#), +and the related builders (in [`net.sourceforge.pmd.properties.builders`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/builders/package-summary.html#)) will be removed. +These specialized interfaces allowed additional constraints to be enforced on the +value of a property, but made the property class hierarchy very large and impractical +to maintain. Their functionality will be mapped uniformly to [`PropertyConstraint`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/constraints/PropertyConstraint.html#)s, +which will allow virtually any constraint to be defined, and improve documentation and error reporting. The +related methods [`PropertyTypeId#isPropertyNumeric`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/PropertyTypeId.html#isPropertyNumeric()) and +[`PropertyTypeId#isPropertyPackaged`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/PropertyTypeId.html#isPropertyPackaged()) are also deprecated. + +* [`MultiValuePropertyDescriptor`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/MultiValuePropertyDescriptor.html#) and [`SingleValuePropertyDescriptor`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/SingleValuePropertyDescriptor.html#) +are deprecated. 7.0.0 will introduce a new XML syntax which will remove the need for such a divide +between single- and multi-valued properties. The method [`PropertyDescriptor#isMultiValue`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/PropertyDescriptor.html#isMultiValue()) will be removed +accordingly. + +##### Changes to the PropertyDescriptor interface + +* [`preferredRowCount`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/PropertyDescriptor.html#preferredRowCount()) is deprecated with no intended replacement. It was never implemented, and does not belong + in this interface. The methods [`uiOrder`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/PropertyDescriptor.html#uiOrder()) and `compareTo(PropertyDescriptor)` are deprecated for the + same reason. These methods mix presentation logic with business logic and are not necessary for PropertyDescriptors to work. + `PropertyDescriptor` will not extend `Comparable` anymore come 7.0.0. +* The method [`propertyErrorFor`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/PropertyDescriptor.html#propertyErrorFor(net.sourceforge.pmd.Rule)) is deprecated and will be removed with no intended + replacement. It's really just a shortcut for `prop.errorFor(rule.getProperty(prop))`. +* `T `[`valueFrom(String)`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/PropertyDescriptor.html#valueFrom(java.lang.String)) and `String `[`asDelimitedString`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/PropertyDescriptor.html#asDelimitedString(java.lang.Object))`(T)` are deprecated and will be removed. These were + used to serialize and deserialize properties to/from a string, but 7.0.0 will introduce a more flexible + XML syntax which will make them obsolete. +* [`isMultiValue`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/PropertyDescriptor.html#isMultiValue()) and [`type`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/PropertyDescriptor.html#type()) are deprecated and won't be replaced. The new XML syntax will remove the need + for a divide between multi- and single-value properties, and will allow arbitrary types to be represented. + Since arbitrary types may be represented, `type` will become obsolete as it can't represent generic types, + which will nevertheless be representable with the XML syntax. It was only used for documentation, but a + new way to document these properties exhaustively will be added with 7.0.0. +* [`errorFor`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/PropertyDescriptor.html#errorFor(java.lang.Object)) is deprecated as its return type will be changed to `Optional` with the shift to Java 8. + +#### Deprecated APIs + + + + + + + + +##### For internalization + +* The implementation of the adapters for the XPath engines Saxon and Jaxen (package [`net.sourceforge.pmd.lang.ast.xpath`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/lang/ast/xpath/package-summary.html#)) + are now deprecated. They'll be moved to an internal package come 7.0.0. Only [`Attribute`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/lang/ast/xpath/Attribute.html#) remains public API. + +* The classes [`PropertyDescriptorField`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/PropertyDescriptorField.html#), [`PropertyDescriptorBuilderConversionWrapper`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/builders/PropertyDescriptorBuilderConversionWrapper.html#), and the methods + [`PropertyDescriptor#attributeValuesById`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/PropertyDescriptor.html#attributeValuesById), [`PropertyDescriptor#isDefinedExternally`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/PropertyDescriptor.html#isDefinedExternally()) and [`PropertyTypeId#getFactory`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/PropertyTypeId.html#getFactory()). + These were used to read and write properties to and from XML, but were not intended as public API. + +* The class [`ValueParserConstants`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/ValueParserConstants.html#) and the interface [`ValueParser`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/ValueParser.html#). + +* All classes from [`net.sourceforge.pmd.lang.java.metrics.impl.visitors`](https://javadoc.io/page/net.sourceforge.pmd/pmd-java/6.10.0/net/sourceforge/pmd/lang/java/metrics/impl/visitors/package-summary.html#) are now considered internal API. They're deprecated + and will be moved into an internal package with 7.0.0. To implement your own metrics visitors, + [`JavaParserVisitorAdapter`](https://javadoc.io/page/net.sourceforge.pmd/pmd-java/6.10.0/net/sourceforge/pmd/lang/java/ast/JavaParserVisitorAdapter.html#) should be directly subclassed. + +* [`LanguageVersionHandler#getDataFlowHandler()`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/lang/LanguageVersionHandler.html#getDataFlowHandler()), [`LanguageVersionHandler#getDFAGraphRule()`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/lang/LanguageVersionHandler.html#getDFAGraphRule()) + +* [`VisitorStarter`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/lang/VisitorStarter.html#) + +##### For removal + +* All classes from [`net.sourceforge.pmd.properties.modules`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/properties/modules/package-summary.html#) will be removed. + +* The interface [`Dimensionable`](https://javadoc.io/page/net.sourceforge.pmd/pmd-java/6.10.0/net/sourceforge/pmd/lang/java/ast/Dimensionable.html#) has been deprecated. + It gets in the way of a grammar change for 7.0.0 and won't be needed anymore (see [#997](https://github.com/pmd/pmd/issues/997)). + +* Several methods from [`ASTLocalVariableDeclaration`](https://javadoc.io/page/net.sourceforge.pmd/pmd-java/6.10.0/net/sourceforge/pmd/lang/java/ast/ASTLocalVariableDeclaration.html#) and [`ASTFieldDeclaration`](https://javadoc.io/page/net.sourceforge.pmd/pmd-java/6.10.0/net/sourceforge/pmd/lang/java/ast/ASTFieldDeclaration.html#) have + also been deprecated: + + * [`ASTFieldDeclaration`](https://javadoc.io/page/net.sourceforge.pmd/pmd-java/6.10.0/net/sourceforge/pmd/lang/java/ast/ASTFieldDeclaration.html#) won't be a [`TypeNode`](https://javadoc.io/page/net.sourceforge.pmd/pmd-java/6.10.0/net/sourceforge/pmd/lang/java/ast/TypeNode.html#) come 7.0.0, so + [`getType`](https://javadoc.io/page/net.sourceforge.pmd/pmd-java/6.10.0/net/sourceforge/pmd/lang/java/ast/ASTFieldDeclaration.html#getType()) and + [`getTypeDefinition`](https://javadoc.io/page/net.sourceforge.pmd/pmd-java/6.10.0/net/sourceforge/pmd/lang/java/ast/ASTFieldDeclaration.html#getTypeDefinition()) are deprecated. + + * The method `getVariableName` on those two nodes will be removed, too. + + All these are deprecated because those nodes may declare several variables at once, possibly + with different types (and obviously with different names). They both implement `Iterator<`[`ASTVariableDeclaratorId`](https://javadoc.io/page/net.sourceforge.pmd/pmd-java/6.10.0/net/sourceforge/pmd/lang/java/ast/ASTVariableDeclaratorId.html#)`>` + though, so you should iterate on each declared variable. See [#910](https://github.com/pmd/pmd/issues/910). + +* Visitor decorators are now deprecated and will be removed in PMD 7.0.0. They were originally a way to write + composable visitors, used in the metrics framework, but they didn't prove cost-effective. + + * In [`net.sourceforge.pmd.lang.java.ast`](https://javadoc.io/page/net.sourceforge.pmd/pmd-java/6.10.0/net/sourceforge/pmd/lang/java/ast/package-summary.html#): [`JavaParserDecoratedVisitor`](https://javadoc.io/page/net.sourceforge.pmd/pmd-java/6.10.0/net/sourceforge/pmd/lang/java/ast/JavaParserDecoratedVisitor.html#), [`JavaParserControllessVisitor`](https://javadoc.io/page/net.sourceforge.pmd/pmd-java/6.10.0/net/sourceforge/pmd/lang/java/ast/JavaParserControllessVisitor.html#), + [`JavaParserControllessVisitorAdapter`](https://javadoc.io/page/net.sourceforge.pmd/pmd-java/6.10.0/net/sourceforge/pmd/lang/java/ast/JavaParserControllessVisitorAdapter.html#), and [`JavaParserVisitorDecorator`](https://javadoc.io/page/net.sourceforge.pmd/pmd-java/6.10.0/net/sourceforge/pmd/lang/java/ast/JavaParserVisitorDecorator.html#) are deprecated with no intended replacement. + + +* The LanguageModules of several languages, that only support CPD execution, have been deprecated. These languages + are not fully supported by PMD, so having a language module does not make sense. The functionality of CPD is + not affected by this change. The following classes have been deprecated and will be removed with PMD 7.0.0: + + * [`CppHandler`](https://javadoc.io/page/net.sourceforge.pmd/pmd-cpp/6.10.0/net/sourceforge/pmd/lang/cpp/CppHandler.html#) + * [`CppLanguageModule`](https://javadoc.io/page/net.sourceforge.pmd/pmd-cpp/6.10.0/net/sourceforge/pmd/lang/cpp/CppLanguageModule.html#) + * [`CppParser`](https://javadoc.io/page/net.sourceforge.pmd/pmd-cpp/6.10.0/net/sourceforge/pmd/lang/cpp/CppParser.html#) + * [`CsLanguageModule`](https://javadoc.io/page/net.sourceforge.pmd/pmd-cs/6.10.0/net/sourceforge/pmd/lang/cs/CsLanguageModule.html#) + * [`FortranLanguageModule`](https://javadoc.io/page/net.sourceforge.pmd/pmd-fortran/6.10.0/net/sourceforge/pmd/lang/fortran/FortranLanguageModule.html#) + * [`GroovyLanguageModule`](https://javadoc.io/page/net.sourceforge.pmd/pmd-groovy/6.10.0/net/sourceforge/pmd/lang/groovy/GroovyLanguageModule.html#) + * [`MatlabHandler`](https://javadoc.io/page/net.sourceforge.pmd/pmd-matlab/6.10.0/net/sourceforge/pmd/lang/matlab/MatlabHandler.html#) + * [`MatlabLanguageModule`](https://javadoc.io/page/net.sourceforge.pmd/pmd-matlab/6.10.0/net/sourceforge/pmd/lang/matlab/MatlabLanguageModule.html#) + * [`MatlabParser`](https://javadoc.io/page/net.sourceforge.pmd/pmd-matlab/6.10.0/net/sourceforge/pmd/lang/matlab/MatlabParser.html#) + * [`ObjectiveCHandler`](https://javadoc.io/page/net.sourceforge.pmd/pmd-objectivec/6.10.0/net/sourceforge/pmd/lang/objectivec/ObjectiveCHandler.html#) + * [`ObjectiveCLanguageModule`](https://javadoc.io/page/net.sourceforge.pmd/pmd-objectivec/6.10.0/net/sourceforge/pmd/lang/objectivec/ObjectiveCLanguageModule.html#) + * [`ObjectiveCParser`](https://javadoc.io/page/net.sourceforge.pmd/pmd-objectivec/6.10.0/net/sourceforge/pmd/lang/objectivec/ObjectiveCParser.html#) + * [`PhpLanguageModule`](https://javadoc.io/page/net.sourceforge.pmd/pmd-php/6.10.0/net/sourceforge/pmd/lang/php/PhpLanguageModule.html#) + * [`PythonHandler`](https://javadoc.io/page/net.sourceforge.pmd/pmd-python/6.10.0/net/sourceforge/pmd/lang/python/PythonHandler.html#) + * [`PythonLanguageModule`](https://javadoc.io/page/net.sourceforge.pmd/pmd-python/6.10.0/net/sourceforge/pmd/lang/python/PythonLanguageModule.html#) + * [`PythonParser`](https://javadoc.io/page/net.sourceforge.pmd/pmd-python/6.10.0/net/sourceforge/pmd/lang/python/PythonParser.html#) + * [`RubyLanguageModule`](https://javadoc.io/page/net.sourceforge.pmd/pmd-ruby/6.10.0/net/sourceforge/pmd/lang/ruby/RubyLanguageModule.html#) + * [`ScalaLanguageModule`](https://javadoc.io/page/net.sourceforge.pmd/pmd-scala/6.10.0/net/sourceforge/pmd/lang/scala/ScalaLanguageModule.html#) + * [`SwiftLanguageModule`](https://javadoc.io/page/net.sourceforge.pmd/pmd-swift/6.10.0/net/sourceforge/pmd/lang/swift/SwiftLanguageModule.html#) + + +* Optional AST processing stages like symbol table, type resolution or data-flow analysis will be reified +in 7.0.0 to factorise common logic and make them extensible. Further explanations about this change can be +found on [#1426](https://github.com/pmd/pmd/pull/1426). Consequently, the following APIs are deprecated for +removal: + * In [`Rule`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/Rule.html#): [`isDfa()`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/Rule.html#isDfa()), [`isTypeResolution()`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/Rule.html#isTypeResolution()), [`isMultifile()`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/Rule.html#isMultifile()) and their + respective setters. + * In [`RuleSet`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/RuleSet.html#): [`usesDFA(Language)`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/RuleSet.html#usesDFA(net.sourceforge.pmd.lang.Language)), [`usesTypeResolution(Language)`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/RuleSet.html#usesTypeResolution(net.sourceforge.pmd.lang.Language)), [`usesMultifile(Language)`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/RuleSet.html#usesMultifile(net.sourceforge.pmd.lang.Language)) + * In [`RuleSets`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/RuleSets.html#): [`usesDFA(Language)`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/RuleSets.html#usesDFA(net.sourceforge.pmd.lang.Language)), [`usesTypeResolution(Language)`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/RuleSets.html#usesTypeResolution(net.sourceforge.pmd.lang.Language)), [`usesMultifile(Language)`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/RuleSets.html#usesMultifile(net.sourceforge.pmd.lang.Language)) + * In [`LanguageVersionHandler`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/lang/LanguageVersionHandler.html#): [`getDataFlowFacade()`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/lang/LanguageVersionHandler.html#getDataFlowFacade()), [`getSymbolFacade()`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/lang/LanguageVersionHandler.html#getSymbolFacade()), [`getSymbolFacade(ClassLoader)`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/lang/LanguageVersionHandler.html#getSymbolFacade(java.lang.ClassLoader)), + [`getTypeResolutionFacade(ClassLoader)`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/lang/LanguageVersionHandler.html#getTypeResolutionFacade(java.lang.ClassLoader)), [`getQualifiedNameResolutionFacade(ClassLoader)`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.10.0/net/sourceforge/pmd/lang/LanguageVersionHandler.html#getQualifiedNameResolutionFacade(java.lang.ClassLoader)) + +### External Contributions + +* [#1384](https://github.com/pmd/pmd/pull/1384): \[java] New Rule - UseUnderscoresInNumericLiterals - [RajeshR](https://github.com/rajeshggwp) +* [#1424](https://github.com/pmd/pmd/pull/1424): \[doc] #1341 Updating Regex Values in default Value Property - [avishvat](https://github.com/vishva007) +* [#1428](https://github.com/pmd/pmd/pull/1428): \[core] Upgrading JCommander from 1.48 to 1.72 - [Thunderforge](https://github.com/Thunderforge) +* [#1430](https://github.com/pmd/pmd/pull/1430): \[doc] Who really knows regex? - [Dem Pilafian](https://github.com/dpilafian) +* [#1434](https://github.com/pmd/pmd/pull/1434): \[java] JUnitTestsShouldIncludeAssert: Recognize AssertJ soft assertions as valid assert statements - [Loïc Ledoyen](https://github.com/ledoyen) +* [#1439](https://github.com/pmd/pmd/pull/1439): \[java] Avoid FileInputStream and FileOutputStream - [reudismam](https://github.com/reudismam) +* [#1441](https://github.com/pmd/pmd/pull/1441): \[kotlin] [cpd] Added CPD support for Kotlin - [Maikel Steneker](https://github.com/maikelsteneker) +* [#1447](https://github.com/pmd/pmd/pull/1447): \[fortran] Use diamond operator in impl - [reudismam](https://github.com/reudismam) +* [#1453](https://github.com/pmd/pmd/pull/1453): \[java] Adding the fix for #1440. Showing correct message for CommentDefaultAccessmodifier. - [Rohit Kumar](https://github.com/stationeros) +* [#1457](https://github.com/pmd/pmd/pull/1457): \[java] Adding test for Issue #647 - [orimarko](https://github.com/orimarko) +* [#1464](https://github.com/pmd/pmd/pull/1464): \[doc] Fix XSS on documentation web page - [Maxime Robert](https://github.com/marob) +* [#1469](https://github.com/pmd/pmd/pull/1469): \[core] Configurable max loops in DAAPathFinder - [Alberto Fernández](https://github.com/albfernandez) +* [#1494](https://github.com/pmd/pmd/pull/1494): \[java] 1151: Rephrase ImmutableField documentation in design.xml - [Robbie Martinus](https://github.com/rmartinus) +* [#1504](https://github.com/pmd/pmd/pull/1504): \[java] NPE in InvalidSlf4jMessageFormatRule if a logger call with a variable as parameter is not inside a method or constructor - [kris-scheibe](https://github.com/kris-scheibe) + ## 28-October-2018 - 6.9.0 The PMD team is pleased to announce PMD 6.9.0. diff --git a/pmd-apex/pom.xml b/pmd-apex/pom.xml index d706d4b1b6..9b3f2bcff4 100644 --- a/pmd-apex/pom.xml +++ b/pmd-apex/pom.xml @@ -27,30 +27,6 @@ - - - org.apache.maven.plugins - maven-antrun-plugin - - - pmd-clean - clean - - - PMD specific tasks: cleaning generated markdown - - - - - - - - - run - - - - diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/codestyle/VariableNamingConventionsRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/codestyle/VariableNamingConventionsRule.java index ec189d0ebc..6472460446 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/codestyle/VariableNamingConventionsRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/codestyle/VariableNamingConventionsRule.java @@ -6,7 +6,10 @@ package net.sourceforge.pmd.lang.apex.rule.codestyle; import static apex.jorje.semantic.symbol.type.ModifierTypeInfos.FINAL; import static apex.jorje.semantic.symbol.type.ModifierTypeInfos.STATIC; +import static net.sourceforge.pmd.properties.PropertyFactory.booleanProperty; +import static net.sourceforge.pmd.properties.PropertyFactory.stringListProperty; +import java.util.ArrayList; import java.util.List; import java.util.Locale; @@ -17,9 +20,7 @@ import net.sourceforge.pmd.lang.apex.ast.ASTUserInterface; import net.sourceforge.pmd.lang.apex.ast.ASTVariableDeclaration; import net.sourceforge.pmd.lang.apex.ast.ApexNode; import net.sourceforge.pmd.lang.apex.rule.AbstractApexRule; -import net.sourceforge.pmd.properties.BooleanProperty; import net.sourceforge.pmd.properties.PropertyDescriptor; -import net.sourceforge.pmd.properties.StringMultiProperty; public class VariableNamingConventionsRule extends AbstractApexRule { @@ -35,51 +36,60 @@ public class VariableNamingConventionsRule extends AbstractApexRule { private List parameterPrefixes; private List parameterSuffixes; - private static final BooleanProperty CHECK_MEMBERS_DESCRIPTOR = new BooleanProperty("checkMembers", - "Check member variables", true, 1.0f); + private static final PropertyDescriptor CHECK_MEMBERS_DESCRIPTOR = + booleanProperty("checkMembers") + .desc("Check member variables").defaultValue(true).build(); - private static final BooleanProperty CHECK_LOCALS_DESCRIPTOR = new BooleanProperty("checkLocals", - "Check local variables", true, 2.0f); + private static final PropertyDescriptor CHECK_LOCALS_DESCRIPTOR = + booleanProperty("checkLocals") + .desc("Check local variables").defaultValue(true).build(); - private static final BooleanProperty CHECK_PARAMETERS_DESCRIPTOR = new BooleanProperty("checkParameters", - "Check constructor and method parameter variables", true, 3.0f); + private static final PropertyDescriptor CHECK_PARAMETERS_DESCRIPTOR = + booleanProperty("checkParameters") + .desc("Check constructor and method parameter variables").defaultValue(true).build(); - private static final StringMultiProperty STATIC_PREFIXES_DESCRIPTOR = new StringMultiProperty("staticPrefix", - "Static variable prefixes", new String[] { "" }, 4.0f, ','); + private static final PropertyDescriptor> STATIC_PREFIXES_DESCRIPTOR = + stringListProperty("staticPrefix") + .desc("Static variable prefixes").defaultValues("").delim(',').build(); - private static final StringMultiProperty STATIC_SUFFIXES_DESCRIPTOR = new StringMultiProperty("staticSuffix", - "Static variable suffixes", new String[] { "" }, 5.0f, ','); + private static final PropertyDescriptor> STATIC_SUFFIXES_DESCRIPTOR = + stringListProperty("staticSuffix") + .desc("Static variable suffixes").defaultValues("").delim(',').build(); - private static final StringMultiProperty MEMBER_PREFIXES_DESCRIPTOR = new StringMultiProperty("memberPrefix", - "Member variable prefixes", new String[] { "" }, 6.0f, ','); + private static final PropertyDescriptor> MEMBER_PREFIXES_DESCRIPTOR = + stringListProperty("memberPrefix") + .desc("Member variable prefixes").defaultValues("").delim(',').build(); - private static final StringMultiProperty MEMBER_SUFFIXES_DESCRIPTOR = new StringMultiProperty("memberSuffix", - "Member variable suffixes", new String[] { "" }, 7.0f, ','); + private static final PropertyDescriptor> MEMBER_SUFFIXES_DESCRIPTOR = + stringListProperty("memberSuffix") + .desc("Member variable suffixes").defaultValues("").delim(',').build(); - private static final StringMultiProperty LOCAL_PREFIXES_DESCRIPTOR = new StringMultiProperty("localPrefix", - "Local variable prefixes", new String[] { "" }, 8.0f, ','); + private static final PropertyDescriptor> LOCAL_PREFIXES_DESCRIPTOR = + stringListProperty("localPrefix") + .desc("Local variable prefixes").defaultValues("").delim(',').build(); - private static final StringMultiProperty LOCAL_SUFFIXES_DESCRIPTOR = new StringMultiProperty("localSuffix", - "Local variable suffixes", new String[] { "" }, 9.0f, ','); + private static final PropertyDescriptor> LOCAL_SUFFIXES_DESCRIPTOR = + stringListProperty("localSuffix") + .desc("Local variable suffixes").defaultValues("").delim(',').build(); - private static final StringMultiProperty PARAMETER_PREFIXES_DESCRIPTOR = new StringMultiProperty("parameterPrefix", - "Method parameter variable prefixes", new String[] { "" }, 10.0f, ','); + private static final PropertyDescriptor> PARAMETER_PREFIXES_DESCRIPTOR = + stringListProperty("parameterPrefix") + .desc("Method parameter variable prefixes") + .defaultValues("").delim(',').build(); + + private static final PropertyDescriptor> PARAMETER_SUFFIXES_DESCRIPTOR = + stringListProperty("parameterSuffix") + .desc("Method parameter variable suffixes") + .defaultValues("").delim(',').build(); - private static final StringMultiProperty PARAMETER_SUFFIXES_DESCRIPTOR = new StringMultiProperty("parameterSuffix", - "Method parameter variable suffixes", new String[] { "" }, 11.0f, ','); public VariableNamingConventionsRule() { definePropertyDescriptor(CHECK_MEMBERS_DESCRIPTOR); definePropertyDescriptor(CHECK_LOCALS_DESCRIPTOR); definePropertyDescriptor(CHECK_PARAMETERS_DESCRIPTOR); - definePropertyDescriptor(STATIC_PREFIXES_DESCRIPTOR); - definePropertyDescriptor(STATIC_SUFFIXES_DESCRIPTOR); - definePropertyDescriptor(MEMBER_PREFIXES_DESCRIPTOR); - definePropertyDescriptor(MEMBER_SUFFIXES_DESCRIPTOR); - definePropertyDescriptor(LOCAL_PREFIXES_DESCRIPTOR); - definePropertyDescriptor(LOCAL_SUFFIXES_DESCRIPTOR); - definePropertyDescriptor(PARAMETER_PREFIXES_DESCRIPTOR); - definePropertyDescriptor(PARAMETER_SUFFIXES_DESCRIPTOR); + for (PropertyDescriptor> property : suffixOrPrefixProperties()) { + definePropertyDescriptor(property); + } setProperty(CODECLIMATE_CATEGORIES, "Style"); // Note: x10 as Apex has not automatic refactoring @@ -87,6 +97,19 @@ public class VariableNamingConventionsRule extends AbstractApexRule { setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } + private static List>> suffixOrPrefixProperties() { + List>> res = new ArrayList<>(); + res.add(STATIC_PREFIXES_DESCRIPTOR); + res.add(STATIC_SUFFIXES_DESCRIPTOR); + res.add(MEMBER_PREFIXES_DESCRIPTOR); + res.add(MEMBER_SUFFIXES_DESCRIPTOR); + res.add(LOCAL_PREFIXES_DESCRIPTOR); + res.add(LOCAL_SUFFIXES_DESCRIPTOR); + res.add(PARAMETER_PREFIXES_DESCRIPTOR); + res.add(PARAMETER_SUFFIXES_DESCRIPTOR); + return res; + } + @Override public Object visit(ASTUserClass node, Object data) { init(); @@ -209,13 +232,9 @@ public class VariableNamingConventionsRule extends AbstractApexRule { } public boolean hasPrefixesOrSuffixes() { - - for (PropertyDescriptor desc : getPropertyDescriptors()) { - if (desc instanceof StringMultiProperty) { - List values = getProperty((StringMultiProperty) desc); - if (!values.isEmpty()) { - return true; - } + for (PropertyDescriptor> desc : suffixOrPrefixProperties()) { + if (!getProperty(desc).isEmpty()) { + return true; } } return false; diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/AvoidDeeplyNestedIfStmtsRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/AvoidDeeplyNestedIfStmtsRule.java index dc9e4d52d2..9738092751 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/AvoidDeeplyNestedIfStmtsRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/AvoidDeeplyNestedIfStmtsRule.java @@ -4,20 +4,24 @@ package net.sourceforge.pmd.lang.apex.rule.design; +import static net.sourceforge.pmd.properties.constraints.NumericConstraints.positive; + import net.sourceforge.pmd.lang.apex.ast.ASTIfBlockStatement; import net.sourceforge.pmd.lang.apex.ast.ASTUserClass; import net.sourceforge.pmd.lang.apex.rule.AbstractApexRule; -import net.sourceforge.pmd.properties.IntegerProperty; +import net.sourceforge.pmd.properties.PropertyDescriptor; +import net.sourceforge.pmd.properties.PropertyFactory; + public class AvoidDeeplyNestedIfStmtsRule extends AbstractApexRule { private int depth; private int depthLimit; - private static final IntegerProperty PROBLEM_DEPTH_DESCRIPTOR - = IntegerProperty.named("problemDepth") + private static final PropertyDescriptor PROBLEM_DEPTH_DESCRIPTOR + = PropertyFactory.intProperty("problemDepth") .desc("The if statement depth reporting threshold") - .range(1, 25).defaultValue(3).uiOrder(1.0f).build(); + .require(positive()).defaultValue(3).build(); public AvoidDeeplyNestedIfStmtsRule() { definePropertyDescriptor(PROBLEM_DEPTH_DESCRIPTOR); diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/StdCyclomaticComplexityRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/StdCyclomaticComplexityRule.java index 323dd086ff..37bb9d4598 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/StdCyclomaticComplexityRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/StdCyclomaticComplexityRule.java @@ -4,6 +4,9 @@ package net.sourceforge.pmd.lang.apex.rule.design; +import static net.sourceforge.pmd.properties.PropertyFactory.booleanProperty; +import static net.sourceforge.pmd.properties.constraints.NumericConstraints.inRange; + import java.util.Stack; import net.sourceforge.pmd.lang.apex.ast.ASTBooleanExpression; @@ -20,8 +23,9 @@ import net.sourceforge.pmd.lang.apex.ast.ASTUserInterface; import net.sourceforge.pmd.lang.apex.ast.ASTUserTrigger; import net.sourceforge.pmd.lang.apex.ast.ASTWhileLoopStatement; import net.sourceforge.pmd.lang.apex.rule.AbstractApexRule; -import net.sourceforge.pmd.properties.BooleanProperty; -import net.sourceforge.pmd.properties.IntegerProperty; +import net.sourceforge.pmd.properties.PropertyDescriptor; +import net.sourceforge.pmd.properties.PropertyFactory; + /** * Implements the standard cyclomatic complexity rule @@ -36,16 +40,16 @@ import net.sourceforge.pmd.properties.IntegerProperty; */ public class StdCyclomaticComplexityRule extends AbstractApexRule { - public static final IntegerProperty REPORT_LEVEL_DESCRIPTOR - = IntegerProperty.named("reportLevel") + public static final PropertyDescriptor REPORT_LEVEL_DESCRIPTOR + = PropertyFactory.intProperty("reportLevel") .desc("Cyclomatic Complexity reporting threshold") - .range(1, 30).defaultValue(10).uiOrder(1.0f).build(); + .require(inRange(1, 30)) + .defaultValue(10) + .build(); - public static final BooleanProperty SHOW_CLASSES_COMPLEXITY_DESCRIPTOR = new BooleanProperty( - "showClassesComplexity", "Add class average violations to the report", true, 2.0f); + public static final PropertyDescriptor SHOW_CLASSES_COMPLEXITY_DESCRIPTOR = booleanProperty("showClassesComplexity").desc("Add class average violations to the report").defaultValue(true).build(); - public static final BooleanProperty SHOW_METHODS_COMPLEXITY_DESCRIPTOR = new BooleanProperty( - "showMethodsComplexity", "Add method average violations to the report", true, 3.0f); + public static final PropertyDescriptor SHOW_METHODS_COMPLEXITY_DESCRIPTOR = booleanProperty("showMethodsComplexity").desc("Add method average violations to the report").defaultValue(true).build(); private int reportLevel; private boolean showClassesComplexity = true; diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/TooManyFieldsRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/TooManyFieldsRule.java index 58ac910189..31f47b78a8 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/TooManyFieldsRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/TooManyFieldsRule.java @@ -6,6 +6,7 @@ package net.sourceforge.pmd.lang.apex.rule.design; import static apex.jorje.semantic.symbol.type.ModifierTypeInfos.FINAL; import static apex.jorje.semantic.symbol.type.ModifierTypeInfos.STATIC; +import static net.sourceforge.pmd.properties.constraints.NumericConstraints.positive; import java.util.HashMap; import java.util.List; @@ -15,7 +16,8 @@ import net.sourceforge.pmd.lang.apex.ast.ASTField; import net.sourceforge.pmd.lang.apex.ast.ASTUserClass; import net.sourceforge.pmd.lang.apex.rule.AbstractApexRule; import net.sourceforge.pmd.lang.ast.Node; -import net.sourceforge.pmd.properties.IntegerProperty; +import net.sourceforge.pmd.properties.PropertyDescriptor; +import net.sourceforge.pmd.properties.PropertyFactory; import net.sourceforge.pmd.util.NumericConstants; public class TooManyFieldsRule extends AbstractApexRule { @@ -25,8 +27,13 @@ public class TooManyFieldsRule extends AbstractApexRule { private Map stats; private Map nodes; - private static final IntegerProperty MAX_FIELDS_DESCRIPTOR = new IntegerProperty("maxfields", - "Max allowable fields", 1, 300, DEFAULT_MAXFIELDS, 1.0f); + private static final PropertyDescriptor MAX_FIELDS_DESCRIPTOR + = PropertyFactory.intProperty("maxfields") + .desc("Max allowable fields") + .defaultValue(DEFAULT_MAXFIELDS) + .require(positive()) + .build(); + public TooManyFieldsRule() { definePropertyDescriptor(MAX_FIELDS_DESCRIPTOR); @@ -71,7 +78,7 @@ public class TooManyFieldsRule extends AbstractApexRule { stats.put(key, NumericConstants.ZERO); nodes.put(key, clazz); } - Integer i = Integer.valueOf(stats.get(key) + 1); + Integer i = stats.get(key) + 1; stats.put(key, i); } } diff --git a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/metrics/impl/AbstractApexMetricTestRule.java b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/metrics/impl/AbstractApexMetricTestRule.java index 0791a87b4e..290ffa897e 100644 --- a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/metrics/impl/AbstractApexMetricTestRule.java +++ b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/metrics/impl/AbstractApexMetricTestRule.java @@ -4,8 +4,8 @@ package net.sourceforge.pmd.lang.apex.metrics.impl; -import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; import net.sourceforge.pmd.lang.apex.ast.ASTMethod; @@ -17,9 +17,9 @@ import net.sourceforge.pmd.lang.apex.rule.AbstractApexRule; import net.sourceforge.pmd.lang.metrics.MetricOption; import net.sourceforge.pmd.lang.metrics.MetricOptions; import net.sourceforge.pmd.lang.metrics.ResultOption; -import net.sourceforge.pmd.properties.BooleanProperty; -import net.sourceforge.pmd.properties.DoubleProperty; -import net.sourceforge.pmd.properties.EnumeratedMultiProperty; +import net.sourceforge.pmd.properties.PropertyDescriptor; +import net.sourceforge.pmd.properties.PropertyFactory; + /** * Abstract test rule for a metric. Tests of metrics use the standard framework for rule testing, using one dummy rule @@ -29,15 +29,25 @@ import net.sourceforge.pmd.properties.EnumeratedMultiProperty; */ public abstract class AbstractApexMetricTestRule extends AbstractApexRule { - private final EnumeratedMultiProperty optionsDescriptor = new EnumeratedMultiProperty<>( - "metricOptions", "Choose a variant of the metric or the standard", - optionMappings(), Collections.emptyList(), MetricOption.class, 3.0f); - private final BooleanProperty reportClassesDescriptor = new BooleanProperty( - "reportClasses", "Add class violations to the report", isReportClasses(), 2.0f); - private final BooleanProperty reportMethodsDescriptor = new BooleanProperty( - "reportMethods", "Add method violations to the report", isReportMethods(), 3.0f); - private final DoubleProperty reportLevelDescriptor = new DoubleProperty( - "reportLevel", "Minimum value required to report", -1., Double.POSITIVE_INFINITY, defaultReportLevel(), 3.0f); + private final PropertyDescriptor> optionsDescriptor = + PropertyFactory.enumListProperty("metricOptions", optionMappings()) + .desc("Choose a variant of the metric or the standard") + .emptyDefaultValue().build(); + + private final PropertyDescriptor reportClassesDescriptor = + PropertyFactory.booleanProperty("reportClasses") + .desc("Add class violations to the report") + .defaultValue(isReportClasses()).build(); + + private final PropertyDescriptor reportMethodsDescriptor = + PropertyFactory.booleanProperty("reportMethods") + .desc("Add method violations to the report") + .defaultValue(isReportMethods()).build(); + + private final PropertyDescriptor reportLevelDescriptor = + PropertyFactory.doubleProperty("reportLevel") + .desc("Minimum value required to report") + .defaultValue(defaultReportLevel()).build(); private MetricOptions metricOptions; private boolean reportClasses; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/Report.java b/pmd-core/src/main/java/net/sourceforge/pmd/Report.java index ff2a29a672..694a8b657e 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/Report.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/Report.java @@ -160,7 +160,7 @@ public class Report implements Iterable { } public String getMsg() { - return error.getMessage(); + return error.getClass().getSimpleName() + ": " + error.getMessage(); } public String getDetail() { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/Rule.java b/pmd-core/src/main/java/net/sourceforge/pmd/Rule.java index 243e1935f3..00f4272a0f 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/Rule.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/Rule.java @@ -30,6 +30,7 @@ public interface Rule extends PropertySource { * The property descriptor to universally suppress violations with messages * matching a regular expression. */ + // TODO 7.0.0 use PropertyDescriptor StringProperty VIOLATION_SUPPRESS_REGEX_DESCRIPTOR = new StringProperty("violationSuppressRegex", "Suppress violations with messages matching a regular expression", null, Integer.MAX_VALUE - 1); @@ -37,6 +38,7 @@ public interface Rule extends PropertySource { * Name of the property to universally suppress violations on nodes which * match a given relative XPath expression. */ + // TODO 7.0.0 use PropertyDescriptor StringProperty VIOLATION_SUPPRESS_XPATH_DESCRIPTOR = new StringProperty("violationSuppressXPath", "Suppress violations on nodes which match a given relative XPath expression.", null, Integer.MAX_VALUE - 2); @@ -286,13 +288,14 @@ public interface Rule extends PropertySource { /** * Sets whether this Rule uses Data Flow Analysis. - * @deprecated Use {@link #setDfa(boolean)} instead. + * @deprecated See {@link #isDfa()} */ @Deprecated // To be removed in PMD 7.0.0 void setUsesDFA(); /** * Sets whether this Rule uses Data Flow Analysis. + * @deprecated See {@link #isDfa()} */ @Deprecated void setDfa(boolean isDfa); @@ -301,7 +304,7 @@ public interface Rule extends PropertySource { * Gets whether this Rule uses Data Flow Analysis. * * @return true if Data Flow Analysis is used. - * @deprecated Use {@link #isDfa()} instead. + * @deprecated See {@link #isDfa()} */ @Deprecated // To be removed in PMD 7.0.0 boolean usesDFA(); @@ -310,19 +313,22 @@ public interface Rule extends PropertySource { * Gets whether this Rule uses Data Flow Analysis. * * @return true if Data Flow Analysis is used. + * @deprecated Optional AST processing stages will be reified in 7.0.0 to factorise common logic. + * This method and the similar methods will be removed. */ @Deprecated boolean isDfa(); /** * Sets whether this Rule uses Type Resolution. - * @deprecated Use {@link #setTypeResolution(boolean)} instead. + * @deprecated See {@link #isTypeResolution()} */ @Deprecated // To be removed in PMD 7.0.0 void setUsesTypeResolution(); /** * Sets whether this Rule uses Type Resolution. + * @deprecated See {@link #isTypeResolution()} */ @Deprecated void setTypeResolution(boolean usingTypeResolution); @@ -332,7 +338,7 @@ public interface Rule extends PropertySource { * * @return true if Type Resolution is used. * - * @deprecated Use {@link #isTypeResolution()} instead + * @deprecated See {@link #isTypeResolution()} */ @Deprecated // To be removed in PMD 7.0.0 boolean usesTypeResolution(); @@ -341,19 +347,22 @@ public interface Rule extends PropertySource { * Gets whether this Rule uses Type Resolution. * * @return true if Type Resolution is used. + * @deprecated Optional AST processing stages will be reified in 7.0.0 to factorise common logic. + * This method and the similar methods will be removed. */ @Deprecated boolean isTypeResolution(); /** * Sets whether this Rule uses multi-file analysis. - * @deprecated use {@link #setMultifile(boolean)} instead. + * @deprecated See {@link #isMultifile()} */ @Deprecated // To be removed in PMD 7.0.0 void setUsesMultifile(); /** * Sets whether this Rule uses multi-file analysis. + * @deprecated See {@link #isMultifile()} */ @Deprecated void setMultifile(boolean multifile); @@ -363,7 +372,7 @@ public interface Rule extends PropertySource { * * @return true if the multi file analysis is used. * - * @deprecated Use {@link #isMultifile()} instead. + * @deprecated See {@link #isMultifile()} */ @Deprecated // To be removed in PMD 7.0.0 boolean usesMultifile(); @@ -372,6 +381,8 @@ public interface Rule extends PropertySource { * Gets whether this Rule uses multi-file analysis. * * @return true if the multi file analysis is used. + * @deprecated Logic for multifile analysis is not implemented yet and probably + * won't be implemented this way. Will be removed in 7.0.0. */ @Deprecated boolean isMultifile(); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSet.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSet.java index 84d1bf877e..79f3b6a22d 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSet.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSet.java @@ -605,6 +605,7 @@ public class RuleSet implements ChecksumAware { * The Language. * @return true if a Rule for the Language uses the DFA layer, * false otherwise. + * @deprecated See {@link Rule#isDfa()} */ @Deprecated public boolean usesDFA(Language language) { @@ -623,6 +624,7 @@ public class RuleSet implements ChecksumAware { * The Language. * @return true if a Rule for the Language uses Type * Resolution, false otherwise. + * @deprecated See {@link Rule#isTypeResolution()} */ @Deprecated public boolean usesTypeResolution(Language language) { @@ -643,6 +645,7 @@ public class RuleSet implements ChecksumAware { * * @return {@code true} if a Rule for the Language uses multi file analysis, * {@code false} otherwise. + * @deprecated See {@link Rule#isMultifile()} */ @Deprecated public boolean usesMultifile(Language language) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSets.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSets.java index c71913b684..482687f4ab 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSets.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSets.java @@ -160,6 +160,7 @@ public class RuleSets { * @param language * the language of a source * @return true if any rule in the RuleSet needs the DFA layer + * @deprecated See {@link Rule#isDfa()} */ @Deprecated public boolean usesDFA(Language language) { @@ -210,6 +211,7 @@ public class RuleSets { * The Language. * @return true if a Rule for the Language uses Type * Resolution, false otherwise. + * @deprecated See {@link Rule#isTypeResolution()} */ @Deprecated public boolean usesTypeResolution(Language language) { @@ -229,6 +231,7 @@ public class RuleSets { * * @return {@code true} if a Rule for the Language uses multi file analysis, * {@code false} otherwise. + * @deprecated See {@link Rule#isMultifile()} */ @Deprecated public boolean usesMultifile(Language language) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/ant/Formatter.java b/pmd-core/src/main/java/net/sourceforge/pmd/ant/Formatter.java index 8a7e84c8d6..2ef0afd459 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/ant/Formatter.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/ant/Formatter.java @@ -7,7 +7,6 @@ package net.sourceforge.pmd.ant; import java.io.BufferedWriter; import java.io.Console; import java.io.File; -import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; @@ -16,6 +15,7 @@ import java.lang.reflect.Field; import java.lang.reflect.Method; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.util.ArrayList; import java.util.List; import java.util.Properties; @@ -181,7 +181,7 @@ public class Formatter { Writer writer = null; boolean isOnError = true; try { - output = new FileOutputStream(file); + output = Files.newOutputStream(file.toPath()); writer = new OutputStreamWriter(output, charset); writer = new BufferedWriter(writer); isOnError = false; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/cache/AbstractAnalysisCache.java b/pmd-core/src/main/java/net/sourceforge/pmd/cache/AbstractAnalysisCache.java index 9a0fa6e508..e3eb75608d 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/cache/AbstractAnalysisCache.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/cache/AbstractAnalysisCache.java @@ -26,6 +26,7 @@ import java.util.logging.Logger; import java.util.zip.Adler32; import java.util.zip.CheckedInputStream; +import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; import net.sourceforge.pmd.PMDVersion; @@ -153,28 +154,48 @@ public abstract class AbstractAnalysisCache implements AnalysisCache { ruleMapper.initialize(ruleSets); } + private static boolean isClassPathWildcard(String entry) { + return entry.endsWith("/*") || entry.endsWith("\\*"); + } + private URL[] getClassPathEntries() { final String classpath = System.getProperty("java.class.path"); final String[] classpathEntries = classpath.split(File.pathSeparator); final List entries = new ArrayList<>(); + final SimpleFileVisitor fileVisitor = new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(final Path file, + final BasicFileAttributes attrs) throws IOException { + if (!attrs.isSymbolicLink()) { // Broken link that can't be followed + entries.add(file.toUri().toURL()); + } + return FileVisitResult.CONTINUE; + } + }; + final SimpleFileVisitor jarFileVisitor = new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(final Path file, + final BasicFileAttributes attrs) throws IOException { + String extension = FilenameUtils.getExtension(file.toString()); + if ("jar".equalsIgnoreCase(extension)) { + fileVisitor.visitFile(file, attrs); + } + return FileVisitResult.CONTINUE; + } + }; + try { for (final String entry : classpathEntries) { final File f = new File(entry); - if (f.isFile()) { + if (isClassPathWildcard(entry)) { + Files.walkFileTree(new File(entry.substring(0, entry.length() - 1)).toPath(), + EnumSet.of(FileVisitOption.FOLLOW_LINKS), 1, jarFileVisitor); + } else if (f.isFile()) { entries.add(f.toURI().toURL()); } else { Files.walkFileTree(f.toPath(), EnumSet.of(FileVisitOption.FOLLOW_LINKS), Integer.MAX_VALUE, - new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(final Path file, - final BasicFileAttributes attrs) throws IOException { - if (!attrs.isSymbolicLink()) { // Broken link that can't be followed - entries.add(file.toUri().toURL()); - } - return FileVisitResult.CONTINUE; - } - }); + fileVisitor); } } } catch (final IOException e) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/cache/AnalysisResult.java b/pmd-core/src/main/java/net/sourceforge/pmd/cache/AnalysisResult.java index 4e4569bede..02eb5a253d 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/cache/AnalysisResult.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/cache/AnalysisResult.java @@ -6,8 +6,8 @@ package net.sourceforge.pmd.cache; import java.io.BufferedInputStream; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; +import java.nio.file.Files; import java.util.ArrayList; import java.util.List; import java.util.zip.Adler32; @@ -38,7 +38,7 @@ public class AnalysisResult { private static long computeFileChecksum(final File sourceFile) { try ( CheckedInputStream stream = new CheckedInputStream( - new BufferedInputStream(new FileInputStream(sourceFile)), new Adler32()); + new BufferedInputStream(Files.newInputStream(sourceFile.toPath())), new Adler32()); ) { // Just read it, the CheckedInputStream will update the checksum on it's own IOUtils.skipFully(stream, sourceFile.length()); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/cache/FileAnalysisCache.java b/pmd-core/src/main/java/net/sourceforge/pmd/cache/FileAnalysisCache.java index 8406594715..efc9315df6 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/cache/FileAnalysisCache.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/cache/FileAnalysisCache.java @@ -10,9 +10,8 @@ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.EOFException; import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; import java.io.IOException; +import java.nio.file.Files; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -46,7 +45,7 @@ public class FileAnalysisCache extends AbstractAnalysisCache { if (cacheExists()) { try ( DataInputStream inputStream = new DataInputStream( - new BufferedInputStream(new FileInputStream(cacheFile))); + new BufferedInputStream(Files.newInputStream(cacheFile.toPath()))); ) { final String cacheVersion = inputStream.readUTF(); @@ -106,7 +105,7 @@ public class FileAnalysisCache extends AbstractAnalysisCache { try ( DataOutputStream outputStream = new DataOutputStream( - new BufferedOutputStream(new FileOutputStream(cacheFile))) + new BufferedOutputStream(Files.newOutputStream(cacheFile.toPath()))) ) { outputStream.writeUTF(pmdVersion); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/cpd/CPDTask.java b/pmd-core/src/main/java/net/sourceforge/pmd/cpd/CPDTask.java index abf9f6e707..953cfd1e25 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/cpd/CPDTask.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/cpd/CPDTask.java @@ -6,11 +6,11 @@ package net.sourceforge.pmd.cpd; import java.io.BufferedWriter; import java.io.File; -import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; +import java.nio.file.Files; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -137,9 +137,9 @@ public class CPDTask extends Task { if (outputFile == null) { os = System.out; } else if (outputFile.isAbsolute()) { - os = new FileOutputStream(outputFile); + os = Files.newOutputStream(outputFile.toPath()); } else { - os = new FileOutputStream(new File(getProject().getBaseDir(), outputFile.toString())); + os = Files.newOutputStream(new File(getProject().getBaseDir(), outputFile.toString()).toPath()); } if (encoding == null) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/cpd/FileReporter.java b/pmd-core/src/main/java/net/sourceforge/pmd/cpd/FileReporter.java index 033171a34c..7e79018210 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/cpd/FileReporter.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/cpd/FileReporter.java @@ -6,12 +6,11 @@ package net.sourceforge.pmd.cpd; import java.io.BufferedWriter; import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; +import java.nio.file.Files; import net.sourceforge.pmd.cpd.renderer.CPDRenderer; @@ -45,7 +44,7 @@ public class FileReporter { } } - private OutputStream getOutputStream() throws FileNotFoundException { - return reportFile == null ? System.out : new FileOutputStream(reportFile); + private OutputStream getOutputStream() throws IOException { + return reportFile == null ? System.out : Files.newOutputStream(reportFile.toPath()); } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/cpd/GUI.java b/pmd-core/src/main/java/net/sourceforge/pmd/cpd/GUI.java index 7249c19a43..916276502a 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/cpd/GUI.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/cpd/GUI.java @@ -18,10 +18,10 @@ import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.io.File; -import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; import java.io.Writer; +import java.nio.file.Files; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -269,7 +269,7 @@ public class GUI implements CPDListener { } if (!f.canWrite()) { - try (PrintWriter pw = new PrintWriter(new FileOutputStream(f))) { + try (PrintWriter pw = new PrintWriter(Files.newOutputStream(f.toPath()))) { renderer.render(matches.iterator(), pw); pw.flush(); JOptionPane.showMessageDialog(frame, "Saved " + matches.size() + " matches"); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/cpd/SourceCode.java b/pmd-core/src/main/java/net/sourceforge/pmd/cpd/SourceCode.java index 0a585f3720..cb9468d948 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/cpd/SourceCode.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/cpd/SourceCode.java @@ -6,11 +6,11 @@ package net.sourceforge.pmd.cpd; import java.io.BufferedReader; import java.io.File; -import java.io.FileInputStream; import java.io.InputStreamReader; import java.io.Reader; import java.io.StringReader; import java.lang.ref.SoftReference; +import java.nio.file.Files; import java.util.ArrayList; import java.util.List; @@ -102,7 +102,7 @@ public class SourceCode { @Override public Reader getReader() throws Exception { - BOMInputStream inputStream = new BOMInputStream(new FileInputStream(file), ByteOrderMark.UTF_8, + BOMInputStream inputStream = new BOMInputStream(Files.newInputStream(file.toPath()), ByteOrderMark.UTF_8, ByteOrderMark.UTF_16BE, ByteOrderMark.UTF_16LE); if (inputStream.hasBOM()) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/DataFlowHandler.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/DataFlowHandler.java index 212916e6b0..b7c7dfab05 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/DataFlowHandler.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/DataFlowHandler.java @@ -6,9 +6,16 @@ package net.sourceforge.pmd.lang; import java.util.List; +import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.dfa.DataFlowNode; + +/** + * @deprecated This is internal API + */ +@Deprecated +@InternalApi public interface DataFlowHandler { DataFlowHandler DUMMY = new DataFlowHandler() { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/LanguageRegistry.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/LanguageRegistry.java index 029953ae15..7417176fa8 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/LanguageRegistry.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/LanguageRegistry.java @@ -62,7 +62,16 @@ public final class LanguageRegistry { } public static Collection getLanguages() { - return getInstance().languages.values(); + // Filter out languages, that are not fully supported by PMD yet. + // Those languages should not have a LanguageModule then, but they have it. + // TODO This is unnecessary, if the incomplete language modules have been removed. + List languages = new ArrayList<>(); + for (Language language : getInstance().languages.values()) { + if (language.getRuleChainVisitorClass() != null) { + languages.add(language); + } + } + return languages; } public static Language getLanguage(String languageName) { @@ -132,15 +141,12 @@ public final class LanguageRegistry { * A utility method to find the Languages which have Rule support. * * @return A List of Languages with Rule support. + * + * @deprecated This method will be removed with PMD 7.0.0. Use {@link #getLanguages()} instead. */ + @Deprecated public static List findWithRuleSupport() { - List languages = new ArrayList<>(); - for (Language language : getInstance().languages.values()) { - if (language.getRuleChainVisitorClass() != null) { - languages.add(language); - } - } - return languages; + return new ArrayList<>(getLanguages()); } public static String commaSeparatedTerseNamesForLanguage(List languages) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/LanguageVersionHandler.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/LanguageVersionHandler.java index b390f9c177..edc0b3d05a 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/LanguageVersionHandler.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/LanguageVersionHandler.java @@ -8,6 +8,7 @@ import java.io.Writer; import java.util.List; import net.sourceforge.pmd.annotation.Experimental; +import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.ast.AstProcessingStage; import net.sourceforge.pmd.lang.dfa.DFAGraphRule; import net.sourceforge.pmd.lang.rule.RuleViolationFactory; @@ -17,6 +18,10 @@ import net.sourceforge.pmd.lang.rule.RuleViolationFactory; * Interface for obtaining the classes necessary for checking source files of a * specific language. * + * Note: "façade" getters like {@link #getSymbolFacade()} will be removed with 7.0.0 + * and replaced with a more extensible mechanism. They're now deprecated. See also + * https://github.com/pmd/pmd/pull/1426 + * * @author pieter_van_raemdonck - Application Engineers NV/SA - www.ae.be */ public interface LanguageVersionHandler { @@ -59,18 +64,6 @@ public interface LanguageVersionHandler { RuleViolationFactory getRuleViolationFactory(); - /** - * Get the DumpFacade. - * - * @param writer The writer to dump to. - * - * @return VisitorStarter - */ - // TODO should we deprecate? Not much use to it. - // Plus if it's not implemented, then it does nothing to the writer which is unexpected. - VisitorStarter getDumpFacade(Writer writer, String prefix, boolean recurse); - - /** * Get the DataFlowHandler. */ @@ -82,6 +75,7 @@ public interface LanguageVersionHandler { * Get the DataFlowFacade. * * @return VisitorStarter + * @deprecated see note in the class description */ @Deprecated VisitorStarter getDataFlowFacade(); @@ -91,6 +85,7 @@ public interface LanguageVersionHandler { * Get the SymbolFacade. * * @return VisitorStarter + * @deprecated see note in the class description */ @Deprecated VisitorStarter getSymbolFacade(); @@ -102,6 +97,7 @@ public interface LanguageVersionHandler { * @param classLoader A ClassLoader to use for resolving Types. * * @return VisitorStarter + * @deprecated see note in the class description */ @Deprecated VisitorStarter getSymbolFacade(ClassLoader classLoader); @@ -113,15 +109,28 @@ public interface LanguageVersionHandler { * @param classLoader A ClassLoader to use for resolving Types. * * @return VisitorStarter + * @deprecated see note in the class description */ @Deprecated VisitorStarter getTypeResolutionFacade(ClassLoader classLoader); + /** + * Get the DumpFacade. + * + * @param writer + * The writer to dump to. + * @return VisitorStarter + * @deprecated The dump façade is not that useful and will be completely scrapped with PMD 7.0.0 + */ + @Deprecated + VisitorStarter getDumpFacade(Writer writer, String prefix, boolean recurse); + /** * Gets the visitor that performs multifile data gathering. * * @return The visitor starter + * @deprecated see note in the class description */ @Deprecated VisitorStarter getMultifileFacade(); @@ -134,11 +143,16 @@ public interface LanguageVersionHandler { * @param classLoader The classloader to use to resolve the types of type qualified names * * @return The visitor starter + * @deprecated see note in the class description */ @Deprecated VisitorStarter getQualifiedNameResolutionFacade(ClassLoader classLoader); + /** + * @deprecated This is internal API + */ @Deprecated + @InternalApi DFAGraphRule getDFAGraphRule(); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/VisitorStarter.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/VisitorStarter.java index 56c1151ab2..7bfcba22b3 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/VisitorStarter.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/VisitorStarter.java @@ -4,13 +4,18 @@ package net.sourceforge.pmd.lang; +import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.ast.Node; /** * Interface for starting an implementation of the visitors for ASTs. * * @author pieter_van_raemdonck - Application Engineers NV/SA - www.ae.be + * + * @deprecated Is internal API, and is now only used on methods deprecated for removal. */ +@Deprecated +@InternalApi public interface VisitorStarter { /** diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/dfa/report/ReportHTMLPrintVisitor.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/dfa/report/ReportHTMLPrintVisitor.java index 61ab8eb4ee..682dbbc587 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/dfa/report/ReportHTMLPrintVisitor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/dfa/report/ReportHTMLPrintVisitor.java @@ -6,8 +6,9 @@ package net.sourceforge.pmd.lang.dfa.report; import java.io.BufferedWriter; import java.io.File; -import java.io.FileWriter; import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import org.apache.commons.lang3.StringUtils; @@ -44,7 +45,8 @@ public class ReportHTMLPrintVisitor extends ReportVisitor { * Writes the buffer to file. */ private void write(String filename, StringBuilder buf) throws IOException { - try (BufferedWriter bw = new BufferedWriter(new FileWriter(new File(baseDir + FILE_SEPARATOR + filename)))) { + try (BufferedWriter bw = Files.newBufferedWriter(new File(baseDir + FILE_SEPARATOR + filename).toPath(), + StandardCharsets.UTF_8)) { bw.write(buf.toString(), 0, buf.length()); } } @@ -92,7 +94,9 @@ public class ReportHTMLPrintVisitor extends ReportVisitor { */ if (node.getParent() == null) { packageBuf.insert(0, - "" + " " + " PMD" + " " + " " + PMD.EOL + "" + PMD.EOL + + "" + " " + PMD.EOL + " " + PMD.EOL + + " PMD" + " " + " " + PMD.EOL + "

Package View

" + "" + " " + PMD.EOL + "" + "" + "" + " " + PMD.EOL); @@ -152,7 +156,8 @@ public class ReportHTMLPrintVisitor extends ReportVisitor { String str = cnode.getClassName(); classBuf.insert(0, - "PMD - " + str + "" + PMD.EOL + "

Class View

" + "" + PMD.EOL + + "PMD - " + str + "" + PMD.EOL + "

Class View

" + "

Class: " + str + "

" + "
PackageClass#
" + " " + PMD.EOL + "" + "" + " " + PMD.EOL); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/MetricOptions.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/MetricOptions.java index 033fb2c361..7a0562839e 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/MetricOptions.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/MetricOptions.java @@ -82,6 +82,16 @@ public class MetricOptions { } + /** + * Returns true if this bundle contains the given option. + * + * @param option Option to look for + */ + public boolean contains(MetricOption option) { + return options.contains(option); + } + + @Override public String toString() { return "MetricOptions{" diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/MockRule.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/MockRule.java index 8c0e15ea9d..0cfad63c71 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/MockRule.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/MockRule.java @@ -4,13 +4,16 @@ package net.sourceforge.pmd.lang.rule; +import static net.sourceforge.pmd.properties.constraints.NumericConstraints.inRange; + import java.util.List; import net.sourceforge.pmd.RuleContext; import net.sourceforge.pmd.RulePriority; import net.sourceforge.pmd.lang.LanguageRegistry; import net.sourceforge.pmd.lang.ast.Node; -import net.sourceforge.pmd.properties.IntegerProperty; +import net.sourceforge.pmd.properties.PropertyFactory; + /** * This is a Rule implementation which can be used in scenarios where an actual @@ -23,7 +26,7 @@ public class MockRule extends AbstractRule { public MockRule() { super(); setLanguage(LanguageRegistry.getLanguage("Dummy")); - definePropertyDescriptor(IntegerProperty.named("testIntProperty").desc("testIntProperty").range(0, 100).defaultValue(1).uiOrder(0).build()); + definePropertyDescriptor(PropertyFactory.intProperty("testIntProperty").desc("testIntProperty").require(inRange(1, 100)).defaultValue(1).build()); } public MockRule(String name, String description, String message, String ruleSetName, RulePriority priority) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/XPathRule.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/XPathRule.java index f990dfab74..61aec6de29 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/XPathRule.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/XPathRule.java @@ -30,6 +30,7 @@ import net.sourceforge.pmd.properties.StringProperty; */ public class XPathRule extends AbstractRule { + // TODO 7.0.0 use PropertyDescriptor public static final StringProperty XPATH_DESCRIPTOR = StringProperty.named("xpath") .desc("XPath expression") .defaultValue("") @@ -45,7 +46,8 @@ public class XPathRule extends AbstractRule { tmp.put(XPATH_2_0, XPATH_2_0); XPATH_VERSIONS = Collections.unmodifiableMap(tmp); } - + + // published, can't be converted public static final EnumeratedProperty VERSION_DESCRIPTOR = EnumeratedProperty.named("version") .desc("XPath specification version") .mappings(XPATH_VERSIONS) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/BooleanMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/BooleanMultiProperty.java index bb13cac575..1a2f6d4028 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/BooleanMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/BooleanMultiProperty.java @@ -17,7 +17,9 @@ import net.sourceforge.pmd.properties.builders.PropertyDescriptorBuilderConversi * Defines a property type that supports multiple Boolean values. * * @author Brian Remedios + * @deprecated Not useful, will be removed with 7.0.0 */ +@Deprecated public final class BooleanMultiProperty extends AbstractMultiValueProperty { @@ -28,7 +30,10 @@ public final class BooleanMultiProperty extends AbstractMultiValueProperty defaultValues, float theUIOrder) { this(theName, theDescription, defaultValues, theUIOrder, false); } @@ -76,11 +84,19 @@ public final class BooleanMultiProperty extends AbstractMultiValueProperty { private BooleanMultiPBuilder(String name) { super(name); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/BooleanProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/BooleanProperty.java index acac8d414a..0f3ef45b96 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/BooleanProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/BooleanProperty.java @@ -15,7 +15,10 @@ import net.sourceforge.pmd.properties.builders.SingleValuePropertyBuilder; * * @author Brian Remedios * @version Refactored June 2017 (6.0.0) + * @deprecated Use a {@code PropertyDescriptor} instead. A builder is available from {@link PropertyFactory#booleanProperty(String)} and its overloads. + * This class will be removed in 7.0.0. */ +@Deprecated public final class BooleanProperty extends AbstractSingleValueProperty { /** @@ -26,8 +29,9 @@ public final class BooleanProperty extends AbstractSingleValueProperty * @param defaultBoolStr String representing the default value. * @param theUIOrder UI order * - * @deprecated will be removed in 7.0.0 + * @deprecated Use {@link PropertyFactory#booleanProperty(String)} or its overloads. */ + @Deprecated public BooleanProperty(String theName, String theDescription, String defaultBoolStr, float theUIOrder) { this(theName, theDescription, Boolean.valueOf(defaultBoolStr), theUIOrder, false); } @@ -46,7 +50,10 @@ public final class BooleanProperty extends AbstractSingleValueProperty * @param theDescription Description * @param defaultValue Default value * @param theUIOrder UI order + * + * @deprecated Use {@link PropertyFactory#booleanProperty(String)} or its overloads. */ + @Deprecated public BooleanProperty(String theName, String theDescription, boolean defaultValue, float theUIOrder) { this(theName, theDescription, defaultValue, theUIOrder, false); } @@ -74,11 +81,19 @@ public final class BooleanProperty extends AbstractSingleValueProperty } + /** + * @deprecated Use {@link PropertyFactory#booleanProperty(String)} or its overloads. + */ + @Deprecated public static BooleanPBuilder named(String name) { return new BooleanPBuilder(name); } + /** + * @deprecated Use {@link PropertyFactory#booleanProperty(String)} or its overloads. + */ + @Deprecated public static final class BooleanPBuilder extends SingleValuePropertyBuilder { private BooleanPBuilder(String name) { super(name); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/CharacterMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/CharacterMultiProperty.java index e94c3840e8..db45c30273 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/CharacterMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/CharacterMultiProperty.java @@ -19,7 +19,10 @@ import net.sourceforge.pmd.properties.builders.PropertyDescriptorBuilderConversi * * @author Brian Remedios * @version Refactored June 2017 (6.0.0) + * @deprecated Use a {@code PropertyDescriptor>}. A builder is available from {@link PropertyFactory#charListProperty(String)}. + * This class will be removed in 7.0.0. */ +@Deprecated public final class CharacterMultiProperty extends AbstractMultiValueProperty { @@ -33,7 +36,9 @@ public final class CharacterMultiProperty extends AbstractMultiValueProperty defaultValues, float theUIOrder, char delimiter) { this(theName, theDescription, defaultValues, theUIOrder, delimiter, false); } @@ -104,11 +111,19 @@ public final class CharacterMultiProperty extends AbstractMultiValueProperty { private CharacterMultiPBuilder(String name) { super(name); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/CharacterProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/CharacterProperty.java index ba90f2b3f3..5cb8752b5d 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/CharacterProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/CharacterProperty.java @@ -15,7 +15,10 @@ import net.sourceforge.pmd.properties.builders.SingleValuePropertyBuilder; * * @author Brian Remedios * @version Refactored June 2017 (6.0.0) + * @deprecated Use a {@code PropertyDescriptor}. A builder is available from {@link PropertyFactory#charProperty(String)}. + * This class will be removed in 7.0.0. */ +@Deprecated public final class CharacterProperty extends AbstractSingleValueProperty { /** @@ -27,8 +30,9 @@ public final class CharacterProperty extends AbstractSingleValueProperty { private CharacterPBuilder(String name) { super(name); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/DoubleMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/DoubleMultiProperty.java index 5bfabaf259..8040a66051 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/DoubleMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/DoubleMultiProperty.java @@ -16,7 +16,11 @@ import net.sourceforge.pmd.properties.builders.PropertyDescriptorBuilderConversi * * @author Brian Remedios * @version Refactored June 2017 (6.0.0) + * + * @deprecated Use a {@code PropertyDescriptor>} instead. A builder is available from {@link PropertyFactory#doubleListProperty(String)}. + * This class will be removed in 7.0.0. */ +@Deprecated public final class DoubleMultiProperty extends AbstractMultiNumericProperty { /** @@ -30,7 +34,9 @@ public final class DoubleMultiProperty extends AbstractMultiNumericProperty max} or one of the defaults is not between the bounds + * @deprecated use {@link PropertyFactory#doubleListProperty(String)} */ + @Deprecated public DoubleMultiProperty(String theName, String theDescription, Double min, Double max, Double[] defaultValues, float theUIOrder) { this(theName, theDescription, min, max, Arrays.asList(defaultValues), theUIOrder, false); @@ -55,7 +61,9 @@ public final class DoubleMultiProperty extends AbstractMultiNumericProperty max} or one of the defaults is not between the bounds + * @deprecated use {@link PropertyFactory#doubleListProperty(String)} */ + @Deprecated public DoubleMultiProperty(String theName, String theDescription, Double min, Double max, List defaultValues, float theUIOrder) { this(theName, theDescription, min, max, defaultValues, theUIOrder, false); @@ -83,12 +91,15 @@ public final class DoubleMultiProperty extends AbstractMultiNumericProperty { private DoubleMultiPBuilder(String name) { super(name); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/DoubleProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/DoubleProperty.java index ce635c4366..0fdabe9da4 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/DoubleProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/DoubleProperty.java @@ -15,7 +15,11 @@ import net.sourceforge.pmd.properties.builders.SingleNumericPropertyBuilder; * * @author Brian Remedios * @version Refactored June 2017 (6.0.0) + * + * @deprecated Use a {@code PropertyDescriptor} instead. A builder is available from {@link PropertyFactory#doubleProperty(String)}. + * This class will be removed in 7.0.0. */ +@Deprecated public final class DoubleProperty extends AbstractNumericProperty { @@ -31,8 +35,9 @@ public final class DoubleProperty extends AbstractNumericProperty { * @param theUIOrder UI order * * @throws IllegalArgumentException if {@literal min > max} or one of the defaults is not between the bounds - * @deprecated will be removed in 7.0.0 + * @deprecated Use {@link PropertyFactory#doubleProperty(String)}. */ + @Deprecated public DoubleProperty(String theName, String theDescription, String minStr, String maxStr, String defaultStr, float theUIOrder) { this(theName, theDescription, doubleFrom(minStr), doubleFrom(maxStr), doubleFrom(defaultStr), theUIOrder, false); @@ -57,7 +62,9 @@ public final class DoubleProperty extends AbstractNumericProperty { * @param theUIOrder UI order * * @throws IllegalArgumentException if {@literal min > max} or one of the defaults is not between the bounds + * @deprecated Use {@link PropertyFactory#doubleProperty(String)}. */ + @Deprecated public DoubleProperty(String theName, String theDescription, Double min, Double max, Double theDefault, float theUIOrder) { this(theName, theDescription, min, max, theDefault, theUIOrder, false); @@ -98,11 +105,19 @@ public final class DoubleProperty extends AbstractNumericProperty { } + /** + * @deprecated Use {@link PropertyFactory#doubleProperty(String)}. + */ + @Deprecated public static DoublePBuilder named(String name) { return new DoublePBuilder(name); } + /** + * @deprecated Use {@link PropertyFactory#doubleProperty(String)}. + */ + @Deprecated public static final class DoublePBuilder extends SingleNumericPropertyBuilder { private DoublePBuilder(String name) { super(name); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/EnumeratedMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/EnumeratedMultiProperty.java index fd4ed5530b..bf27ee573c 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/EnumeratedMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/EnumeratedMultiProperty.java @@ -22,7 +22,10 @@ import net.sourceforge.pmd.util.CollectionUtil; * @author Brian Remedios * @author Clément Fournier * @version Refactored June 2017 (6.0.0) + * @deprecated Use a {@code PropertyDescriptor>} instead. A builder is available from {@link PropertyFactory#enumListProperty(String, Map)}. + * This class will be removed in 7.0.0. */ +@Deprecated public final class EnumeratedMultiProperty extends AbstractMultiValueProperty implements EnumeratedPropertyDescriptor> { @@ -42,8 +45,7 @@ public final class EnumeratedMultiProperty extends AbstractMultiValueProperty * @param valueType Type of the values * @param theUIOrder UI order * - * @deprecated Use {@link #EnumeratedMultiProperty(String, String, Map, List, Class, float)}. Will be removed in - * 7.0.0 + * @deprecated Use {@link PropertyFactory#enumListProperty(String, Map)} */ @Deprecated public EnumeratedMultiProperty(String theName, String theDescription, String[] theLabels, E[] theChoices, @@ -64,8 +66,7 @@ public final class EnumeratedMultiProperty extends AbstractMultiValueProperty * @param choiceIndices Indices of the default values * @param theUIOrder UI order * - * @deprecated Use {@link #EnumeratedMultiProperty(String, String, Map, List, Class, float)}. Will be removed in - * 7.0.0 + * @deprecated Use {@link PropertyFactory#enumListProperty(String, Map)} */ @Deprecated public EnumeratedMultiProperty(String theName, String theDescription, String[] theLabels, E[] theChoices, @@ -84,7 +85,9 @@ public final class EnumeratedMultiProperty extends AbstractMultiValueProperty * @param defaultValues List of default values * @param valueType Type of the values * @param theUIOrder UI order + * @deprecated Use {@link PropertyFactory#enumListProperty(String, Map)} */ + @Deprecated public EnumeratedMultiProperty(String theName, String theDescription, Map choices, List defaultValues, Class valueType, float theUIOrder) { this(theName, theDescription, choices, defaultValues, valueType, theUIOrder, false); @@ -156,11 +159,19 @@ public final class EnumeratedMultiProperty extends AbstractMultiValueProperty } + /** + * @deprecated Use {@link PropertyFactory#enumListProperty(String, Map)} + */ + @Deprecated public static EnumMultiPBuilder named(String name) { return new EnumMultiPBuilder<>(name); } + /** + * @deprecated Use {@link PropertyFactory#enumListProperty(String, Map)} + */ + @Deprecated public static final class EnumMultiPBuilder extends MultiValuePropertyBuilder> { private Class valueType; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/EnumeratedProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/EnumeratedProperty.java index d22cf55487..9d709a287b 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/EnumeratedProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/EnumeratedProperty.java @@ -22,7 +22,10 @@ import net.sourceforge.pmd.util.CollectionUtil; * @author Brian Remedios * @author Clément Fournier * @version Refactored June 2017 (6.0.0) + * @deprecated Use a {@code PropertyDescriptor} instead. A builder is available from {@link PropertyFactory#enumProperty(String, Map)}. + * This class will be removed in 7.0.0. */ +@Deprecated public final class EnumeratedProperty extends AbstractSingleValueProperty implements EnumeratedPropertyDescriptor { @@ -41,7 +44,7 @@ public final class EnumeratedProperty extends AbstractSingleValueProperty * @param valueType Type of the values * @param theUIOrder UI order * - * @deprecated will be removed in 7.0.0. Use {@link #EnumeratedProperty(String, String, Map, Object, Class, float)} + * @deprecated Use {@link PropertyFactory#enumProperty(String, Map)} */ @Deprecated public EnumeratedProperty(String theName, String theDescription, String[] theLabels, E[] theChoices, @@ -62,7 +65,7 @@ public final class EnumeratedProperty extends AbstractSingleValueProperty * @param defaultIndex Index of the default value * @param theUIOrder UI order * - * @deprecated will be removed in 7.0.0. Use {@link #EnumeratedProperty(String, String, Map, Object, Class, float)} + * @deprecated Use {@link PropertyFactory#enumProperty(String, Map)} */ @Deprecated public EnumeratedProperty(String theName, String theDescription, String[] theLabels, E[] theChoices, @@ -81,7 +84,9 @@ public final class EnumeratedProperty extends AbstractSingleValueProperty * @param defaultValue Default value * @param valueType Type of the values * @param theUIOrder UI order + * @deprecated Use {@link PropertyFactory#enumProperty(String, Map)} */ + @Deprecated public EnumeratedProperty(String theName, String theDescription, Map labelsToChoices, E defaultValue, Class valueType, float theUIOrder) { this(theName, theDescription, labelsToChoices, defaultValue, valueType, theUIOrder, false); @@ -128,10 +133,19 @@ public final class EnumeratedProperty extends AbstractSingleValueProperty } + /** + * @deprecated Use {@link PropertyFactory#enumProperty(String, Map)} + */ + @Deprecated public static EnumPBuilder named(String name) { return new EnumPBuilder<>(name); } + + /** + * @deprecated Use {@link PropertyFactory#enumProperty(String, Map)} + */ + @Deprecated public static final class EnumPBuilder extends SingleValuePropertyBuilder> { private Class valueType; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/FloatMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/FloatMultiProperty.java index 9a166dc60d..a35e56a9b3 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/FloatMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/FloatMultiProperty.java @@ -16,7 +16,8 @@ import net.sourceforge.pmd.properties.builders.PropertyDescriptorBuilderConversi * * @author Brian Remedios * @version Refactored June 2017 (6.0.0) - * @deprecated Will be removed with 7.0.0 with no scheduled replacement. Users should use {@link DoubleMultiProperty} instead + * @deprecated Use a {@code PropertyDescriptor>} instead. A builder is available from {@link PropertyFactory#doubleListProperty(String)}. + * This class will be removed in 7.0.0. */ @Deprecated public final class FloatMultiProperty extends AbstractMultiNumericProperty { @@ -33,7 +34,9 @@ public final class FloatMultiProperty extends AbstractMultiNumericProperty max} or one of the defaults is not between the bounds + * @deprecated use {@link PropertyFactory#doubleListProperty(String)} */ + @Deprecated public FloatMultiProperty(String theName, String theDescription, Float min, Float max, Float[] defaultValues, float theUIOrder) { this(theName, theDescription, min, max, Arrays.asList(defaultValues), theUIOrder, false); @@ -58,7 +61,9 @@ public final class FloatMultiProperty extends AbstractMultiNumericProperty max} or one of the defaults is not between the bounds + * @deprecated use {@link PropertyFactory#doubleListProperty(String)} */ + @Deprecated public FloatMultiProperty(String theName, String theDescription, Float min, Float max, List defaultValues, float theUIOrder) { this(theName, theDescription, min, max, defaultValues, theUIOrder, false); @@ -87,11 +92,15 @@ public final class FloatMultiProperty extends AbstractMultiNumericProperty { private FloatMultiPBuilder(String name) { super(name); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/FloatProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/FloatProperty.java index 9f0990e24f..c8a649b4ab 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/FloatProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/FloatProperty.java @@ -14,7 +14,7 @@ import net.sourceforge.pmd.properties.builders.SingleNumericPropertyBuilder; * Defines a property type that supports single float property values within an upper and lower boundary. * * - * @deprecated Will be removed with 7.0.0 with no scheduled replacement. Users should use {@link DoubleProperty} instead + * @deprecated Use {@link PropertyFactory#doubleProperty(String)} instead. This class will be removed with 7.0.0. * @author Brian Remedios */ @Deprecated @@ -33,8 +33,9 @@ public final class FloatProperty extends AbstractNumericProperty { * @param theUIOrder UI order * * @throws IllegalArgumentException if {@literal min > max} or one of the defaults is not between the bounds - * @deprecated will be removed in 7.0.0 + * @deprecated Use {@link PropertyFactory#doubleProperty(String)} instead. */ + @Deprecated public FloatProperty(String theName, String theDescription, String minStr, String maxStr, String defaultStr, float theUIOrder) { this(theName, theDescription, FLOAT_PARSER.valueOf(minStr), @@ -60,7 +61,9 @@ public final class FloatProperty extends AbstractNumericProperty { * @param theUIOrder UI order * * @throws IllegalArgumentException if {@literal min > max} or one of the defaults is not between the bounds + * @deprecated Use {@link PropertyFactory#doubleProperty(String)} instead. */ + @Deprecated public FloatProperty(String theName, String theDescription, Float min, Float max, Float theDefault, float theUIOrder) { this(theName, theDescription, min, max, theDefault, theUIOrder, false); @@ -88,12 +91,17 @@ public final class FloatProperty extends AbstractNumericProperty { }; } - + /** @deprecated Use {@link PropertyFactory#doubleProperty(String)} instead. */ + @Deprecated public static FloatPBuilder named(String name) { return new FloatPBuilder(name); } + /** + * @deprecated Use {@link PropertyFactory#doubleProperty(String)} instead. + */ + @Deprecated public static final class FloatPBuilder extends SingleNumericPropertyBuilder { private FloatPBuilder(String name) { super(name); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/GenericMultiValuePropertyDescriptor.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/GenericMultiValuePropertyDescriptor.java index 017a6e33ca..80f3ac0ef8 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/GenericMultiValuePropertyDescriptor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/GenericMultiValuePropertyDescriptor.java @@ -42,7 +42,7 @@ final class GenericMultiValuePropertyDescriptor> exte String dftValueError = errorFor(new ArrayList<>(defaultValue)); if (dftValueError != null) { - throw new IllegalStateException(dftValueError); + throw new IllegalArgumentException(dftValueError); } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/GenericPropertyDescriptor.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/GenericPropertyDescriptor.java index a059707d1d..4cd39da265 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/GenericPropertyDescriptor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/GenericPropertyDescriptor.java @@ -39,7 +39,7 @@ final class GenericPropertyDescriptor extends AbstractSingleValueProperty String dftValueError = errorFor(defaultValue); if (dftValueError != null) { - throw new IllegalStateException(dftValueError); + throw new IllegalArgumentException(dftValueError); } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/IntegerMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/IntegerMultiProperty.java index 3aa5781651..fbdb753d39 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/IntegerMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/IntegerMultiProperty.java @@ -16,7 +16,12 @@ import net.sourceforge.pmd.properties.builders.PropertyDescriptorBuilderConversi * * @author Brian Remedios * @version Refactored June 2017 (6.0.0) + * + * + * @deprecated Use a {@code PropertyDescriptor>} instead. A builder is available from {@link PropertyFactory#intListProperty(String)}. + * This class will be removed in 7.0.0. */ +@Deprecated public final class IntegerMultiProperty extends AbstractMultiNumericProperty { @@ -31,7 +36,9 @@ public final class IntegerMultiProperty extends AbstractMultiNumericProperty max} or one of the defaults is not between the bounds + * @deprecated Use {@link PropertyFactory#intListProperty(String)} */ + @Deprecated public IntegerMultiProperty(String theName, String theDescription, Integer min, Integer max, Integer[] defaultValues, float theUIOrder) { this(theName, theDescription, min, max, Arrays.asList(defaultValues), theUIOrder, false); @@ -57,7 +64,9 @@ public final class IntegerMultiProperty extends AbstractMultiNumericProperty max} or one of the defaults is not between the bounds + * @deprecated Use {@link PropertyFactory#intListProperty(String)} */ + @Deprecated public IntegerMultiProperty(String theName, String theDescription, Integer min, Integer max, List defaultValues, float theUIOrder) { @@ -87,11 +96,19 @@ public final class IntegerMultiProperty extends AbstractMultiNumericProperty { private IntegerMultiPBuilder(String name) { super(name); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/IntegerProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/IntegerProperty.java index 6508fa3fbe..e7628d38c4 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/IntegerProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/IntegerProperty.java @@ -14,7 +14,11 @@ import net.sourceforge.pmd.properties.builders.SingleNumericPropertyBuilder; * Defines a datatype that supports single Integer property values within an upper and lower boundary. * * @author Brian Remedios + * + * @deprecated Use a {@code PropertyDescriptor} instead. A builder is available from {@link PropertyFactory#intProperty(String)}. + * This class will be removed in 7.0.0. */ +@Deprecated public final class IntegerProperty extends AbstractNumericProperty { @@ -29,7 +33,10 @@ public final class IntegerProperty extends AbstractNumericProperty { * @param theUIOrder UI order * * @throws IllegalArgumentException if {@literal min > max} or one of the defaults is not between the bounds + * + * @deprecated Use {@link PropertyFactory#intProperty(String)} */ + @Deprecated public IntegerProperty(String theName, String theDescription, Integer min, Integer max, Integer theDefault, float theUIOrder) { this(theName, theDescription, min, max, theDefault, theUIOrder, false); @@ -65,11 +72,19 @@ public final class IntegerProperty extends AbstractNumericProperty { } + /** + * @deprecated Use {@link PropertyFactory#intProperty(String)} + */ + @Deprecated public static IntegerPBuilder named(String name) { return new IntegerPBuilder(name); } + /** + * @deprecated Use {@link PropertyFactory#intProperty(String)} + */ + @Deprecated public static final class IntegerPBuilder extends SingleNumericPropertyBuilder { private IntegerPBuilder(String name) { super(name); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/LongMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/LongMultiProperty.java index eb07bf17bc..3634c506b9 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/LongMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/LongMultiProperty.java @@ -16,7 +16,11 @@ import net.sourceforge.pmd.properties.builders.PropertyDescriptorBuilderConversi * * @author Brian Remedios * @version Refactored June 2017 (6.0.0) + * + * @deprecated Use a {@code PropertyDescriptor>} instead. A builder is available from {@link PropertyFactory#longIntListProperty(String)}. + * This class will be removed in 7.0.0. */ +@Deprecated public final class LongMultiProperty extends AbstractMultiNumericProperty { @@ -31,7 +35,9 @@ public final class LongMultiProperty extends AbstractMultiNumericProperty * @param theUIOrder UI order * * @throws IllegalArgumentException if {@literal min > max} or one of the defaults is not between the bounds + * @deprecated Use {@link PropertyFactory#longIntListProperty(String)} */ + @Deprecated public LongMultiProperty(String theName, String theDescription, Long min, Long max, Long[] defaultValues, float theUIOrder) { this(theName, theDescription, min, max, Arrays.asList(defaultValues), theUIOrder, false); @@ -56,7 +62,9 @@ public final class LongMultiProperty extends AbstractMultiNumericProperty * @param theUIOrder UI order * * @throws IllegalArgumentException if {@literal min > max} or one of the defaults is not between the bounds + * @deprecated Use {@link PropertyFactory#longIntListProperty(String)} */ + @Deprecated public LongMultiProperty(String theName, String theDescription, Long min, Long max, List defaultValues, float theUIOrder) { this(theName, theDescription, min, max, defaultValues, theUIOrder, false); @@ -85,11 +93,15 @@ public final class LongMultiProperty extends AbstractMultiNumericProperty } + /** @deprecated Use {@link PropertyFactory#longIntListProperty(String)} */ + @Deprecated public static LongMultiPBuilder named(String name) { return new LongMultiPBuilder(name); } + /** @deprecated Use {@link PropertyFactory#longIntListProperty(String)} */ + @Deprecated public static final class LongMultiPBuilder extends MultiNumericPropertyBuilder { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/LongProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/LongProperty.java index 020dc50f3e..e420a3b739 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/LongProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/LongProperty.java @@ -14,7 +14,11 @@ import net.sourceforge.pmd.properties.builders.SingleNumericPropertyBuilder; * @author Brian Remedios * @author Clément Fournier * @version Refactored June 2017 (6.0.0) + * + * @deprecated Use a {@code PropertyDescriptor} instead. A builder is available from {@link PropertyFactory#longIntProperty(String)}. + * This class will be removed in 7.0.0. */ +@Deprecated public final class LongProperty extends AbstractNumericProperty { @@ -30,8 +34,9 @@ public final class LongProperty extends AbstractNumericProperty { * @param theUIOrder UI order * * @throws IllegalArgumentException if {@literal min > max} or one of the defaults is not between the bounds - * @deprecated will be removed in 7.0.0 + * @deprecated Use {@link PropertyFactory#longIntProperty(String)} */ + @Deprecated public LongProperty(String theName, String theDescription, String minStr, String maxStr, String defaultStr, float theUIOrder) { this(theName, theDescription, Long.valueOf(minStr), Long.valueOf(maxStr), @@ -57,7 +62,9 @@ public final class LongProperty extends AbstractNumericProperty { * @param theUIOrder UI order * * @throws IllegalArgumentException if {@literal min > max} or one of the defaults is not between the bounds + * @deprecated Use {@link PropertyFactory#longIntProperty(String)} */ + @Deprecated public LongProperty(String theName, String theDescription, Long min, Long max, Long theDefault, float theUIOrder) { this(theName, theDescription, min, max, theDefault, theUIOrder, false); } @@ -85,11 +92,15 @@ public final class LongProperty extends AbstractNumericProperty { } + /** @deprecated Use {@link PropertyFactory#longIntProperty(String)} */ + @Deprecated public static LongPBuilder named(String name) { return new LongPBuilder(name); } + /** @deprecated Use {@link PropertyFactory#longIntProperty(String)} */ + @Deprecated public static final class LongPBuilder extends SingleNumericPropertyBuilder { private LongPBuilder(String name) { super(name); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/PropertyBuilder.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/PropertyBuilder.java index f5ea68375e..c2a18f9bf3 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/PropertyBuilder.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/PropertyBuilder.java @@ -7,6 +7,7 @@ package net.sourceforge.pmd.properties; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; @@ -18,10 +19,28 @@ import net.sourceforge.pmd.properties.PropertyBuilder.GenericCollectionPropertyB import net.sourceforge.pmd.properties.builders.PropertyDescriptorBuilder; import net.sourceforge.pmd.properties.constraints.PropertyConstraint; - +// @formatter:off /** * Base class for generic property builders. - * Note: from 7.0.0 on, all property builders will + * Property builders are obtained from the {@link PropertyFactory}, + * and are used to build {@link PropertyDescriptor}s. + * + *

All properties must specify the following attributes to build + * properly: + *

    + *
  • A name: filled-in when obtaining the builder + *
  • A description: see {@link #desc(String)} + *
  • A default value: see {@link #defaultValue(Object)} + *
+ * + *

The {@link PropertyDescriptor} may be built after those required steps by + * calling {@link #build()}. + * + *

A property builder may throw {@link IllegalArgumentException} at any + * stage during the build process to indicate invalid input. It usually tries + * to do so as early as possible, rather than waiting for the call to {@link #build()}. + * + *

Note: from 7.0.0 on, all property builders will * extend this class instead of {@link PropertyDescriptorBuilder}. * * @param Concrete type of this builder instance @@ -30,6 +49,7 @@ import net.sourceforge.pmd.properties.constraints.PropertyConstraint; * @author Clément Fournier * @since 6.10.0 */ +// @formatter:on public abstract class PropertyBuilder, T> { private static final Pattern NAME_PATTERN = Pattern.compile("[a-zA-Z][\\w-]*"); @@ -51,8 +71,6 @@ public abstract class PropertyBuilder, T> { } - // will maybe be scrapped - @Deprecated void setDefinedExternally(boolean bool) { this.isDefinedExternally = bool; } @@ -64,21 +82,39 @@ public abstract class PropertyBuilder, T> { String getDescription() { + if (StringUtils.isBlank(description)) { + throw new IllegalArgumentException("Description must be provided"); + } return description; } + /** Returns the value, asserting it has been set. */ T getDefaultValue() { + if (!isDefaultValueSet()) { + throw new IllegalArgumentException("A default value must be provided"); + } return defaultValue; } + boolean isDefaultValueSet() { + return defaultValue != null; + } + + /** - * Specify the description of the property. + * Specify the description of the property. This is used for documentation. + * Please describe precisely how the property may change the behaviour of the + * rule. Providing complete information should be preferred over being concise. + * + *

Calling this method is required for {@link #build()} to succeed. * * @param desc The description * * @return The same builder + * + * @throws IllegalArgumentException If the description is null or whitespace */ @SuppressWarnings("unchecked") public B desc(String desc) { @@ -89,6 +125,14 @@ public abstract class PropertyBuilder, T> { return (B) this; } + // TODO 7.0.0 document the following: + // + // *

Constraints should be independent from each other, and should + // * perform no side effects. PMD doesn't specify how many times a + // * constraint predicate will be executed, or in what order. + // + // This is superfluous right now bc users may not create their own constraints + /** * Add a constraint on the values that this property may take. @@ -99,8 +143,9 @@ public abstract class PropertyBuilder, T> { * @param constraint The constraint * * @return The same builder + * + * @see net.sourceforge.pmd.properties.constraints.NumericConstraints */ - // TODO we could probably specify the order of execution of constraints come 7.0.0, for now this remains unspecified @SuppressWarnings("unchecked") public B require(PropertyConstraint constraint) { validators.add(constraint); @@ -109,14 +154,23 @@ public abstract class PropertyBuilder, T> { /** - * Specify a default value. + * Specify a default value. Some subclasses provide convenient + * related methods, see e.g. {@link GenericCollectionPropertyBuilder#defaultValues(Object, Object[])}. + * Using the null value is prohibited. * - * @param val Value + *

Calling this method is required for {@link #build()} to succeed. + * + * @param val Default value * * @return The same builder + * + * @throws IllegalArgumentException If the argument is null */ @SuppressWarnings("unchecked") public B defaultValue(T val) { + if (val == null) { + throw new IllegalArgumentException("Property values may not be null."); + } this.defaultValue = val; return (B) this; } @@ -127,7 +181,7 @@ public abstract class PropertyBuilder, T> { * * @return The built descriptor * - * @throws IllegalStateException if the default value doesn't satisfy the given constraints + * @throws IllegalArgumentException if the description or default value were not provided, or if the default value doesn't satisfy the given constraints */ public abstract PropertyDescriptor build(); @@ -140,25 +194,19 @@ public abstract class PropertyBuilder, T> { } - /** - * Generic builder for a single-value property. - * - * @param Type of values the property handles - * - * @author Clément Fournier - * @since 6.10.0 - */ - // Note: we may keep some specialized property builders around to allow for some sugar, - // e.g. specifying the default value of a regex property as a string, or like the collection one, - // with varargs for collection types - public static final class GenericPropertyBuilder extends PropertyBuilder, T> { - - + // Technically this may very well be merged into PropertyBuilder + // We'd have all properties (even collection properties) enjoy a ValueParser, + // which means they could be parsed in a tag (collections would use delimiters) if they opt in. + // The delimiters wouldn't be configurable (we'd take our current defaults). If they could ambiguous + // then the syntax should be the only one available. + // This would allow specifying eg lists of numbers as 1,2,3, for which the syntax would look clumsy + abstract static class BaseSinglePropertyBuilder, T> extends PropertyBuilder { private final ValueParser parser; private final Class type; - GenericPropertyBuilder(String name, ValueParser parser, Class type) { + // Class is not final but a package-private constructor restricts inheritance + BaseSinglePropertyBuilder(String name, ValueParser parser, Class type) { super(name); this.parser = parser; this.type = type; @@ -197,9 +245,10 @@ public abstract class PropertyBuilder, T> { return toCollection(listSupplier); } + // TODO 7.0.0 this can be inlined private > GenericCollectionPropertyBuilder toCollection(Supplier emptyCollSupplier) { - if (getDefaultValue() != null) { + if (isDefaultValueSet()) { throw new IllegalStateException("The default value is already set!"); } @@ -230,14 +279,79 @@ public abstract class PropertyBuilder, T> { type ); } - - } + /** + * Generic builder for a single-value property. + * + * @param Type of values the property handles + * + * @author Clément Fournier + * @since 6.10.0 + */ + // Note: This type is used to fix the first type parameter for classes that don't need more API. + public static final class GenericPropertyBuilder extends BaseSinglePropertyBuilder, T> { + + GenericPropertyBuilder(String name, ValueParser parser, Class type) { + super(name, parser, type); + } + } + + + /** + * Specialized builder for regex properties. Allows specifying the pattern as a + * string, with {@link #defaultValue(String)}. + * + * @author Clément Fournier + * @since 6.10.0 + */ + public static final class RegexPropertyBuilder extends BaseSinglePropertyBuilder { + + RegexPropertyBuilder(String name) { + super(name, ValueParserConstants.REGEX_PARSER, Pattern.class); + } + + + /** + * Specify a default value using a string pattern. The argument is + * compiled to a pattern using {@link Pattern#compile(String)}. + * + * @param pattern String pattern + * + * @return The same builder + * + * @throws java.util.regex.PatternSyntaxException If the argument is not a valid pattern + */ + public RegexPropertyBuilder defaultValue(String pattern) { + super.defaultValue(Pattern.compile(pattern)); + return this; + } + + + /** + * Specify a default value using a string pattern. The argument is + * compiled to a pattern using {@link Pattern#compile(String, int)}. + * + * @param pattern String pattern + * @param flags Regex compilation flags, the same as for {@link Pattern#compile(String, int)} + * + * @return The same builder + * + * @throws java.util.regex.PatternSyntaxException If the argument is not a valid pattern + * @throws IllegalArgumentException If bit values other than those corresponding to the defined + * match flags are set in {@code flags} + */ + public RegexPropertyBuilder defaultValue(String pattern, int flags) { + super.defaultValue(Pattern.compile(pattern, flags)); + return this; + } + } + + /** * Generic builder for a collection-valued property. - * This class adds overloads to {@linkplain #defaultValues(Object[])} - * to make its use more flexible. + * This class adds methods related to {@link #defaultValue(Collection)} + * to make its use more flexible. See e.g. {@link #defaultValues(Object, Object[])}. * *

Note: this is designed to support arbitrary collections. * Pre-7.0.0, the only collections available from the {@link PropertyFactory} @@ -253,7 +367,7 @@ public abstract class PropertyBuilder, T> { private final ValueParser parser; private final Supplier emptyCollSupplier; private final Class type; - private char multiValueDelimiter; + private char multiValueDelimiter = MultiValuePropertyDescriptor.DEFAULT_DELIMITER; /** @@ -292,21 +406,36 @@ public abstract class PropertyBuilder, T> { /** - * Specify default values. + * Specify default values. To specify an empty + * default value, use {@link #emptyDefaultValue()}. * - * @param val List of values + * @param head First value + * @param tail Rest of the values * * @return The same builder */ @SuppressWarnings("unchecked") - public GenericCollectionPropertyBuilder defaultValues(V... val) { - return super.defaultValue(getDefaultValue(Arrays.asList(val))); + public GenericCollectionPropertyBuilder defaultValues(V head, V... tail) { + List tmp = new ArrayList<>(tail.length + 1); + tmp.add(head); + tmp.addAll(Arrays.asList(tail)); + return super.defaultValue(getDefaultValue(tmp)); + } + + + /** + * Specify that the default value is an empty collection. + * + * @return The same builder + */ + public GenericCollectionPropertyBuilder emptyDefaultValue() { + return super.defaultValue(getDefaultValue(Collections.emptyList())); } /** * Require that the given constraint be fulfilled on each item of the - * value of this properties. This is a convenient shorthand for + * value of this property. This is a convenient shorthand for * {@code require(constraint.toCollectionConstraint())}. * * @param constraint Constraint to impose on the items of the collection value diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/PropertyFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/PropertyFactory.java index b76e7321d0..2a1a10c239 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/PropertyFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/PropertyFactory.java @@ -9,18 +9,69 @@ import java.util.Map; import net.sourceforge.pmd.properties.PropertyBuilder.GenericCollectionPropertyBuilder; import net.sourceforge.pmd.properties.PropertyBuilder.GenericPropertyBuilder; +import net.sourceforge.pmd.properties.PropertyBuilder.RegexPropertyBuilder; +import net.sourceforge.pmd.properties.constraints.NumericConstraints; +import net.sourceforge.pmd.properties.constraints.PropertyConstraint; - +//@formatter:off /** * Provides factory methods for common property types. * Note: from 7.0.0 on, this will be the only way to - * build property descriptors. + * build property descriptors. Concrete property classes + * and their constructors/ builders will be gradually + * deprecated before 7.0.0. + * + *

Usage

+ * + * Properties are a way to make your rule configurable by + * letting a user fill in some config value in their + * ruleset XML. + * + * As a rule developer, to declare a property on your rule, you + * must: + *
    + *
  • Build a {@link PropertyDescriptor} using one of + * the factory methods of this class, and providing the + * {@linkplain PropertyBuilder builder} with the required + * info. + *
  • Define the property on your rule using {@link PropertySource#definePropertyDescriptor(PropertyDescriptor)}. + * This should be done in your rule's constructor. + *
+ * + * You can then retrieve the value configured by the user in your + * rule using {@link PropertySource#getProperty(PropertyDescriptor)}. + * + *

Example

+ * + *
+ * class MyRule {
+ *   // The property descriptor may be static, it can be shared across threads.
+ *   private static final {@link PropertyDescriptor}<Integer> myIntProperty
+ *     = PropertyFactory.{@linkplain #intProperty(String) intProperty}("myIntProperty")
+ *                      .{@linkplain PropertyBuilder#desc(String) desc}("This is my property")
+ *                      .{@linkplain PropertyBuilder#defaultValue(Object) defaultValue}(3)
+ *                      .{@linkplain PropertyBuilder#require(PropertyConstraint) require}(inRange(0, 100))   // constraints are checked before the rule is run
+ *                      .{@linkplain PropertyBuilder#build() build}();
+ *
+ *   // ..
+ *
+ *   public MyRule() {
+ *     {@linkplain PropertySource#definePropertyDescriptor(PropertyDescriptor) definePropertyDescriptor}(myIntProperty);
+ *   }
+ *
+ *     // ... somewhere in the rule
+ *
+ *     int myPropertyValue = {@linkplain PropertySource#getProperty(PropertyDescriptor) getProperty(myIntProperty)};
+ *     // use it.
+ *
+ * }
+ * 
* - * TODO next PR add doc * * @author Clément Fournier * @since 6.10.0 */ +//@formatter:on public final class PropertyFactory { private PropertyFactory() { @@ -28,36 +79,221 @@ public final class PropertyFactory { } + /** + * Returns a builder for an integer property. The property descriptor + * will by default accept any value conforming to the format specified + * by {@link Integer#parseInt(String)}, e.g. {@code 1234} or {@code -123}. + * + *

Note that that parser only supports decimal representations. + * + *

Acceptable values may be further refined by {@linkplain PropertyBuilder#require(PropertyConstraint) adding constraints}. + * The class {@link NumericConstraints} provides some useful ready-made constraints + * for that purpose. + * + * @param name Name of the property to build + * + * @return A new builder + * + * @see NumericConstraints + */ public static GenericPropertyBuilder intProperty(String name) { return new GenericPropertyBuilder<>(name, ValueParserConstants.INTEGER_PARSER, Integer.class); } + /** + * Returns a builder for a property having as value a list of integers. The + * format of the individual items is the same as for {@linkplain #intProperty(String) intProperty}. + * + * @param name Name of the property to build + * + * @return A new builder + */ public static GenericCollectionPropertyBuilder> intListProperty(String name) { return intProperty(name).toList().delim(MultiValuePropertyDescriptor.DEFAULT_NUMERIC_DELIMITER); } + /** + * Returns a builder for a long integer property. The property descriptor + * will by default accept any value conforming to the format specified + * by {@link Long#parseLong(String)}, e.g. {@code 1234455678854}. + * + *

Note that that parser only supports decimal representations, and that neither + * the character L nor l is permitted to appear at the end of the string as a type + * indicator, as would be permitted in Java source. + * + *

Acceptable values may be further refined by {@linkplain PropertyBuilder#require(PropertyConstraint) adding constraints}. + * The class {@link NumericConstraints} provides some useful ready-made constraints + * for that purpose. + * + * @param name Name of the property to build + * + * @return A new builder + * + * @see NumericConstraints + */ + public static GenericPropertyBuilder longIntProperty(String name) { + return new GenericPropertyBuilder<>(name, ValueParserConstants.LONG_PARSER, Long.class); + } + + + /** + * Returns a builder for a property having as value a list of long integers. The + * format of the individual items is the same as for {@linkplain #longIntProperty(String)} longIntProperty}. + * + * @param name Name of the property to build + * + * @return A new builder + */ + public static GenericCollectionPropertyBuilder> longIntListProperty(String name) { + return longIntProperty(name).toList().delim(MultiValuePropertyDescriptor.DEFAULT_NUMERIC_DELIMITER); + } + + + /** + * Returns a builder for a double property. The property descriptor + * will by default accept any value conforming to the format specified + * by {@link Double#valueOf(String)}, e.g. {@code 0}, {@code .93}, or {@code 1e-1}. + * Acceptable values may be further refined by {@linkplain PropertyBuilder#require(PropertyConstraint) adding constraints}. + * The class {@link NumericConstraints} provides some useful ready-made constraints + * for that purpose. + * + * @param name Name of the property to build + * + * @return A new builder + * + * @see NumericConstraints + */ public static GenericPropertyBuilder doubleProperty(String name) { return new GenericPropertyBuilder<>(name, ValueParserConstants.DOUBLE_PARSER, Double.class); } + /** + * Returns a builder for a property having as value a list of decimal numbers. The + * format of the individual items is the same as for {@linkplain #doubleProperty(String) doubleProperty}. + * + * @param name Name of the property to build + * + * @return A new builder + */ public static GenericCollectionPropertyBuilder> doubleListProperty(String name) { return doubleProperty(name).toList().delim(MultiValuePropertyDescriptor.DEFAULT_NUMERIC_DELIMITER); } + /** + * Returns a builder for a regex property. The value type of such + * a property is {@link java.util.regex.Pattern}. For this use case, this type of + * property should be preferred over {@linkplain #stringProperty(String) stringProperty} + * as pattern compilation, including syntax errors, are handled transparently to + * the rule. + * + *

This type of property is not available as a list, because the delimiters + * could be part of the regex. This restriction will be lifted with 7.0.0. + * + * @param name Name of the property to build + * + * @return A new builder + */ + public static RegexPropertyBuilder regexProperty(String name) { + return new RegexPropertyBuilder(name); + } + + + /** + * Returns a builder for a string property. The property descriptor + * will accept any string, and performs no expansion of escape + * sequences (e.g. {@code \n} in the XML will be represented as the + * character sequence '\' 'n' and not the line-feed character '\n'). + * This behaviour could be changed with PMD 7.0.0. + * + * @param name Name of the property to build + * + * @return A new builder + */ public static GenericPropertyBuilder stringProperty(String name) { return new GenericPropertyBuilder<>(name, ValueParserConstants.STRING_PARSER, String.class); } + /** + * Returns a builder for a property having as value a list of strings. The + * format of the individual items is the same as for {@linkplain #stringProperty(String) stringProperty}. + * + * @param name Name of the property to build + * + * @return A new builder + */ public static GenericCollectionPropertyBuilder> stringListProperty(String name) { - return stringProperty(name).toList().delim(MultiValuePropertyDescriptor.DEFAULT_DELIMITER); + return stringProperty(name).toList(); } + /** + * Returns a builder for a character property. The property descriptor + * will accept any single character string. No unescaping is performed + * other than what the XML parser does itself. That means that Java + * escape sequences are not expanded: e.g. "\n", will be represented as the + * character sequence '\' 'n', so it's not a valid value for this type + * of property. On the other hand, XML character references are expanded, + * like {@literal &} ('&') or {@literal <} ('<'). + * + * @param name Name of the property to build + * + * @return A new builder + */ + public static GenericPropertyBuilder charProperty(String name) { + return new GenericPropertyBuilder<>(name, ValueParserConstants.CHARACTER_PARSER, Character.class); + } + + + /** + * Returns a builder for a property having as value a list of characters. The + * format of the individual items is the same as for {@linkplain #charProperty(String) charProperty}. + * + * @param name Name of the property to build + * + * @return A new builder + */ + public static GenericCollectionPropertyBuilder> charListProperty(String name) { + return charProperty(name).toList(); + } + + + /** + * Returns a builder for a boolean property. The boolean is parsed from + * the XML using {@link Boolean#valueOf(String)}, i.e. the only truthy + * value is the string "true", and all other string values are falsy. + * + * @param name Name of the property to build + * + * @return A new builder + */ + public static GenericPropertyBuilder booleanProperty(String name) { + return new GenericPropertyBuilder<>(name, ValueParserConstants.BOOLEAN_PARSER, Boolean.class); + } + + // We can add more useful factories with Java 8. + // * We don't really need a Map, just a Function. + // * We could have a factory taking a Class> + // and a Function to build a mapper for a whole enum. + + /** + * Returns a builder for an enumerated property. Such a property can be + * defined for any type {@code }, provided the possible values can be + * indexed by strings. This is enforced by passing a {@code Map} + * at construction time, which maps labels to values. If {@link Map#get(Object)} + * returns null for a given label, then the value is rejected. Null values + * are hence prohibited. + * + * @param name Name of the property to build + * @param nameToValue Map of labels to values. The null key is ignored. + * @param Value type of the property + * + * @return A new builder + */ public static GenericPropertyBuilder enumProperty(String name, Map nameToValue) { // TODO find solution to document the set of possible values // At best, map that requirement to a constraint (eg make parser return null if not found, and @@ -66,8 +302,18 @@ public final class PropertyFactory { } + /** + * Returns a builder for a property having as value a list of {@code }. The + * format of the individual items is the same as for {@linkplain #enumProperty(String, Map)}. + * + * @param name Name of the property to build + * @param nameToValue Map of labels to values. The null key is ignored. + * @param Value type of the property + * + * @return A new builder + */ public static GenericCollectionPropertyBuilder> enumListProperty(String name, Map nameToValue) { - return enumProperty(name, nameToValue).toList(); + return enumProperty(name, nameToValue).toList().delim(MultiValuePropertyDescriptor.DEFAULT_DELIMITER); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/PropertyTypeId.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/PropertyTypeId.java index 4e78fc04c2..f6984d9efa 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/PropertyTypeId.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/PropertyTypeId.java @@ -34,6 +34,8 @@ public enum PropertyTypeId { // e.g. the Class type), including the mnemonics (eg. xs:integer instead of Integer) BOOLEAN("Boolean", BooleanProperty.extractor(), ValueParserConstants.BOOLEAN_PARSER), + /** @deprecated see {@link BooleanMultiProperty} */ + @Deprecated BOOLEAN_LIST("List[Boolean]", BooleanMultiProperty.extractor(), ValueParserConstants.BOOLEAN_PARSER), STRING("String", StringProperty.extractor(), ValueParserConstants.STRING_PARSER), diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/RegexProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/RegexProperty.java index c7559693b9..3904893b33 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/RegexProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/RegexProperty.java @@ -18,7 +18,10 @@ import net.sourceforge.pmd.properties.builders.SingleValuePropertyBuilder; * * @author Clément Fournier * @since 6.2.0 + * @deprecated Use a {@code PropertyDescriptor}. A builder is available from {@link PropertyFactory#regexProperty(String)}. + * This class will be removed in 7.0.0. */ +@Deprecated public final class RegexProperty extends AbstractSingleValueProperty { RegexProperty(String theName, String theDescription, Pattern theDefault, float theUIOrder, boolean isDefinedExternally) { @@ -54,12 +57,21 @@ public final class RegexProperty extends AbstractSingleValueProperty { * @param name The name of the property * * @return A new builder + * + * @deprecated Use {@link PropertyFactory#regexProperty(String)} */ + @Deprecated public static RegexPBuilder named(String name) { return new RegexPBuilder(name); } - /** Builder for a {@link RegexProperty}. */ + + /** + * Builder for a {@link RegexProperty}. + * + * @deprecated Use {@link PropertyFactory#regexProperty(String)} + */ + @Deprecated public static final class RegexPBuilder extends SingleValuePropertyBuilder { private RegexPBuilder(String name) { super(name); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/StringMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/StringMultiProperty.java index 538c0abc20..6ef59d7bb6 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/StringMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/StringMultiProperty.java @@ -19,7 +19,10 @@ import net.sourceforge.pmd.properties.builders.PropertyDescriptorBuilderConversi * * @author Brian Remedios * @version Refactored June 2017 (6.0.0) + * @deprecated Use a {@code PropertyDescriptor>}. A builder is available from {@link PropertyFactory#stringListProperty(String)}. + * This class will be removed in 7.0.0. */ +@Deprecated public final class StringMultiProperty extends AbstractMultiValueProperty { @@ -34,7 +37,9 @@ public final class StringMultiProperty extends AbstractMultiValueProperty defaultValues, float theUIOrder, char delimiter) { this(theName, theDescription, defaultValues, theUIOrder, delimiter, false); @@ -147,11 +154,19 @@ public final class StringMultiProperty extends AbstractMultiValueProperty { private StringMultiPBuilder(String name) { super(name); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/StringProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/StringProperty.java index 0fe2652845..d48c78187c 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/StringProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/StringProperty.java @@ -13,7 +13,10 @@ import net.sourceforge.pmd.properties.builders.SingleValuePropertyBuilder; * * @author Brian Remedios * @version Refactored June 2017 (6.0.0) + * @deprecated Use a {@code PropertyDescriptor}. A builder is available from {@link PropertyFactory#stringProperty(String)}. + * This class will be removed in 7.0.0. */ +@Deprecated public final class StringProperty extends AbstractSingleValueProperty { /** @@ -23,7 +26,10 @@ public final class StringProperty extends AbstractSingleValueProperty { * @param theDescription Description * @param defaultValue Default value * @param theUIOrder UI order + * + * @deprecated Use {@link PropertyFactory#stringProperty(String)} */ + @Deprecated public StringProperty(String theName, String theDescription, String defaultValue, float theUIOrder) { this(theName, theDescription, defaultValue, theUIOrder, false); } @@ -31,7 +37,7 @@ public final class StringProperty extends AbstractSingleValueProperty { /** Master constructor. */ private StringProperty(String theName, String theDescription, String defaultValue, float theUIOrder, boolean - isDefinedExternally) { + isDefinedExternally) { super(theName, theDescription, defaultValue, theUIOrder, isDefinedExternally); } @@ -58,11 +64,19 @@ public final class StringProperty extends AbstractSingleValueProperty { } + /** + * @deprecated Use {@link PropertyFactory#stringProperty(String)} + */ + @Deprecated public static StringPBuilder named(String name) { return new StringPBuilder(name); } + /** + * @deprecated Use {@link PropertyFactory#stringProperty(String)} + */ + @Deprecated public static final class StringPBuilder extends SingleValuePropertyBuilder { private StringPBuilder(String name) { super(name); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/ValueParserConstants.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/ValueParserConstants.java index e5f623ffb3..5f9aec1c7e 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/ValueParserConstants.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/ValueParserConstants.java @@ -240,6 +240,11 @@ public final class ValueParserConstants { static ValueParser enumerationParser(final Map mappings) { + + if (mappings.containsValue(null)) { + throw new IllegalArgumentException("Map may not contain entries with null values"); + } + return new ValueParser() { @Override public T valueOf(String value) throws IllegalArgumentException { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/renderers/CSVRenderer.java b/pmd-core/src/main/java/net/sourceforge/pmd/renderers/CSVRenderer.java index 8c3ef261c2..6daddb79ad 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/renderers/CSVRenderer.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/renderers/CSVRenderer.java @@ -15,10 +15,12 @@ import org.apache.commons.lang3.StringUtils; import net.sourceforge.pmd.PMD; import net.sourceforge.pmd.RuleViolation; -import net.sourceforge.pmd.properties.BooleanProperty; +import net.sourceforge.pmd.properties.PropertyDescriptor; +import net.sourceforge.pmd.properties.PropertyFactory; import net.sourceforge.pmd.properties.PropertySource; import net.sourceforge.pmd.renderers.ColumnDescriptor.Accessor; + /** * Renderer the results to a comma-delimited text format. All available columns * are present by default. IDEs can enable/disable columns individually @@ -33,7 +35,7 @@ public class CSVRenderer extends AbstractIncrementingRenderer { private static final String DEFAULT_SEPARATOR = ","; - private static final Map PROPERTY_DESCRIPTORS_BY_ID = new HashMap<>(); + private static final Map> PROPERTY_DESCRIPTORS_BY_ID = new HashMap<>(); public static final String NAME = "csv"; @@ -96,14 +98,14 @@ public class CSVRenderer extends AbstractIncrementingRenderer { this(ALL_COLUMNS, DEFAULT_SEPARATOR, PMD.EOL); } - private static BooleanProperty booleanPropertyFor(String id, String label) { + private static PropertyDescriptor booleanPropertyFor(String id, String label) { - BooleanProperty prop = PROPERTY_DESCRIPTORS_BY_ID.get(id); + PropertyDescriptor prop = PROPERTY_DESCRIPTORS_BY_ID.get(id); if (prop != null) { return prop; } - prop = new BooleanProperty(id, "Include " + label + " column", true, 1.0f); + prop = PropertyFactory.booleanProperty(id).defaultValue(true).desc("Include " + label + " column").build(); PROPERTY_DESCRIPTORS_BY_ID.put(id, prop); return prop; } @@ -113,12 +115,11 @@ public class CSVRenderer extends AbstractIncrementingRenderer { List> actives = new ArrayList<>(); for (ColumnDescriptor desc : ALL_COLUMNS) { - BooleanProperty prop = booleanPropertyFor(desc.id, null); + PropertyDescriptor prop = booleanPropertyFor(desc.id, null); if (getProperty(prop)) { actives.add(desc); - } else { - // System.out.println("disabled: " + prop); } + } return actives; } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/renderers/CodeClimateRule.java b/pmd-core/src/main/java/net/sourceforge/pmd/renderers/CodeClimateRule.java index 0db97409c5..88991c7497 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/renderers/CodeClimateRule.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/renderers/CodeClimateRule.java @@ -54,6 +54,7 @@ public interface CodeClimateRule extends Rule { } } + // these properties may not be updated yet /** * Defines the code climate categories for which this rule will find diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/renderers/HTMLRenderer.java b/pmd-core/src/main/java/net/sourceforge/pmd/renderers/HTMLRenderer.java index ecebba5dd5..29e485a4cf 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/renderers/HTMLRenderer.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/renderers/HTMLRenderer.java @@ -28,6 +28,7 @@ public class HTMLRenderer extends AbstractIncrementingRenderer { public static final String NAME = "html"; + // TODO 7.0.0 use PropertyDescriptor public static final StringProperty LINE_PREFIX = new StringProperty("linePrefix", "Prefix for line number anchor in the source file.", null, 1); public static final StringProperty LINK_PREFIX = new StringProperty("linkPrefix", "Path to HTML source.", null, 0); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/renderers/IDEAJRenderer.java b/pmd-core/src/main/java/net/sourceforge/pmd/renderers/IDEAJRenderer.java index f6cddabd64..5f67921a15 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/renderers/IDEAJRenderer.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/renderers/IDEAJRenderer.java @@ -25,6 +25,7 @@ public class IDEAJRenderer extends AbstractIncrementingRenderer { public static final String NAME = "ideaj"; + // TODO 7.0.0 use PropertyDescriptor public static final StringProperty FILE_NAME = new StringProperty("fileName", "File name.", "", 0); public static final StringProperty SOURCE_PATH = new StringProperty("sourcePath", "Source path.", "", 1); public static final StringProperty CLASS_AND_METHOD_NAME = new StringProperty("classAndMethodName", diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/renderers/TextColorRenderer.java b/pmd-core/src/main/java/net/sourceforge/pmd/renderers/TextColorRenderer.java index f28df9dab3..bd2f60bfd2 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/renderers/TextColorRenderer.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/renderers/TextColorRenderer.java @@ -7,9 +7,10 @@ package net.sourceforge.pmd.renderers; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; -import java.io.FileReader; import java.io.IOException; import java.io.Reader; +import java.nio.charset.Charset; +import java.nio.file.Files; import java.util.Iterator; import java.util.Map; @@ -53,6 +54,7 @@ public class TextColorRenderer extends AbstractAccumulatingRenderer { public static final String NAME = "textcolor"; + // What? TODO 7.0.0 Use a boolean property public static final StringProperty COLOR = new StringProperty("color", "Enables colors with anything other than 'false' or '0'.", "yes", 0); private static final String SYSTEM_PROPERTY_PMD_COLOR = "pmd.color"; @@ -201,7 +203,13 @@ public class TextColorRenderer extends AbstractAccumulatingRenderer { } protected Reader getReader(String sourceFile) throws FileNotFoundException { - return new FileReader(new File(sourceFile)); + try { + return Files.newBufferedReader(new File(sourceFile).toPath(), Charset.defaultCharset()); + } catch (IOException e) { + FileNotFoundException ex = new FileNotFoundException(sourceFile); + ex.initCause(e); + throw ex; + } } /** diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/renderers/XMLRenderer.java b/pmd-core/src/main/java/net/sourceforge/pmd/renderers/XMLRenderer.java index 5249555170..d4f4f13e90 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/renderers/XMLRenderer.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/renderers/XMLRenderer.java @@ -24,6 +24,7 @@ public class XMLRenderer extends AbstractIncrementingRenderer { public static final String NAME = "xml"; + // TODO 7.0.0 use PropertyDescriptor or something more specialized public static final StringProperty ENCODING = new StringProperty("encoding", "XML encoding format, defaults to UTF-8.", "UTF-8", 0); private boolean useUTF8 = false; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/renderers/XSLTRenderer.java b/pmd-core/src/main/java/net/sourceforge/pmd/renderers/XSLTRenderer.java index 7c28598175..62b90da9ec 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/renderers/XSLTRenderer.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/renderers/XSLTRenderer.java @@ -5,13 +5,13 @@ package net.sourceforge.pmd.renderers; import java.io.File; -import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.StringReader; import java.io.StringWriter; import java.io.Writer; +import java.nio.file.Files; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; @@ -38,6 +38,7 @@ public class XSLTRenderer extends XMLRenderer { public static final String NAME = "xslt"; + // TODO 7.0.0 use PropertyDescriptor> public static final StringProperty XSLT_FILENAME = new StringProperty("xsltFilename", "The XSLT file name.", null, 0); @@ -77,12 +78,12 @@ public class XSLTRenderer extends XMLRenderer { InputStream xslt = null; File file = new File(this.xsltFilename); if (file.exists() && file.canRead()) { - xslt = new FileInputStream(file); + xslt = Files.newInputStream(file.toPath()); } else { xslt = this.getClass().getResourceAsStream(this.xsltFilename); } if (xslt == null) { - throw new FileNotFoundException("Can't file XSLT sheet :" + this.xsltFilename); + throw new FileNotFoundException("Can't find XSLT file: " + this.xsltFilename); } this.prepareTransformer(xslt); // Now we build the XML file diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/renderers/YAHTMLRenderer.java b/pmd-core/src/main/java/net/sourceforge/pmd/renderers/YAHTMLRenderer.java index f716b536e4..279fb89c02 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/renderers/YAHTMLRenderer.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/renderers/YAHTMLRenderer.java @@ -5,9 +5,10 @@ package net.sourceforge.pmd.renderers; import java.io.File; -import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -26,6 +27,7 @@ import net.sourceforge.pmd.properties.StringProperty; public class YAHTMLRenderer extends AbstractAccumulatingRenderer { public static final String NAME = "yahtml"; + // TODO 7.0.0 use PropertyDescriptor> with a constraint that the file is an existing directory public static final StringProperty OUTPUT_DIR = new StringProperty("outputDir", "Output directory.", null, 0); private SortedMap reportNodesByPackage = new TreeMap<>(); @@ -98,9 +100,11 @@ public class YAHTMLRenderer extends AbstractAccumulatingRenderer { } private void renderIndex(String outputDir) throws IOException { - try (PrintWriter out = new PrintWriter(new FileWriter(new File(outputDir, "index.html")))) { + try (PrintWriter out = new PrintWriter(Files.newBufferedWriter(new File(outputDir, "index.html").toPath(), StandardCharsets.UTF_8))) { + out.println(""); out.println(""); out.println(" "); + out.println(" "); out.println(" PMD"); out.println(" "); out.println(" "); @@ -137,9 +141,11 @@ public class YAHTMLRenderer extends AbstractAccumulatingRenderer { private void renderClasses(String outputDir) throws IOException { for (ReportNode node : reportNodesByPackage.values()) { if (node.hasViolations()) { - try (PrintWriter out = new PrintWriter(new FileWriter(new File(outputDir, node.getClassName() + ".html")))) { + try (PrintWriter out = new PrintWriter(Files.newBufferedWriter(new File(outputDir, node.getClassName() + ".html").toPath(), StandardCharsets.UTF_8))) { + out.println(""); out.println(""); out.println(" "); + out.println(" "); out.print(" PMD - "); out.print(node.getClassName()); out.println(""); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/FileIterable.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/FileIterable.java index 26ae2a4a1b..26f56edc44 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/util/FileIterable.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/util/FileIterable.java @@ -5,10 +5,10 @@ package net.sourceforge.pmd.util; import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileReader; import java.io.IOException; import java.io.LineNumberReader; +import java.nio.charset.Charset; +import java.nio.file.Files; import java.util.Iterator; /** @@ -26,10 +26,9 @@ public class FileIterable implements Iterable { private LineNumberReader lineReader = null; public FileIterable(File file) { - try { - lineReader = new LineNumberReader(new FileReader(file)); - } catch (FileNotFoundException e) { + lineReader = new LineNumberReader(Files.newBufferedReader(file.toPath(), Charset.defaultCharset())); + } catch (IOException e) { throw new IllegalStateException(e); } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/IOUtil.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/IOUtil.java index e812c7ad26..9b9ac61911 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/util/IOUtil.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/util/IOUtil.java @@ -5,13 +5,14 @@ package net.sourceforge.pmd.util; import java.io.BufferedReader; -import java.io.BufferedWriter; import java.io.Closeable; -import java.io.FileWriter; +import java.io.File; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Reader; import java.io.Writer; +import java.nio.charset.Charset; +import java.nio.file.Files; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; @@ -31,7 +32,8 @@ public final class IOUtil { public static Writer createWriter(String reportFile) { try { - return StringUtils.isBlank(reportFile) ? createWriter() : new BufferedWriter(new FileWriter(reportFile)); + return StringUtils.isBlank(reportFile) ? createWriter() + : Files.newBufferedWriter(new File(reportFile).toPath(), Charset.defaultCharset()); } catch (IOException e) { throw new IllegalArgumentException(e); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/ResourceLoader.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/ResourceLoader.java index 27587aa57d..6629ec3cc7 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/util/ResourceLoader.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/util/ResourceLoader.java @@ -5,13 +5,12 @@ package net.sourceforge.pmd.util; import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; +import java.nio.file.Files; import java.util.Objects; import net.sourceforge.pmd.RuleSetNotFoundException; @@ -60,8 +59,8 @@ public class ResourceLoader { final File file = new File(name); if (file.exists()) { try { - return new FileInputStream(file); - } catch (final FileNotFoundException e) { + return Files.newInputStream(file.toPath()); + } catch (final IOException e) { // if the file didn't exist, we wouldn't be here throw new RuntimeException(e); // somehow the file vanished between checking for existence and opening } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/database/DBType.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/database/DBType.java index 56d8a978a0..81c740ee2c 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/util/database/DBType.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/util/database/DBType.java @@ -5,10 +5,10 @@ package net.sourceforge.pmd.util.database; import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.NoSuchFileException; import java.util.Properties; import java.util.PropertyResourceBundle; import java.util.ResourceBundle; @@ -171,21 +171,21 @@ public class DBType { if (LOGGER.isLoggable(Level.FINEST)) { LOGGER.finest("Attempting File no file suffix: " + matchString); } - try (InputStream stream = new FileInputStream(propertiesFile)) { + try (InputStream stream = Files.newInputStream(propertiesFile.toPath())) { resourceBundle = new PropertyResourceBundle(stream); propertiesSource = propertiesFile.getAbsolutePath(); LOGGER.finest("FileSystemWithoutExtension"); - } catch (FileNotFoundException notFoundOnFilesystemWithoutExtension) { + } catch (NoSuchFileException notFoundOnFilesystemWithoutExtension) { if (LOGGER.isLoggable(Level.FINEST)) { LOGGER.finest("notFoundOnFilesystemWithoutExtension"); LOGGER.finest("Attempting File with added file suffix: " + matchString + ".properties"); } - try (InputStream stream = new FileInputStream(propertiesFile)) { - propertiesFile = new File(matchString + ".properties"); + propertiesFile = new File(matchString + ".properties"); + try (InputStream stream = Files.newInputStream(propertiesFile.toPath())) { resourceBundle = new PropertyResourceBundle(stream); propertiesSource = propertiesFile.getAbsolutePath(); LOGGER.finest("FileSystemWithExtension"); - } catch (FileNotFoundException notFoundOnFilesystemWithExtensionTackedOn) { + } catch (NoSuchFileException notFoundOnFilesystemWithExtensionTackedOn) { if (LOGGER.isLoggable(Level.FINEST)) { LOGGER.finest("Attempting JARWithoutClassPrefix: " + matchString); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/datasource/FileDataSource.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/datasource/FileDataSource.java index 6c52cd2e29..b4bb31aa01 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/util/datasource/FileDataSource.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/util/datasource/FileDataSource.java @@ -5,9 +5,9 @@ package net.sourceforge.pmd.util.datasource; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; +import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -30,7 +30,7 @@ public class FileDataSource implements DataSource { @Override public InputStream getInputStream() throws IOException { - return new FileInputStream(file); + return Files.newInputStream(file.toPath()); } @Override diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/AbstractRuleTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/AbstractRuleTest.java index 999488418d..f42e4b058c 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/AbstractRuleTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/AbstractRuleTest.java @@ -4,6 +4,7 @@ package net.sourceforge.pmd; +import static net.sourceforge.pmd.properties.constraints.NumericConstraints.inRange; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -20,10 +21,11 @@ import net.sourceforge.pmd.lang.ast.DummyNode; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.rule.AbstractRule; import net.sourceforge.pmd.lang.rule.ParametricRuleViolation; -import net.sourceforge.pmd.properties.IntegerProperty; import net.sourceforge.pmd.properties.PropertyDescriptor; +import net.sourceforge.pmd.properties.PropertyFactory; import net.sourceforge.pmd.properties.StringProperty; + public class AbstractRuleTest { public static class MyRule extends AbstractRule { @@ -86,7 +88,7 @@ public class AbstractRuleTest { DummyNode s = new DummyNode(1); s.testingOnlySetBeginColumn(5); s.testingOnlySetBeginLine(5); - RuleViolation rv = new ParametricRuleViolation(r, ctx, s, "specificdescription"); + RuleViolation rv = new ParametricRuleViolation<>(r, ctx, s, "specificdescription"); assertEquals("Line number mismatch!", 5, rv.getBeginLine()); assertEquals("Filename mismatch!", "filename", rv.getFilename()); assertEquals("Rule object mismatch!", r, rv.getRule()); @@ -96,7 +98,7 @@ public class AbstractRuleTest { @Test public void testRuleWithVariableInMessage() { MyRule r = new MyRule(); - r.definePropertyDescriptor(IntegerProperty.named("testInt").desc("description").range(0, 100).defaultValue(10).uiOrder(0).build()); + r.definePropertyDescriptor(PropertyFactory.intProperty("testInt").desc("description").require(inRange(0, 100)).defaultValue(10).build()); r.setMessage("Message ${packageName} ${className} ${methodName} ${variableName} ${testInt} ${noSuchProperty}"); RuleContext ctx = new RuleContext(); ctx.setLanguageVersion(LanguageRegistry.getLanguage(DummyLanguageModule.NAME).getDefaultVersion()); @@ -123,7 +125,7 @@ public class AbstractRuleTest { DummyNode n = new DummyNode(1); n.testingOnlySetBeginColumn(5); n.testingOnlySetBeginLine(5); - RuleViolation rv = new ParametricRuleViolation(r, ctx, n, "specificdescription"); + RuleViolation rv = new ParametricRuleViolation<>(r, ctx, n, "specificdescription"); ctx.getReport().addRuleViolation(rv); assertTrue(ctx.getReport().isEmpty()); } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetTest.java index 3d47494e86..b0cdbb5fa6 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetTest.java @@ -530,7 +530,7 @@ public class RuleSetTest { assertTrue("Report should have processing errors", context.getReport().hasErrors()); List errors = CollectionUtil.toList(context.getReport().errors()); assertEquals("Errors expected", 1, errors.size()); - assertEquals("Wrong error message", "Test exception while applying rule", errors.get(0).getMsg()); + assertEquals("Wrong error message", "RuntimeException: Test exception while applying rule", errors.get(0).getMsg()); assertTrue("Should be a RuntimeException", errors.get(0).getError() instanceof RuntimeException); } @@ -577,7 +577,7 @@ public class RuleSetTest { assertTrue("Report should have processing errors", context.getReport().hasErrors()); List errors = CollectionUtil.toList(context.getReport().errors()); assertEquals("Errors expected", 1, errors.size()); - assertEquals("Wrong error message", "Test exception while applying rule", errors.get(0).getMsg()); + assertEquals("Wrong error message", "RuntimeException: Test exception while applying rule", errors.get(0).getMsg()); assertTrue("Should be a RuntimeException", errors.get(0).getError() instanceof RuntimeException); assertEquals("There should be a violation", 1, context.getReport().size()); @@ -617,7 +617,7 @@ public class RuleSetTest { assertTrue("Report should have processing errors", context.getReport().hasErrors()); List errors = CollectionUtil.toList(context.getReport().errors()); assertEquals("Errors expected", 1, errors.size()); - assertEquals("Wrong error message", "Test exception while applying rule", errors.get(0).getMsg()); + assertEquals("Wrong error message", "RuntimeException: Test exception while applying rule", errors.get(0).getMsg()); assertTrue("Should be a RuntimeException", errors.get(0).getError() instanceof RuntimeException); assertEquals("There should be a violation", 1, context.getReport().size()); diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/cache/FileAnalysisCacheTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/cache/FileAnalysisCacheTest.java index 50bc478d29..41837fba91 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/cache/FileAnalysisCacheTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/cache/FileAnalysisCacheTest.java @@ -16,6 +16,7 @@ import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Collections; @@ -254,7 +255,51 @@ public class FileAnalysisCacheTest { assertFalse("Cache believes cache is up to date when a classpath file changed", reloadedCache.isUpToDate(sourceFile)); } - + + @Test + public void testWildcardClasspath() throws MalformedURLException, IOException { + final RuleSets rs = mock(RuleSets.class); + final ClassLoader cl = mock(ClassLoader.class); + setupCacheWithFiles(newCacheFile, rs, cl, sourceFile); + + // Prepare two jar files + final File classpathJar1 = tempFolder.newFile("mylib1.jar"); + Files.write(classpathJar1.toPath(), "content of mylib1.jar".getBytes(StandardCharsets.UTF_8)); + final File classpathJar2 = tempFolder.newFile("mylib2.jar"); + Files.write(classpathJar2.toPath(), "content of mylib2.jar".getBytes(StandardCharsets.UTF_8)); + + System.setProperty("java.class.path", System.getProperty("java.class.path") + File.pathSeparator + tempFolder.getRoot().getAbsolutePath() + "/*"); + + final FileAnalysisCache reloadedCache = new FileAnalysisCache(newCacheFile); + reloadedCache.checkValidity(rs, cl); + assertFalse("Cache believes cache is up to date when the classpath changed", + reloadedCache.isUpToDate(sourceFile)); + } + + @Test + public void testWildcardClasspathContentsChangeInvalidatesCache() throws MalformedURLException, IOException { + final RuleSets rs = mock(RuleSets.class); + final ClassLoader cl = mock(ClassLoader.class); + + // Prepare two jar files + final File classpathJar1 = tempFolder.newFile("mylib1.jar"); + Files.write(classpathJar1.toPath(), "content of mylib1.jar".getBytes(StandardCharsets.UTF_8)); + final File classpathJar2 = tempFolder.newFile("mylib2.jar"); + Files.write(classpathJar2.toPath(), "content of mylib2.jar".getBytes(StandardCharsets.UTF_8)); + + System.setProperty("java.class.path", System.getProperty("java.class.path") + File.pathSeparator + tempFolder.getRoot().getAbsolutePath() + "/*"); + + setupCacheWithFiles(newCacheFile, rs, cl, sourceFile); + + // Change one file's contents + Files.write(Paths.get(classpathJar2.getAbsolutePath()), "some other text".getBytes(StandardCharsets.UTF_8)); + + final FileAnalysisCache reloadedCache = new FileAnalysisCache(newCacheFile); + reloadedCache.checkValidity(rs, cl); + assertFalse("Cache believes cache is up to date when the classpath changed", + reloadedCache.isUpToDate(sourceFile)); + } + @Test public void testUnknownFileIsNotUpToDate() throws IOException { final FileAnalysisCache cache = new FileAnalysisCache(newCacheFile); diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/CharacterPropertyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/CharacterPropertyTest.java index 06c2ff574c..d0a50c7e7b 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/CharacterPropertyTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/CharacterPropertyTest.java @@ -15,6 +15,7 @@ import org.junit.Test; * * @author Brian Remedios */ +@Deprecated public class CharacterPropertyTest extends AbstractPropertyDescriptorTester { private static final char DELIMITER = '|'; diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/DoublePropertyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/DoublePropertyTest.java index bc940ecf9c..9b24dc2d0b 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/DoublePropertyTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/DoublePropertyTest.java @@ -14,6 +14,7 @@ import java.util.List; * * @author Brian Remedios */ +@Deprecated public class DoublePropertyTest extends AbstractNumericPropertyDescriptorTester { private static final double MIN = -10.0; diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/IntegerPropertyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/IntegerPropertyTest.java index 746c7e242a..437bcfc422 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/IntegerPropertyTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/IntegerPropertyTest.java @@ -15,6 +15,7 @@ import java.util.List; * * @author Brian Remedios */ +@Deprecated public class IntegerPropertyTest extends AbstractNumericPropertyDescriptorTester { private static final int MIN = 1; diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/LongPropertyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/LongPropertyTest.java index a35ce908db..878ec3f4c8 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/LongPropertyTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/LongPropertyTest.java @@ -10,6 +10,7 @@ import java.util.List; /** * @author Clément Fournier */ +@Deprecated public class LongPropertyTest extends AbstractNumericPropertyDescriptorTester { private static final long MIN = 10L; diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/NonRuleWithAllPropertyTypes.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/NonRuleWithAllPropertyTypes.java deleted file mode 100644 index cc93b240e3..0000000000 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/NonRuleWithAllPropertyTypes.java +++ /dev/null @@ -1,115 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.properties; - -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import net.sourceforge.pmd.RuleContext; -import net.sourceforge.pmd.lang.ast.Node; -import net.sourceforge.pmd.lang.rule.AbstractRule; -import net.sourceforge.pmd.util.ClassUtil; - -/** - * A non-functional rule containing all property types. Used for testing UIs. - * - * Steps required to use with Eclipse Plugin: - * - * update your chosen ruleset xml file to include this 'rule' compile new PMD - * jars copy both the pmd5.0.jar and pmd-test-5.0.jar to the eclipse-plugin/lib - * directory update the /manifest.mf file to ensure it includes the - * pmd-test-5.0.jar - * - * @author Brian Remedios - */ -public class NonRuleWithAllPropertyTypes extends AbstractRule { - - // descriptors are public to enable us to write external tests - public static final StringProperty SINGLE_STR = new StringProperty("singleStr", "String value", "hello world", 3.0f); - public static final StringMultiProperty MULTI_STR = new StringMultiProperty("multiStr", "Multiple string values", - new String[] {"hello", "world"}, 5.0f, '|'); - public static final IntegerProperty SINGLE_INT = IntegerProperty.named("singleInt").desc("Single integer value").range(1, 10).defaultValue(8).uiOrder(3.0f).build(); - public static final IntegerMultiProperty MULTI_INT = new IntegerMultiProperty("multiInt", "Multiple integer values", - 0, 10, new Integer[] {1, 2, 3, 4}, 5.0f); - public static final LongProperty SINGLE_LONG = new LongProperty("singleLong", "Single long value", 1L, 10L, 8L, - 3.0f); - public static final LongMultiProperty MULTI_LONG = new LongMultiProperty("multiLong", "Multiple long values", 0L, - 10L, new Long[] {1L, 2L, 3L, 4L}, 5.0f); - public static final BooleanProperty SINGLE_BOOL = new BooleanProperty("singleBool", "Single boolean value", true, - 6.0f); - public static final BooleanMultiProperty MULTI_BOOL = new BooleanMultiProperty("multiBool", - "Multiple boolean values", new Boolean[] {true, false}, 5.0f); - public static final CharacterProperty SINGLE_CHAR = new CharacterProperty("singleChar", "Single character", 'a', - 5.0f); - public static final CharacterMultiProperty MULTI_CHAR = new CharacterMultiProperty("multiChar", - "Multiple characters", new Character[] {'a', 'e', 'i', 'o', 'u'}, 6.0f, '|'); - public static final FloatProperty SINGLE_FLOAT = new FloatProperty("singleFloat", "Single float value", .9f, 10f, .9f, - 5.0f); - public static final FloatMultiProperty MULTI_FLOAT = new FloatMultiProperty("multiFloat", "Multiple float values", - 0f, 5f, new Float[] {1f, 2f, 3f}, 6.0f); - public static final TypeProperty SINGLE_TYPE = new TypeProperty("singleType", "Single type", String.class, - new String[] {"java.lang"}, 5.0f); - public static final TypeMultiProperty MULTI_TYPE = new TypeMultiProperty("multiType", "Multiple types", - Arrays.asList(Integer.class, Object.class), new String[] {"java.lang"}, 6.0f); - - private static final Map ENUM_MAPPINGS; - - static { - Map tmp = new HashMap<>(); - tmp.put("String", String.class); - tmp.put("Object", Object.class); - ENUM_MAPPINGS = Collections.unmodifiableMap(tmp); - } - - - public static final EnumeratedProperty ENUM_TYPE = new EnumeratedProperty<>("enumType", "Enumerated choices", ENUM_MAPPINGS, Object.class, Class.class, 5.0f); - - - public static final EnumeratedMultiProperty MULTI_ENUM_TYPE = new EnumeratedMultiProperty<>("multiEnumType", "Multiple enumerated choices", ENUM_MAPPINGS, - Arrays.asList(String.class, Object.class), Class.class, 5.0f); - - private static final Method STRING_LENGTH = ClassUtil.methodFor(String.class, "length", ClassUtil.EMPTY_CLASS_ARRAY); - - public static final MethodProperty SINGLE_METHOD = new MethodProperty("singleMethod", "Single method", - STRING_LENGTH, new String[] {"java.lang"}, 5.0f); - - private static final Method STRING_TO_LOWER_CASE = ClassUtil.methodFor(String.class, "toLowerCase", - ClassUtil.EMPTY_CLASS_ARRAY); - - public static final MethodMultiProperty MULTI_METHOD = new MethodMultiProperty("multiMethod", "Multiple methods", - new Method[] {STRING_LENGTH, STRING_TO_LOWER_CASE}, new String[] {"java.lang"}, 6.0f); - - - public NonRuleWithAllPropertyTypes() { - super(); - definePropertyDescriptor(SINGLE_STR); - definePropertyDescriptor(MULTI_STR); - definePropertyDescriptor(SINGLE_INT); - definePropertyDescriptor(MULTI_INT); - definePropertyDescriptor(SINGLE_LONG); - definePropertyDescriptor(MULTI_LONG); - definePropertyDescriptor(SINGLE_BOOL); - definePropertyDescriptor(MULTI_BOOL); - definePropertyDescriptor(SINGLE_CHAR); - definePropertyDescriptor(MULTI_CHAR); - definePropertyDescriptor(SINGLE_FLOAT); - definePropertyDescriptor(MULTI_FLOAT); - definePropertyDescriptor(SINGLE_TYPE); - definePropertyDescriptor(MULTI_TYPE); - definePropertyDescriptor(ENUM_TYPE); - definePropertyDescriptor(SINGLE_METHOD); - definePropertyDescriptor(MULTI_METHOD); - definePropertyDescriptor(MULTI_ENUM_TYPE); - } - - - @Override - public void apply(List nodes, RuleContext ctx) { - } -} diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/PropertyAccessorTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/PropertyAccessorTest.java deleted file mode 100644 index 624a27f926..0000000000 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/PropertyAccessorTest.java +++ /dev/null @@ -1,90 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.properties; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertSame; - -import java.util.Arrays; - -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; - -import net.sourceforge.pmd.Rule; -import net.sourceforge.pmd.cpd.ReportException; -import net.sourceforge.pmd.util.NumericConstants; - -/** - * @author Brian Remedios - */ -public class PropertyAccessorTest { - - private Rule rule; - - - @Before - public void setUpSingleRule() { - rule = new NonRuleWithAllPropertyTypes(); - } - - - @Test - public void testIntegers() { - rule.setProperty(NonRuleWithAllPropertyTypes.SINGLE_INT, NumericConstants.ZERO); - assertSame(rule.getProperty(NonRuleWithAllPropertyTypes.SINGLE_INT), 0); - - rule.setProperty(NonRuleWithAllPropertyTypes.MULTI_INT, - Arrays.asList(NumericConstants.ZERO, NumericConstants.ONE)); - assertEquals(rule.getProperty(NonRuleWithAllPropertyTypes.MULTI_INT), Arrays.asList(0, 1)); - } - - - @Test - public void testBooleans() { - - rule.setProperty(NonRuleWithAllPropertyTypes.SINGLE_BOOL, Boolean.FALSE); - assertFalse(rule.getProperty(NonRuleWithAllPropertyTypes.SINGLE_BOOL)); - - rule.setProperty(NonRuleWithAllPropertyTypes.MULTI_BOOL, Arrays.asList(Boolean.TRUE, Boolean.FALSE)); - assertEquals(rule.getProperty(NonRuleWithAllPropertyTypes.MULTI_BOOL), Arrays.asList(true, false)); - } - - - @Ignore - @Test - public void testFloats() throws ReportException { - /* - * rule.setProperty("singleFloat", new Float(0)); - * assertTrue(rule.getFloatProperty("singleFloat") == 0f); - * - * rule.setProperties("multiBool", new Boolean[] {Boolean.TRUE, - * Boolean.FALSE}); - * assertTrue(areEqual(rule.getBooleanProperties("multiBool"), new - * boolean[]{true, false})); - * - * boolean exceptionOccurred = false; try { - * rule.setProperties("singleBool", new Boolean[] {Boolean.TRUE, - * Boolean.FALSE}); } catch (Exception ex) { exceptionOccurred = true; } - * assertTrue(exceptionOccurred); - * - * exceptionOccurred = false; try { rule.setProperty("multiBool", - * Boolean.TRUE); } catch (Exception ex) { exceptionOccurred = true; } - * assertTrue(exceptionOccurred); - */ - } - - - @Test - public void testStrings() { - rule.setProperty(NonRuleWithAllPropertyTypes.SINGLE_STR, "brian"); - assertEquals(rule.getProperty(NonRuleWithAllPropertyTypes.SINGLE_STR), "brian"); - - rule.setProperty(NonRuleWithAllPropertyTypes.MULTI_STR, "hello", "world"); - assertEquals(rule.getProperty(NonRuleWithAllPropertyTypes.MULTI_STR), - Arrays.asList("hello", "world")); - } -} diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/PropertyDescriptorTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/PropertyDescriptorTest.java index 6171832a29..8fa10cd46e 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/PropertyDescriptorTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/PropertyDescriptorTest.java @@ -11,8 +11,14 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; import org.apache.commons.lang3.StringUtils; import org.hamcrest.Matcher; @@ -85,15 +91,15 @@ public class PropertyDescriptorTest { public void testDefaultValueConstraintViolationCausesFailure() { PropertyConstraint constraint = inRange(1, 10); - thrown.expect(IllegalStateException.class); + thrown.expect(IllegalArgumentException.class); thrown.expectMessage(allOf(containsIgnoreCase("Constraint violat"/*-ed or -ion*/), containsIgnoreCase(constraint.getConstraintDescription()))); - PropertyDescriptor intProperty = PropertyFactory.intProperty("fooProp") - .desc("hello") - .defaultValue(1000) - .require(constraint) - .build(); + PropertyFactory.intProperty("fooProp") + .desc("hello") + .defaultValue(1000) + .require(constraint) + .build(); } @@ -101,7 +107,7 @@ public class PropertyDescriptorTest { public void testDefaultValueConstraintViolationCausesFailureMulti() { PropertyConstraint constraint = inRange(1d, 10d); - thrown.expect(IllegalStateException.class); + thrown.expect(IllegalArgumentException.class); thrown.expectMessage(allOf(containsIgnoreCase("Constraint violat"/*-ed or -ion*/), containsIgnoreCase(constraint.getConstraintDescription()))); @@ -142,6 +148,190 @@ public class PropertyDescriptorTest { assertEquals("bazooli", descriptor.defaultValue()); } + @Test + public void testIntProperty() { + PropertyDescriptor descriptor = PropertyFactory.intProperty("intProp") + .desc("hello") + .defaultValue(1) + .build(); + assertEquals("intProp", descriptor.name()); + assertEquals("hello", descriptor.description()); + assertEquals(Integer.valueOf(1), descriptor.defaultValue()); + assertEquals(Integer.valueOf(5), descriptor.valueFrom("5")); + + PropertyDescriptor> listDescriptor = PropertyFactory.intListProperty("intListProp") + .desc("hello") + .defaultValues(1, 2) + .build(); + assertEquals("intListProp", listDescriptor.name()); + assertEquals("hello", listDescriptor.description()); + assertEquals(Arrays.asList(1, 2), listDescriptor.defaultValue()); + assertEquals(Arrays.asList(5, 7), listDescriptor.valueFrom("5,7")); + } + + @Test + public void testIntPropertyInvalidValue() { + PropertyDescriptor descriptor = PropertyFactory.intProperty("intProp") + .desc("hello") + .defaultValue(1) + .build(); + thrown.expect(NumberFormatException.class); + thrown.expectMessage("not a number"); + descriptor.valueFrom("not a number"); + } + + @Test + public void testDoubleProperty() { + PropertyDescriptor descriptor = PropertyFactory.doubleProperty("doubleProp") + .desc("hello") + .defaultValue(1.0) + .build(); + assertEquals("doubleProp", descriptor.name()); + assertEquals("hello", descriptor.description()); + assertEquals(Double.valueOf(1.0), descriptor.defaultValue()); + assertEquals(Double.valueOf(2.0), descriptor.valueFrom("2.0")); + + PropertyDescriptor> listDescriptor = PropertyFactory.doubleListProperty("doubleListProp") + .desc("hello") + .defaultValues(1.0, 2.0) + .build(); + assertEquals("doubleListProp", listDescriptor.name()); + assertEquals("hello", listDescriptor.description()); + assertEquals(Arrays.asList(1.0, 2.0), listDescriptor.defaultValue()); + assertEquals(Arrays.asList(2.0, 3.0), listDescriptor.valueFrom("2.0,3.0")); + } + + @Test + public void testDoublePropertyInvalidValue() { + PropertyDescriptor descriptor = PropertyFactory.doubleProperty("doubleProp") + .desc("hello") + .defaultValue(1.0) + .build(); + thrown.expect(NumberFormatException.class); + thrown.expectMessage("this is not a number"); + descriptor.valueFrom("this is not a number"); + } + + @Test + public void testStringProperty() { + PropertyDescriptor descriptor = PropertyFactory.stringProperty("stringProp") + .desc("hello") + .defaultValue("default value") + .build(); + assertEquals("stringProp", descriptor.name()); + assertEquals("hello", descriptor.description()); + assertEquals("default value", descriptor.defaultValue()); + assertEquals("foo", descriptor.valueFrom("foo")); + + PropertyDescriptor> listDescriptor = PropertyFactory.stringListProperty("stringListProp") + .desc("hello") + .defaultValues("v1", "v2") + .build(); + assertEquals("stringListProp", listDescriptor.name()); + assertEquals("hello", listDescriptor.description()); + assertEquals(Arrays.asList("v1", "v2"), listDescriptor.defaultValue()); + assertEquals(Arrays.asList("foo", "bar"), listDescriptor.valueFrom("foo|bar")); + } + + private enum SampleEnum { A, B, C } + + private static Map nameMap = new LinkedHashMap<>(); + + static { + nameMap.put("TEST_A", SampleEnum.A); + nameMap.put("TEST_B", SampleEnum.B); + nameMap.put("TEST_C", SampleEnum.C); + } + + @Test + public void testEnumProperty() { + PropertyDescriptor descriptor = PropertyFactory.enumProperty("enumProp", nameMap) + .desc("hello") + .defaultValue(SampleEnum.B) + .build(); + assertEquals("enumProp", descriptor.name()); + assertEquals("hello", descriptor.description()); + assertEquals(SampleEnum.B, descriptor.defaultValue()); + assertEquals(SampleEnum.C, descriptor.valueFrom("TEST_C")); + + PropertyDescriptor> listDescriptor = PropertyFactory.enumListProperty("enumListProp", nameMap) + .desc("hello") + .defaultValues(SampleEnum.A, SampleEnum.B) + .build(); + assertEquals("enumListProp", listDescriptor.name()); + assertEquals("hello", listDescriptor.description()); + assertEquals(Arrays.asList(SampleEnum.A, SampleEnum.B), listDescriptor.defaultValue()); + assertEquals(Arrays.asList(SampleEnum.B, SampleEnum.C), listDescriptor.valueFrom("TEST_B|TEST_C")); + } + + + @Test + public void testEnumPropertyNullValueFailsBuild() { + Map map = new HashMap<>(nameMap); + map.put("TEST_NULL", null); + + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage(containsIgnoreCase("null value")); + + PropertyFactory.enumProperty("enumProp", map); + } + + + @Test + public void testEnumListPropertyNullValueFailsBuild() { + Map map = new HashMap<>(nameMap); + map.put("TEST_NULL", null); + + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage(containsIgnoreCase("null value")); + + PropertyFactory.enumListProperty("enumProp", map); + } + + + @Test + public void testEnumPropertyInvalidValue() { + PropertyDescriptor descriptor = PropertyFactory.enumProperty("enumProp", nameMap) + .desc("hello") + .defaultValue(SampleEnum.B) + .build(); + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("Value was not in the set [TEST_A, TEST_B, TEST_C]"); + descriptor.valueFrom("InvalidEnumValue"); + } + + @Test + public void testRegexProperty() { + PropertyDescriptor descriptor = PropertyFactory.regexProperty("regexProp") + .desc("hello") + .defaultValue("^[A-Z].*$") + .build(); + assertEquals("regexProp", descriptor.name()); + assertEquals("hello", descriptor.description()); + assertEquals("^[A-Z].*$", descriptor.defaultValue().toString()); + assertEquals("[0-9]+", descriptor.valueFrom("[0-9]+").toString()); + } + + @Test + public void testRegexPropertyInvalidValue() { + PropertyDescriptor descriptor = PropertyFactory.regexProperty("regexProp") + .desc("hello") + .defaultValue("^[A-Z].*$") + .build(); + thrown.expect(PatternSyntaxException.class); + thrown.expectMessage("Unclosed character class"); + descriptor.valueFrom("[open class"); + } + + @Test + public void testRegexPropertyInvalidDefaultValue() { + thrown.expect(PatternSyntaxException.class); + thrown.expectMessage("Unclosed character class"); + PropertyDescriptor descriptor = PropertyFactory.regexProperty("regexProp") + .desc("hello") + .defaultValue("[open class") + .build(); + } private static Matcher containsIgnoreCase(final String substring) { return new SubstringMatcher(substring) { @@ -154,7 +344,7 @@ public class PropertyDescriptorTest { @Override protected String relationship() { - return "containing ignoring case"; + return "containing (ignoring case)"; } }; } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/RegexPropertyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/RegexPropertyTest.java index 5f760e8280..09d9442eff 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/RegexPropertyTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/RegexPropertyTest.java @@ -15,6 +15,7 @@ import java.util.regex.Pattern; * @author Clément Fournier * @since 6.2.0 */ +@Deprecated public class RegexPropertyTest extends AbstractPropertyDescriptorTester { public RegexPropertyTest() { super("Regex"); diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/SimpleEnumeratedPropertyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/SimpleEnumeratedPropertyTest.java index 6626ccf629..b890cc89ea 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/SimpleEnumeratedPropertyTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/SimpleEnumeratedPropertyTest.java @@ -24,6 +24,7 @@ import net.sourceforge.pmd.properties.SimpleEnumeratedPropertyTest.Foo; * * @author Brian Remedios */ +@Deprecated public class SimpleEnumeratedPropertyTest extends AbstractPropertyDescriptorTester { private static final String[] KEYS = {"bar", "na", "bee", "coo"}; diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/AbstractRendererTst.java b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/AbstractRendererTst.java index 36a0960155..9b6a8f30b6 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/AbstractRendererTst.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/AbstractRendererTst.java @@ -38,6 +38,10 @@ public abstract class AbstractRendererTst { return ""; } + public String getExpectedErrorWithoutMessage(ProcessingError error) { + return getExpectedError(error); + } + public String getExpectedError(ConfigurationError error) { return ""; } @@ -128,6 +132,15 @@ public abstract class AbstractRendererTst { assertEquals(filter(getExpectedError(err)), filter(actual)); } + @Test + public void testErrorWithoutMessage() throws Exception { + Report rep = new Report(); + Report.ProcessingError err = new Report.ProcessingError(new NullPointerException(), "file"); + rep.addError(err); + String actual = ReportTest.render(getRenderer(), rep); + assertEquals(filter(getExpectedErrorWithoutMessage(err)), filter(actual)); + } + @Test public void testConfigError() throws Exception { Report rep = new Report(); diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/PapariTextRendererTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/PapariTextRendererTest.java index 60c7055dca..360466a715 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/PapariTextRendererTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/PapariTextRendererTest.java @@ -56,7 +56,14 @@ public class PapariTextRendererTest extends AbstractRendererTst { @Override public String getExpectedError(ProcessingError error) { - return PMD.EOL + PMD.EOL + "Summary:" + PMD.EOL + PMD.EOL + " err: Error" + PMD.EOL + return PMD.EOL + PMD.EOL + "Summary:" + PMD.EOL + PMD.EOL + " err: RuntimeException: Error" + PMD.EOL + + error.getDetail() + PMD.EOL + PMD.EOL + + "* errors: 1" + PMD.EOL + "* warnings: 0" + PMD.EOL; + } + + @Override + public String getExpectedErrorWithoutMessage(ProcessingError error) { + return PMD.EOL + PMD.EOL + "Summary:" + PMD.EOL + PMD.EOL + " err: NullPointerException: null" + PMD.EOL + error.getDetail() + PMD.EOL + PMD.EOL + "* errors: 1" + PMD.EOL + "* warnings: 0" + PMD.EOL; } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/TextRendererTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/TextRendererTest.java index ac9ca9c9ce..4cdd2053c6 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/TextRendererTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/TextRendererTest.java @@ -32,7 +32,12 @@ public class TextRendererTest extends AbstractRendererTst { @Override public String getExpectedError(ProcessingError error) { - return "file\t-\tError" + PMD.EOL; + return "file\t-\tRuntimeException: Error" + PMD.EOL; + } + + @Override + public String getExpectedErrorWithoutMessage(ProcessingError error) { + return "file\t-\tNullPointerException: null" + PMD.EOL; } @Override diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/XMLRendererTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/XMLRendererTest.java index b8b0df7694..097702c194 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/XMLRendererTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/XMLRendererTest.java @@ -56,7 +56,13 @@ public class XMLRendererTest extends AbstractRendererTst { @Override public String getExpectedError(ProcessingError error) { - return getHeader() + "" + return getHeader() + "" + + PMD.EOL + "" + PMD.EOL + "" + PMD.EOL + "" + PMD.EOL; + } + + @Override + public String getExpectedErrorWithoutMessage(ProcessingError error) { + return getHeader() + "" + PMD.EOL + "" + PMD.EOL + "" + PMD.EOL + "" + PMD.EOL; } diff --git a/pmd-core/src/test/resources/net/sourceforge/pmd/renderers/yahtml/YAHTMLSampleClass1.html b/pmd-core/src/test/resources/net/sourceforge/pmd/renderers/yahtml/YAHTMLSampleClass1.html index 290e7104d9..8240e1ea8f 100644 --- a/pmd-core/src/test/resources/net/sourceforge/pmd/renderers/yahtml/YAHTMLSampleClass1.html +++ b/pmd-core/src/test/resources/net/sourceforge/pmd/renderers/yahtml/YAHTMLSampleClass1.html @@ -1,5 +1,7 @@ + + PMD - YAHTMLSampleClass1 diff --git a/pmd-core/src/test/resources/net/sourceforge/pmd/renderers/yahtml/YAHTMLSampleClass2.html b/pmd-core/src/test/resources/net/sourceforge/pmd/renderers/yahtml/YAHTMLSampleClass2.html index df94031c6a..762b3a7db7 100644 --- a/pmd-core/src/test/resources/net/sourceforge/pmd/renderers/yahtml/YAHTMLSampleClass2.html +++ b/pmd-core/src/test/resources/net/sourceforge/pmd/renderers/yahtml/YAHTMLSampleClass2.html @@ -1,5 +1,7 @@ + + PMD - YAHTMLSampleClass2 diff --git a/pmd-core/src/test/resources/net/sourceforge/pmd/renderers/yahtml/index.html b/pmd-core/src/test/resources/net/sourceforge/pmd/renderers/yahtml/index.html index 65b0d3a738..7b9dd8ddfe 100644 --- a/pmd-core/src/test/resources/net/sourceforge/pmd/renderers/yahtml/index.html +++ b/pmd-core/src/test/resources/net/sourceforge/pmd/renderers/yahtml/index.html @@ -1,5 +1,7 @@ + + PMD diff --git a/pmd-cpp/src/main/java/net/sourceforge/pmd/cpd/CPPTokenizer.java b/pmd-cpp/src/main/java/net/sourceforge/pmd/cpd/CPPTokenizer.java index b81450012b..09ab82cd1a 100644 --- a/pmd-cpp/src/main/java/net/sourceforge/pmd/cpd/CPPTokenizer.java +++ b/pmd-cpp/src/main/java/net/sourceforge/pmd/cpd/CPPTokenizer.java @@ -13,11 +13,9 @@ import java.util.Properties; import net.sourceforge.pmd.PMD; import net.sourceforge.pmd.cpd.token.JavaCCTokenFilter; import net.sourceforge.pmd.cpd.token.TokenFilter; -import net.sourceforge.pmd.lang.LanguageRegistry; -import net.sourceforge.pmd.lang.LanguageVersionHandler; import net.sourceforge.pmd.lang.ast.GenericToken; import net.sourceforge.pmd.lang.ast.TokenMgrError; -import net.sourceforge.pmd.lang.cpp.CppLanguageModule; +import net.sourceforge.pmd.lang.cpp.CppTokenManager; import net.sourceforge.pmd.util.IOUtil; /** @@ -55,11 +53,7 @@ public class CPPTokenizer implements Tokenizer { public void tokenize(SourceCode sourceCode, Tokens tokenEntries) { StringBuilder buffer = sourceCode.getCodeBuffer(); try (Reader reader = IOUtil.skipBOM(new StringReader(maybeSkipBlocks(buffer.toString())))) { - LanguageVersionHandler languageVersionHandler = LanguageRegistry.getLanguage(CppLanguageModule.NAME) - .getDefaultVersion().getLanguageVersionHandler(); - final TokenFilter tokenFilter = new JavaCCTokenFilter( - languageVersionHandler.getParser(languageVersionHandler.getDefaultParserOptions()) - .getTokenManager(sourceCode.getFileName(), reader)); + final TokenFilter tokenFilter = new JavaCCTokenFilter(new CppTokenManager(reader)); GenericToken currentToken = tokenFilter.getNextToken(); while (currentToken != null) { diff --git a/pmd-cpp/src/main/java/net/sourceforge/pmd/lang/cpp/CppHandler.java b/pmd-cpp/src/main/java/net/sourceforge/pmd/lang/cpp/CppHandler.java index 6565592a18..657ef70f00 100644 --- a/pmd-cpp/src/main/java/net/sourceforge/pmd/lang/cpp/CppHandler.java +++ b/pmd-cpp/src/main/java/net/sourceforge/pmd/lang/cpp/CppHandler.java @@ -10,7 +10,9 @@ import net.sourceforge.pmd.lang.ParserOptions; /** * Implementation of LanguageVersionHandler for the C++ Language. + * @deprecated There is no full PMD support for c++. */ +@Deprecated public class CppHandler extends AbstractCpdLanguageVersionHandler { @Override diff --git a/pmd-cpp/src/main/java/net/sourceforge/pmd/lang/cpp/CppLanguageModule.java b/pmd-cpp/src/main/java/net/sourceforge/pmd/lang/cpp/CppLanguageModule.java index ef81858c60..6cd9a34eb5 100644 --- a/pmd-cpp/src/main/java/net/sourceforge/pmd/lang/cpp/CppLanguageModule.java +++ b/pmd-cpp/src/main/java/net/sourceforge/pmd/lang/cpp/CppLanguageModule.java @@ -8,7 +8,10 @@ import net.sourceforge.pmd.lang.BaseLanguageModule; /** * Implementation of the C/C++ Language Module. + * + * @deprecated There is no full PMD support for c++. */ +@Deprecated public class CppLanguageModule extends BaseLanguageModule { /** The name, that can be used to display the language in UI. */ diff --git a/pmd-cpp/src/main/java/net/sourceforge/pmd/lang/cpp/CppParser.java b/pmd-cpp/src/main/java/net/sourceforge/pmd/lang/cpp/CppParser.java index 27a8435144..2e28ff971b 100644 --- a/pmd-cpp/src/main/java/net/sourceforge/pmd/lang/cpp/CppParser.java +++ b/pmd-cpp/src/main/java/net/sourceforge/pmd/lang/cpp/CppParser.java @@ -16,7 +16,10 @@ import net.sourceforge.pmd.lang.ast.ParseException; /** * Adapter for the C++ Parser. + * + * @deprecated There is no full PMD support for c++. */ +@Deprecated public class CppParser extends AbstractParser { /** diff --git a/pmd-cpp/src/test/java/net/sourceforge/pmd/LanguageVersionTest.java b/pmd-cpp/src/test/java/net/sourceforge/pmd/LanguageVersionTest.java deleted file mode 100644 index 532789523b..0000000000 --- a/pmd-cpp/src/test/java/net/sourceforge/pmd/LanguageVersionTest.java +++ /dev/null @@ -1,33 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd; - -import java.util.Arrays; -import java.util.Collection; - -import org.junit.runners.Parameterized.Parameters; - -import net.sourceforge.pmd.lang.LanguageRegistry; -import net.sourceforge.pmd.lang.LanguageVersion; -import net.sourceforge.pmd.lang.cpp.CppLanguageModule; - -public class LanguageVersionTest extends AbstractLanguageVersionTest { - - public LanguageVersionTest(String name, String terseName, String version, LanguageVersion expected) { - super(name, terseName, version, expected); - } - - @Parameters - public static Collection data() { - return Arrays.asList(new Object[][] { - { - CppLanguageModule.NAME, - CppLanguageModule.TERSE_NAME, - "", - LanguageRegistry.getLanguage(CppLanguageModule.NAME).getDefaultVersion(), - }, - }); - } -} diff --git a/pmd-cs/src/main/java/net/sourceforge/pmd/lang/cs/CsLanguageModule.java b/pmd-cs/src/main/java/net/sourceforge/pmd/lang/cs/CsLanguageModule.java index 238014b832..c90fd57029 100644 --- a/pmd-cs/src/main/java/net/sourceforge/pmd/lang/cs/CsLanguageModule.java +++ b/pmd-cs/src/main/java/net/sourceforge/pmd/lang/cs/CsLanguageModule.java @@ -8,7 +8,10 @@ import net.sourceforge.pmd.lang.BaseLanguageModule; /** * Language Module for C# + * + * @deprecated There is no full PMD support for c#. */ +@Deprecated public class CsLanguageModule extends BaseLanguageModule { /** The name. */ diff --git a/pmd-fortran/src/main/java/net/sourceforge/pmd/lang/fortran/FortranLanguageModule.java b/pmd-fortran/src/main/java/net/sourceforge/pmd/lang/fortran/FortranLanguageModule.java index 510ed045a4..48ac68a69f 100644 --- a/pmd-fortran/src/main/java/net/sourceforge/pmd/lang/fortran/FortranLanguageModule.java +++ b/pmd-fortran/src/main/java/net/sourceforge/pmd/lang/fortran/FortranLanguageModule.java @@ -8,7 +8,10 @@ import net.sourceforge.pmd.lang.BaseLanguageModule; /** * Implementation for the Fortran Language Module + * + * @deprecated There is no full PMD support for fortran. */ +@Deprecated public class FortranLanguageModule extends BaseLanguageModule { /** The name */ diff --git a/pmd-fortran/src/test/java/net/sourceforge/pmd/LanguageVersionTest.java b/pmd-fortran/src/test/java/net/sourceforge/pmd/LanguageVersionTest.java deleted file mode 100644 index e4cb577784..0000000000 --- a/pmd-fortran/src/test/java/net/sourceforge/pmd/LanguageVersionTest.java +++ /dev/null @@ -1,33 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd; - -import java.util.Arrays; -import java.util.Collection; - -import org.junit.runners.Parameterized.Parameters; - -import net.sourceforge.pmd.lang.LanguageRegistry; -import net.sourceforge.pmd.lang.LanguageVersion; -import net.sourceforge.pmd.lang.fortran.FortranLanguageModule; - -public class LanguageVersionTest extends AbstractLanguageVersionTest { - - public LanguageVersionTest(String name, String terseName, String version, LanguageVersion expected) { - super(name, terseName, version, expected); - } - - @Parameters - public static Collection data() { - return Arrays.asList(new Object[][] { - { - FortranLanguageModule.NAME, - FortranLanguageModule.TERSE_NAME, - "", - LanguageRegistry.getLanguage(FortranLanguageModule.NAME).getDefaultVersion(), - }, - }); - } -} diff --git a/pmd-groovy/src/main/java/net/sourceforge/pmd/lang/groovy/GroovyLanguageModule.java b/pmd-groovy/src/main/java/net/sourceforge/pmd/lang/groovy/GroovyLanguageModule.java index 95ddc5870b..02149c8db5 100644 --- a/pmd-groovy/src/main/java/net/sourceforge/pmd/lang/groovy/GroovyLanguageModule.java +++ b/pmd-groovy/src/main/java/net/sourceforge/pmd/lang/groovy/GroovyLanguageModule.java @@ -8,7 +8,10 @@ import net.sourceforge.pmd.lang.BaseLanguageModule; /** * Language Module for Groovy + * + * @deprecated There is no full PMD support for Groovy. */ +@Deprecated public class GroovyLanguageModule extends BaseLanguageModule { /** The name. */ diff --git a/pmd-groovy/src/test/java/net/sourceforge/pmd/LanguageVersionTest.java b/pmd-groovy/src/test/java/net/sourceforge/pmd/LanguageVersionTest.java deleted file mode 100644 index 48b1486ac4..0000000000 --- a/pmd-groovy/src/test/java/net/sourceforge/pmd/LanguageVersionTest.java +++ /dev/null @@ -1,33 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd; - -import java.util.Arrays; -import java.util.Collection; - -import org.junit.runners.Parameterized.Parameters; - -import net.sourceforge.pmd.lang.LanguageRegistry; -import net.sourceforge.pmd.lang.LanguageVersion; -import net.sourceforge.pmd.lang.groovy.GroovyLanguageModule; - -public class LanguageVersionTest extends AbstractLanguageVersionTest { - - public LanguageVersionTest(String name, String terseName, String version, LanguageVersion expected) { - super(name, terseName, version, expected); - } - - @Parameters - public static Collection data() { - return Arrays.asList(new Object[][] { - { - GroovyLanguageModule.NAME, - GroovyLanguageModule.TERSE_NAME, - "", - LanguageRegistry.getLanguage(GroovyLanguageModule.NAME).getDefaultVersion(), - }, - }); - } -} diff --git a/pmd-java/pom.xml b/pmd-java/pom.xml index 6f083e3b69..3d06ae4075 100644 --- a/pmd-java/pom.xml +++ b/pmd-java/pom.xml @@ -64,23 +64,6 @@ run - - pmd-clean - clean - - - PMD specific tasks: cleaning generated markdown - - - - - - - - - run - - diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTDoStatement.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTDoStatement.java index 6a0f3d114b..8d44fcf3bd 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTDoStatement.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTDoStatement.java @@ -5,18 +5,53 @@ package net.sourceforge.pmd.lang.java.ast; +import net.sourceforge.pmd.annotation.InternalApi; + + +/** + * Represents a {@code do ... while} statement. + * + * + *

+ *
+ * DoStatement ::= "do" {@linkplain ASTStatement Statement} "while" "(" {@linkplain ASTExpression Expression} ")" ";"
+ *
+ * 
+ */ public class ASTDoStatement extends AbstractJavaNode { + + @InternalApi + @Deprecated public ASTDoStatement(int id) { super(id); } + + @InternalApi + @Deprecated public ASTDoStatement(JavaParser p, int id) { super(p, id); } + /** - * Accept the visitor. * + * Returns the node that represents the guard of this loop. + * This may be any expression of type boolean. */ + public ASTExpression getGuardExpressionNode() { + return (ASTExpression) jjtGetChild(1); + } + + + /** + * Returns the statement that will be run while the guard + * evaluates to true. + */ + public ASTStatement getBody() { + return (ASTStatement) jjtGetChild(0); + } + + @Override public Object jjtAccept(JavaParserVisitor visitor, Object data) { return visitor.visit(this, data); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTForStatement.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTForStatement.java index 6da777ad99..6d7d58d615 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTForStatement.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTForStatement.java @@ -14,7 +14,6 @@ package net.sourceforge.pmd.lang.java.ast; * | "for" "(" {@linkplain ASTForInit ForInit}? ";" {@linkplain ASTExpression Expression}? ";" {@linkplain ASTForUpdate ForUpdate}? ")" {@linkplain ASTStatement Statement} * * - * */ // TODO this should be split into two different nodes, otherwise // we can't enrich the API without returning null half the time @@ -23,10 +22,12 @@ public class ASTForStatement extends AbstractJavaNode { super(id); } + public ASTForStatement(JavaParser p, int id) { super(p, id); } + @Override public Object jjtAccept(JavaParserVisitor visitor, Object data) { return visitor.visit(this, data); @@ -39,6 +40,21 @@ public class ASTForStatement extends AbstractJavaNode { } + /** + * Returns the node that represents the guard of this loop. + * This may be any expression of type boolean. + * + *

If this node represents a foreach loop, or if there is + * no specified guard, then returns null. + */ + public ASTExpression getGuardExpressionNode() { + if (isForeach()) { + return null; + } + return getFirstChildOfType(ASTExpression.class); + } + + /** * Returns true if this node represents a foreach loop. */ diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTForUpdate.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTForUpdate.java index 783789cbc9..0a1e0d6878 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTForUpdate.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTForUpdate.java @@ -5,15 +5,34 @@ package net.sourceforge.pmd.lang.java.ast; +import net.sourceforge.pmd.annotation.InternalApi; + + +/** + * Update clause of a {@linkplain ASTForStatement for statement}. + * + *

+ *
+ * ForUpdate ::= {@linkplain ASTStatementExpressionList StatementExpressionList}
+ *
+ * 
+ */ public class ASTForUpdate extends AbstractJavaNode { + + @InternalApi + @Deprecated public ASTForUpdate(int id) { super(id); } + + @InternalApi + @Deprecated public ASTForUpdate(JavaParser p, int id) { super(p, id); } + /** * Accept the visitor. * */ diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTIfStatement.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTIfStatement.java index e719194546..56cadb71f6 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTIfStatement.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTIfStatement.java @@ -5,29 +5,79 @@ package net.sourceforge.pmd.lang.java.ast; +import net.sourceforge.pmd.annotation.InternalApi; + + +/** + * Represents an {@code if} statement, possibly with an {@code else} statement. + * + *
+ *
+ * IfStatement ::= "if" "(" {@linkplain ASTExpression Expression} ")" {@linkplain ASTStatement Statement}
+ *                 ( "else" {@linkplain ASTStatement Statement} )?
+ *
+ * 
+ */ public class ASTIfStatement extends AbstractJavaNode { private boolean hasElse; + + @InternalApi + @Deprecated public ASTIfStatement(int id) { super(id); } + + @InternalApi + @Deprecated public ASTIfStatement(JavaParser p, int id) { super(p, id); } + + @InternalApi + @Deprecated public void setHasElse() { this.hasElse = true; } + + /** + * Returns true if this statement has an {@code else} clause. + */ public boolean hasElse() { return this.hasElse; } + /** - * Accept the visitor. * + * Returns the node that represents the guard of this conditional. + * This may be any expression of type boolean. */ + public ASTExpression getGuardExpressionNode() { + return (ASTExpression) jjtGetChild(0); + } + + + /** + * Returns the statement that will be run if the guard evaluates + * to true. + */ + public ASTStatement getThenBranch() { + return (ASTStatement) jjtGetChild(1); + } + + + /** + * Returns the statement of the {@code else} clause, if any. + */ + public ASTStatement getElseBranch() { + return hasElse() ? (ASTStatement) jjtGetChild(2) : null; + } + + @Override public Object jjtAccept(JavaParserVisitor visitor, Object data) { return visitor.visit(this, data); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchLabel.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchLabel.java index 9ca93300db..6483ed2abe 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchLabel.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchLabel.java @@ -5,27 +5,41 @@ package net.sourceforge.pmd.lang.java.ast; +import net.sourceforge.pmd.annotation.InternalApi; + + /** * Represents either a {@code case} or {@code default} label inside * a {@linkplain ASTSwitchStatement switch statement}. * *
+ *
  * SwitchLabel ::=  "case" {@linkplain ASTExpression Expression} ":"
  *                | "default" ":"
+ *
  * 
*/ public class ASTSwitchLabel extends AbstractJavaNode { private boolean isDefault; + + @InternalApi + @Deprecated public ASTSwitchLabel(int id) { super(id); } + + @InternalApi + @Deprecated public ASTSwitchLabel(JavaParser p, int id) { super(p, id); } + + @InternalApi + @Deprecated public void setDefault() { isDefault = true; } @@ -34,9 +48,6 @@ public class ASTSwitchLabel extends AbstractJavaNode { return isDefault; } - /** - * Accept the visitor. * - */ @Override public Object jjtAccept(JavaParserVisitor visitor, Object data) { return visitor.visit(this, data); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTWhileStatement.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTWhileStatement.java index 95f373f6b7..36d9c127ee 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTWhileStatement.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTWhileStatement.java @@ -5,18 +5,52 @@ package net.sourceforge.pmd.lang.java.ast; +import net.sourceforge.pmd.annotation.InternalApi; + + +/** + * Represents a {@code while} statement. + * + *
+ *
+ * WhileStatement ::= "while" "(" {@linkplain ASTExpression Expression} ")" {@linkplain ASTStatement Statement}
+ *
+ * 
+ */ public class ASTWhileStatement extends AbstractJavaNode { + + @InternalApi + @Deprecated public ASTWhileStatement(int id) { super(id); } + + @InternalApi + @Deprecated public ASTWhileStatement(JavaParser p, int id) { super(p, id); } + /** - * Accept the visitor. * + * Returns the node that represents the guard of this loop. + * This may be any expression of type boolean. */ + public ASTExpression getGuardExpressionNode() { + return (ASTExpression) jjtGetChild(0); + } + + + /** + * Returns the statement that will be run while the guard + * evaluates to true. + */ + public ASTStatement getBody() { + return (ASTStatement) jjtGetChild(1); + } + + @Override public Object jjtAccept(JavaParserVisitor visitor, Object data) { return visitor.visit(this, data); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserControllessVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserControllessVisitor.java index bf91290688..1ef0a6a7e6 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserControllessVisitor.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserControllessVisitor.java @@ -13,6 +13,9 @@ package net.sourceforge.pmd.lang.java.ast; * * @see JavaParserDecoratedVisitor * @see JavaParserVisitorDecorator + * + * @deprecated Visitor decorators are deprecated because they lead to fragile code. */ +@Deprecated public interface JavaParserControllessVisitor extends JavaParserVisitor { } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserControllessVisitorAdapter.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserControllessVisitorAdapter.java index aec2b1e153..a0953ee098 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserControllessVisitorAdapter.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserControllessVisitorAdapter.java @@ -10,7 +10,10 @@ package net.sourceforge.pmd.lang.java.ast; * * @author Clément Fournier * @since 6.0.0 + * + * @deprecated Visitor decorators are deprecated because they lead to fragile code. */ +@Deprecated public class JavaParserControllessVisitorAdapter extends JavaParserVisitorAdapter implements JavaParserControllessVisitor { @Override diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserDecoratedVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserDecoratedVisitor.java index 0e55523479..d13a5e1ff8 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserDecoratedVisitor.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserDecoratedVisitor.java @@ -14,7 +14,10 @@ package net.sourceforge.pmd.lang.java.ast; * * @author Clément Fournier * @since 6.0.0 + * + * @deprecated Visitor decorators are deprecated because they lead to fragile code. */ +@Deprecated public class JavaParserDecoratedVisitor implements JavaParserVisitor { diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserVisitorDecorator.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserVisitorDecorator.java index 7451c09a30..d9968afdbf 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserVisitorDecorator.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserVisitorDecorator.java @@ -7,9 +7,12 @@ package net.sourceforge.pmd.lang.java.ast; /** * Decorates a control less visitor. This must be wrapped into a {@link JavaParserDecoratedVisitor} to work properly. * + * @deprecated Visitor decorators are deprecated because they lead to fragile code. + * * @author Clément Fournier * @since 6.0.0 */ +@Deprecated public class JavaParserVisitorDecorator implements JavaParserControllessVisitor { private JavaParserVisitor visitor; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/CycloMetric.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/CycloMetric.java index f6bff5ecd2..6096714ad8 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/CycloMetric.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/CycloMetric.java @@ -5,19 +5,14 @@ package net.sourceforge.pmd.lang.java.metrics.impl; import java.util.List; -import java.util.Set; import org.apache.commons.lang3.mutable.MutableInt; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.java.ast.ASTConditionalAndExpression; import net.sourceforge.pmd.lang.java.ast.ASTConditionalOrExpression; -import net.sourceforge.pmd.lang.java.ast.JavaNode; -import net.sourceforge.pmd.lang.java.ast.JavaParserDecoratedVisitor; import net.sourceforge.pmd.lang.java.ast.MethodLikeNode; -import net.sourceforge.pmd.lang.java.metrics.impl.visitors.CycloAssertAwareDecorator; -import net.sourceforge.pmd.lang.java.metrics.impl.visitors.CycloBaseVisitor; -import net.sourceforge.pmd.lang.java.metrics.impl.visitors.CycloPathAwareDecorator; +import net.sourceforge.pmd.lang.java.metrics.impl.internal.CycloVisitor; import net.sourceforge.pmd.lang.metrics.MetricOption; import net.sourceforge.pmd.lang.metrics.MetricOptions; @@ -35,25 +30,8 @@ public final class CycloMetric extends AbstractJavaOperationMetric { @Override - public double computeFor(final MethodLikeNode node, MetricOptions options) { - Set opts = options.getOptions(); - JavaParserDecoratedVisitor visitor = new JavaParserDecoratedVisitor(CycloBaseVisitor.INSTANCE) { // TODO decorators are unmaintainable, change that someday - // stops the visit when stumbling on a lambda or class decl - @Override - public Object visit(JavaNode localNode, Object data) { - return localNode.isFindBoundary() && !localNode.equals(node) ? data : super.visit(localNode, data); // TODO generalize that to other metrics - } - }; - - if (opts.contains(CycloOption.CONSIDER_ASSERT)) { - visitor.decorateWith(new CycloAssertAwareDecorator()); - } - - if (!opts.contains(CycloOption.IGNORE_BOOLEAN_PATHS)) { - visitor.decorateWith(new CycloPathAwareDecorator()); - } - - MutableInt cyclo = (MutableInt) node.jjtAccept(visitor, new MutableInt(1)); + public double computeFor(MethodLikeNode node, MetricOptions options) { + MutableInt cyclo = (MutableInt) node.jjtAccept(new CycloVisitor(options, node), new MutableInt(1)); return (double) cyclo.getValue(); } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/NcssMetric.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/NcssMetric.java index 99a904393f..5b852f943c 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/NcssMetric.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/NcssMetric.java @@ -4,15 +4,11 @@ package net.sourceforge.pmd.lang.java.metrics.impl; -import java.util.Set; - import org.apache.commons.lang3.mutable.MutableInt; import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; -import net.sourceforge.pmd.lang.java.ast.JavaParserDecoratedVisitor; import net.sourceforge.pmd.lang.java.ast.MethodLikeNode; -import net.sourceforge.pmd.lang.java.metrics.impl.visitors.NcssBaseVisitor; -import net.sourceforge.pmd.lang.java.metrics.impl.visitors.NcssCountImportsDecorator; +import net.sourceforge.pmd.lang.java.metrics.impl.internal.NcssVisitor; import net.sourceforge.pmd.lang.metrics.MetricOption; import net.sourceforge.pmd.lang.metrics.MetricOptions; @@ -54,17 +50,8 @@ public final class NcssMetric { @Override - public double computeFor(ASTAnyTypeDeclaration node, MetricOptions version) { - Set options = version.getOptions(); - JavaParserDecoratedVisitor visitor = new JavaParserDecoratedVisitor(NcssBaseVisitor.INSTANCE); - - if (options.contains(NcssOption.COUNT_IMPORTS)) { - visitor.decorateWith(new NcssCountImportsDecorator()); - } - - // decorate - - MutableInt ncss = (MutableInt) node.jjtAccept(visitor, new MutableInt(0)); + public double computeFor(ASTAnyTypeDeclaration node, MetricOptions options) { + MutableInt ncss = (MutableInt) node.jjtAccept(new NcssVisitor(options, node), new MutableInt(0)); return (double) ncss.getValue(); } @@ -79,15 +66,8 @@ public final class NcssMetric { @Override - public double computeFor(MethodLikeNode node, MetricOptions version) { - Set options = version.getOptions(); - JavaParserDecoratedVisitor visitor = new JavaParserDecoratedVisitor(NcssBaseVisitor.INSTANCE); - - if (options.contains(NcssOption.COUNT_IMPORTS)) { - visitor.decorateWith(new NcssCountImportsDecorator()); - } - - MutableInt ncss = (MutableInt) node.jjtAccept(visitor, new MutableInt(0)); + public double computeFor(MethodLikeNode node, MetricOptions options) { + MutableInt ncss = (MutableInt) node.jjtAccept(new NcssVisitor(options, node), new MutableInt(0)); return (double) ncss.getValue(); } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/internal/CycloVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/internal/CycloVisitor.java new file mode 100644 index 0000000000..a3a78083f2 --- /dev/null +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/internal/CycloVisitor.java @@ -0,0 +1,160 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.metrics.impl.internal; + +import org.apache.commons.lang3.mutable.MutableInt; + +import net.sourceforge.pmd.lang.java.ast.ASTAssertStatement; +import net.sourceforge.pmd.lang.java.ast.ASTBlockStatement; +import net.sourceforge.pmd.lang.java.ast.ASTCatchStatement; +import net.sourceforge.pmd.lang.java.ast.ASTConditionalExpression; +import net.sourceforge.pmd.lang.java.ast.ASTDoStatement; +import net.sourceforge.pmd.lang.java.ast.ASTForStatement; +import net.sourceforge.pmd.lang.java.ast.ASTIfStatement; +import net.sourceforge.pmd.lang.java.ast.ASTSwitchLabel; +import net.sourceforge.pmd.lang.java.ast.ASTSwitchStatement; +import net.sourceforge.pmd.lang.java.ast.ASTThrowStatement; +import net.sourceforge.pmd.lang.java.ast.ASTWhileStatement; +import net.sourceforge.pmd.lang.java.ast.JavaNode; +import net.sourceforge.pmd.lang.java.ast.JavaParserVisitorAdapter; +import net.sourceforge.pmd.lang.java.metrics.impl.CycloMetric; +import net.sourceforge.pmd.lang.java.metrics.impl.CycloMetric.CycloOption; +import net.sourceforge.pmd.lang.metrics.MetricOptions; + + +/** + * Visitor for the Cyclo metric. + * + * @author Clément Fournier + * @since 6.7.0 + */ +public class CycloVisitor extends JavaParserVisitorAdapter { + + + protected final boolean considerBooleanPaths; + protected final boolean considerAssert; + private final JavaNode topNode; + + + public CycloVisitor(MetricOptions options, JavaNode topNode) { + considerBooleanPaths = !options.getOptions().contains(CycloOption.IGNORE_BOOLEAN_PATHS); + considerAssert = options.getOptions().contains(CycloOption.CONSIDER_ASSERT); + this.topNode = topNode; + } + + + @Override + public final Object visit(JavaNode localNode, Object data) { + return localNode.isFindBoundary() && !localNode.equals(topNode) ? data : super.visit(localNode, data); + } + + + @Override + public Object visit(ASTSwitchStatement node, Object data) { + + if (considerBooleanPaths) { + ((MutableInt) data).add(CycloMetric.booleanExpressionComplexity(node.getTestedExpression())); + } + + for (ASTSwitchLabel label : node) { + if (label.isDefault()) { + // like for "else", default is not a decision point + continue; + } + + if (considerBooleanPaths) { + ((MutableInt) data).increment(); + } else if (node.jjtGetNumChildren() > 1 + label.jjtGetChildIndex() + && node.jjtGetChild(label.jjtGetChildIndex() + 1) instanceof ASTBlockStatement) { + // an empty label is only counted if we count boolean paths + ((MutableInt) data).increment(); + } + } + return super.visit(node, data); + } + + + @Override + public Object visit(ASTConditionalExpression node, Object data) { + ((MutableInt) data).increment(); + if (considerBooleanPaths) { + ((MutableInt) data).add(CycloMetric.booleanExpressionComplexity(node.getGuardExpressionNode())); + } + return super.visit(node, data); + } + + + @Override + public Object visit(ASTWhileStatement node, Object data) { + ((MutableInt) data).increment(); + if (considerBooleanPaths) { + ((MutableInt) data).add(CycloMetric.booleanExpressionComplexity(node.getGuardExpressionNode())); + } + return super.visit(node, data); + } + + + @Override + public Object visit(ASTIfStatement node, Object data) { + ((MutableInt) data).increment(); + if (considerBooleanPaths) { + ((MutableInt) data).add(CycloMetric.booleanExpressionComplexity(node.getGuardExpressionNode())); + } + + return super.visit(node, data); + } + + + @Override + public Object visit(ASTForStatement node, Object data) { + ((MutableInt) data).increment(); + + if (considerBooleanPaths && !node.isForeach()) { + ((MutableInt) data).add(CycloMetric.booleanExpressionComplexity(node.getGuardExpressionNode())); + } + + return super.visit(node, data); + } + + + @Override + public Object visit(ASTDoStatement node, Object data) { + ((MutableInt) data).increment(); + if (considerBooleanPaths) { + ((MutableInt) data).add(CycloMetric.booleanExpressionComplexity(node.getGuardExpressionNode())); + } + + return super.visit(node, data); + } + + + @Override + public Object visit(ASTCatchStatement node, Object data) { + ((MutableInt) data).increment(); + return super.visit(node, data); + } + + + @Override + public Object visit(ASTThrowStatement node, Object data) { + ((MutableInt) data).increment(); + return super.visit(node, data); + } + + + @Override + public Object visit(ASTAssertStatement node, Object data) { + if (considerAssert) { + ((MutableInt) data).add(2); // equivalent to if (condition) { throw .. } + + if (considerBooleanPaths) { + ((MutableInt) data).add(CycloMetric.booleanExpressionComplexity(node.getGuardExpressionNode())); + } + } + + return super.visit(node, data); + } + +} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/internal/NcssVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/internal/NcssVisitor.java new file mode 100644 index 0000000000..68a243ff73 --- /dev/null +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/internal/NcssVisitor.java @@ -0,0 +1,271 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.metrics.impl.internal; + +import java.util.List; + +import org.apache.commons.lang3.mutable.MutableInt; + +import net.sourceforge.pmd.lang.java.ast.ASTAnnotationTypeDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTAssertStatement; +import net.sourceforge.pmd.lang.java.ast.ASTBreakStatement; +import net.sourceforge.pmd.lang.java.ast.ASTCatchStatement; +import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; +import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTContinueStatement; +import net.sourceforge.pmd.lang.java.ast.ASTDoStatement; +import net.sourceforge.pmd.lang.java.ast.ASTEnumDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTExplicitConstructorInvocation; +import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTFinallyStatement; +import net.sourceforge.pmd.lang.java.ast.ASTForInit; +import net.sourceforge.pmd.lang.java.ast.ASTForStatement; +import net.sourceforge.pmd.lang.java.ast.ASTForUpdate; +import net.sourceforge.pmd.lang.java.ast.ASTIfStatement; +import net.sourceforge.pmd.lang.java.ast.ASTImportDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTInitializer; +import net.sourceforge.pmd.lang.java.ast.ASTLabeledStatement; +import net.sourceforge.pmd.lang.java.ast.ASTLocalVariableDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTPackageDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTReturnStatement; +import net.sourceforge.pmd.lang.java.ast.ASTStatementExpression; +import net.sourceforge.pmd.lang.java.ast.ASTSwitchLabel; +import net.sourceforge.pmd.lang.java.ast.ASTSwitchStatement; +import net.sourceforge.pmd.lang.java.ast.ASTSynchronizedStatement; +import net.sourceforge.pmd.lang.java.ast.ASTThrowStatement; +import net.sourceforge.pmd.lang.java.ast.ASTWhileStatement; +import net.sourceforge.pmd.lang.java.ast.JavaNode; +import net.sourceforge.pmd.lang.java.ast.JavaParserVisitorAdapter; +import net.sourceforge.pmd.lang.java.metrics.impl.NcssMetric.NcssOption; +import net.sourceforge.pmd.lang.metrics.MetricOptions; + + +/** + * Visitor for the Ncss metric. + * + * @author Clément Fournier + * @since 6.7.0 + */ +public class NcssVisitor extends JavaParserVisitorAdapter { + + protected final boolean countImports; + + + @SuppressWarnings("PMD.UnusedFormalParameter") + public NcssVisitor(MetricOptions options, JavaNode topNode) { + countImports = options.contains(NcssOption.COUNT_IMPORTS); + // topNode is unused, but we'll need it if we want to discount lambdas + // if we add it later, we break binary compatibility + } + + + @Override + public final Object visit(JavaNode node, Object data) { + // same here + return super.visit(node, data); + } + + + @Override + public Object visit(ASTClassOrInterfaceDeclaration node, Object data) { + if (countImports) { + ASTCompilationUnit acu = node.getFirstParentOfType(ASTCompilationUnit.class); + List imports = acu.findChildrenOfType(ASTImportDeclaration.class); + + int increment = imports.size(); + if (!acu.findChildrenOfType(ASTPackageDeclaration.class).isEmpty()) { + increment++; + } + ((MutableInt) data).add(increment); + } + ((MutableInt) data).increment(); + + return super.visit(node, data); + } + + + @Override + public Object visit(ASTEnumDeclaration node, Object data) { + ((MutableInt) data).increment(); + return super.visit(node, data); + } + + + @Override + public Object visit(ASTAnnotationTypeDeclaration node, Object data) { + ((MutableInt) data).increment(); + return super.visit(node, data); + } + + + @Override + public Object visit(ASTFieldDeclaration node, Object data) { + ((MutableInt) data).increment(); + // May use a lambda + return super.visit(node, data); + } + + + @Override + public Object visit(ASTMethodDeclaration node, Object data) { + ((MutableInt) data).increment(); + return super.visit(node, data); + } + + + @Override + public Object visit(ASTConstructorDeclaration node, Object data) { + ((MutableInt) data).increment(); + return super.visit(node, data); + } + + + @Override + public Object visit(ASTLocalVariableDeclaration node, Object data) { + + // doesn't count variable declared inside a for initializer + if (!(node.jjtGetParent() instanceof ASTForInit)) { + ((MutableInt) data).increment(); + } + // May declare a lambda + return super.visit(node, data); + } + + + @Override + public Object visit(ASTIfStatement node, Object data) { + ((MutableInt) data).increment(); + if (node.hasElse()) { + ((MutableInt) data).increment(); + } + + return super.visit(node, data); + } + + + @Override + public Object visit(ASTWhileStatement node, Object data) { + ((MutableInt) data).increment(); + return super.visit(node, data); + } + + + @Override + public Object visit(ASTSwitchStatement node, Object data) { + ((MutableInt) data).increment(); + return super.visit(node, data); + } + + + @Override + public Object visit(ASTStatementExpression node, Object data) { + if (!(node.jjtGetParent().jjtGetParent() instanceof ASTForUpdate)) { + ((MutableInt) data).increment(); + } + return data; + } + + + @Override + public Object visit(ASTExplicitConstructorInvocation node, Object data) { + ((MutableInt) data).increment(); + return data; + } + + + @Override + public Object visit(ASTContinueStatement node, Object data) { + ((MutableInt) data).increment(); + return data; + } + + + @Override + public Object visit(ASTBreakStatement node, Object data) { + ((MutableInt) data).increment(); + return data; + } + + + @Override + public Object visit(ASTReturnStatement node, Object data) { + ((MutableInt) data).increment(); + return data; + } + + + @Override + public Object visit(ASTDoStatement node, Object data) { + ((MutableInt) data).increment(); + return super.visit(node, data); + } + + + @Override + public Object visit(ASTForStatement node, Object data) { + ((MutableInt) data).increment(); + return super.visit(node, data); + } + + + @Override + public Object visit(ASTSynchronizedStatement node, Object data) { + ((MutableInt) data).increment(); + return super.visit(node, data); + } + + + @Override + public Object visit(ASTCatchStatement node, Object data) { + ((MutableInt) data).increment(); + return super.visit(node, data); + } + + + @Override + public Object visit(ASTThrowStatement node, Object data) { + ((MutableInt) data).increment(); + return super.visit(node, data); + } + + + @Override + public Object visit(ASTFinallyStatement node, Object data) { + ((MutableInt) data).increment(); + return super.visit(node, data); + } + + + @Override + public Object visit(ASTLabeledStatement node, Object data) { + ((MutableInt) data).increment(); + return super.visit(node, data); + } + + + @Override + public Object visit(ASTSwitchLabel node, Object data) { + ((MutableInt) data).increment(); + return super.visit(node, data); + } + + + @Override + public Object visit(ASTInitializer node, Object data) { + ((MutableInt) data).increment(); + return super.visit(node, data); + } + + + @Override + public Object visit(ASTAssertStatement node, Object data) { + ((MutableInt) data).increment(); + return super.visit(node, data); + } + + +} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/visitors/AtfdBaseVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/visitors/AtfdBaseVisitor.java index 34873640c1..6576ae6f1d 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/visitors/AtfdBaseVisitor.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/visitors/AtfdBaseVisitor.java @@ -9,6 +9,7 @@ import java.util.List; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.mutable.MutableInt; +import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.java.ast.ASTAllocationExpression; import net.sourceforge.pmd.lang.java.ast.ASTLiteral; import net.sourceforge.pmd.lang.java.ast.ASTName; @@ -22,7 +23,10 @@ import net.sourceforge.pmd.lang.java.ast.JavaParserVisitorAdapter; * * @author Clément Fournier * @since 6.0.0 + * @deprecated Is internal API, will be moved in 7.0.0 */ +@Deprecated +@InternalApi public class AtfdBaseVisitor extends JavaParserVisitorAdapter { diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/visitors/CycloAssertAwareDecorator.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/visitors/CycloAssertAwareDecorator.java index d50a414c8a..21854db3d7 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/visitors/CycloAssertAwareDecorator.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/visitors/CycloAssertAwareDecorator.java @@ -9,10 +9,15 @@ import org.apache.commons.lang3.mutable.MutableInt; import net.sourceforge.pmd.lang.java.ast.ASTAssertStatement; import net.sourceforge.pmd.lang.java.ast.JavaParserVisitorDecorator; + /** * @author Clément Fournier * @since 6.0.0 + * + * @deprecated Visitor decorators are deprecated because they lead to fragile code. + * */ +@Deprecated public class CycloAssertAwareDecorator extends JavaParserVisitorDecorator { @Override diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/visitors/CycloBaseVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/visitors/CycloBaseVisitor.java index 47ef3aa1f5..0ece5677cc 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/visitors/CycloBaseVisitor.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/visitors/CycloBaseVisitor.java @@ -19,12 +19,16 @@ import net.sourceforge.pmd.lang.java.ast.ASTThrowStatement; import net.sourceforge.pmd.lang.java.ast.ASTWhileStatement; import net.sourceforge.pmd.lang.java.ast.JavaParserControllessVisitorAdapter; + /** * Visitor calculating cyclo without counting boolean operators. * + * @deprecated Visitor decorators are deprecated because they lead to fragile code. + * * @author Clément Fournier * @see net.sourceforge.pmd.lang.java.metrics.impl.CycloMetric */ +@Deprecated public class CycloBaseVisitor extends JavaParserControllessVisitorAdapter { /** Instance. */ diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/visitors/CycloPathAwareDecorator.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/visitors/CycloPathAwareDecorator.java index 25d87ebbee..8cbde2df99 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/visitors/CycloPathAwareDecorator.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/visitors/CycloPathAwareDecorator.java @@ -19,12 +19,16 @@ import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.java.ast.JavaParserVisitorDecorator; import net.sourceforge.pmd.lang.java.metrics.impl.CycloMetric; + /** * Decorator which counts the complexity of boolean expressions for Cyclo. * + * @deprecated Visitor decorators are deprecated because they lead to fragile code. + * * @author Clément Fournier * @see net.sourceforge.pmd.lang.java.metrics.impl.CycloMetric */ +@Deprecated public class CycloPathAwareDecorator extends JavaParserVisitorDecorator { @@ -46,7 +50,7 @@ public class CycloPathAwareDecorator extends JavaParserVisitorDecorator { return data; } - int boolCompFor = CycloMetric.booleanExpressionComplexity(node.getFirstDescendantOfType(ASTExpression.class)); + int boolCompFor = CycloMetric.booleanExpressionComplexity(node.getGuardExpressionNode()); ((MutableInt) data).add(boolCompFor); return data; } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/visitors/NcssBaseVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/visitors/NcssBaseVisitor.java index 2348a9a41e..69e72b7b53 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/visitors/NcssBaseVisitor.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/visitors/NcssBaseVisitor.java @@ -35,12 +35,17 @@ import net.sourceforge.pmd.lang.java.ast.ASTThrowStatement; import net.sourceforge.pmd.lang.java.ast.ASTWhileStatement; import net.sourceforge.pmd.lang.java.ast.JavaParserControllessVisitorAdapter; + /** * Default visitor for the calculation of Ncss. * * @author Clément Fournier * @see net.sourceforge.pmd.lang.java.metrics.impl.NcssMetric + * + * @deprecated Visitor decorators are deprecated because they lead to fragile code. + * */ +@Deprecated public class NcssBaseVisitor extends JavaParserControllessVisitorAdapter { /** Instance. */ diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/visitors/NcssCountImportsDecorator.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/visitors/NcssCountImportsDecorator.java index 879121281c..156beaade5 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/visitors/NcssCountImportsDecorator.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/visitors/NcssCountImportsDecorator.java @@ -14,12 +14,16 @@ import net.sourceforge.pmd.lang.java.ast.ASTImportDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTPackageDeclaration; import net.sourceforge.pmd.lang.java.ast.JavaParserVisitorDecorator; + /** * Decorator which counts imports. * * @author Clément Fournier * @see net.sourceforge.pmd.lang.java.metrics.impl.NcssMetric + * + * @deprecated Visitor decorators are deprecated because they lead to fragile code. */ +@Deprecated public class NcssCountImportsDecorator extends JavaParserVisitorDecorator { diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/visitors/NpathBaseVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/visitors/NpathBaseVisitor.java index 328d64b23b..902a848516 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/visitors/NpathBaseVisitor.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/visitors/NpathBaseVisitor.java @@ -6,6 +6,7 @@ package net.sourceforge.pmd.lang.java.metrics.impl.visitors; import java.util.List; +import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.java.ast.ASTConditionalExpression; import net.sourceforge.pmd.lang.java.ast.ASTDoStatement; import net.sourceforge.pmd.lang.java.ast.ASTExpression; @@ -22,17 +23,22 @@ import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.java.ast.JavaParserVisitorReducedAdapter; import net.sourceforge.pmd.lang.java.metrics.impl.CycloMetric; + /** * Visitor for the default n-path complexity version. * * @author Clément Fournier * @author Jason Bennett + * @deprecated Is internal API, will be moved in 7.0.0 */ +@Deprecated +@InternalApi public class NpathBaseVisitor extends JavaParserVisitorReducedAdapter { /** Instance. */ public static final NpathBaseVisitor INSTANCE = new NpathBaseVisitor(); + /* Multiplies the complexity of the children of this node. */ private int multiplyChildrenComplexities(JavaNode node, Object data) { int product = 1; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/visitors/TccAttributeAccessCollector.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/visitors/TccAttributeAccessCollector.java index 06cf13cf3f..0112d43807 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/visitors/TccAttributeAccessCollector.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/visitors/TccAttributeAccessCollector.java @@ -11,6 +11,7 @@ import java.util.Map; import java.util.Objects; import java.util.Set; +import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration; @@ -30,7 +31,10 @@ import net.sourceforge.pmd.lang.symboltable.Scope; * * @author Clément Fournier * @since 6.0.0 + * @deprecated Is internal API, will be moved in 7.0.0 */ +@Deprecated +@InternalApi public class TccAttributeAccessCollector extends JavaParserVisitorReducedAdapter { private final ASTAnyTypeDeclaration exploredClass; @@ -110,10 +114,10 @@ public class TccAttributeAccessCollector extends JavaParserVisitorReducedAdapter } } - return super.visit(node, data); } + private String getVariableName(ASTPrimaryExpression node) { ASTPrimaryPrefix prefix = node.getFirstDescendantOfType(ASTPrimaryPrefix.class); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/AbstractIgnoredAnnotationRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/AbstractIgnoredAnnotationRule.java index 37e6691da5..a6df69870f 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/AbstractIgnoredAnnotationRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/AbstractIgnoredAnnotationRule.java @@ -4,18 +4,21 @@ package net.sourceforge.pmd.lang.java.rule; +import static net.sourceforge.pmd.properties.PropertyFactory.stringListProperty; + import java.util.Collection; import java.util.Collections; +import java.util.List; import net.sourceforge.pmd.lang.java.ast.Annotatable; -import net.sourceforge.pmd.properties.StringMultiProperty; +import net.sourceforge.pmd.properties.PropertyDescriptor; public abstract class AbstractIgnoredAnnotationRule extends AbstractJavaRule { - private final StringMultiProperty ignoredAnnotationsDescriptor - = StringMultiProperty.named("ignoredAnnotations") + private final PropertyDescriptor> ignoredAnnotationsDescriptor + = stringListProperty("ignoredAnnotations") .desc("Fully qualified names of the annotation types that should be ignored by this rule") - .defaultValues(defaultSuppressionAnnotations()) + .defaultValue(defaultSuppressionAnnotations()) .build(); protected Collection defaultSuppressionAnnotations() { diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/GenericLiteralCheckerRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/GenericLiteralCheckerRule.java index 6cf24e57c6..8407ee22fc 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/GenericLiteralCheckerRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/GenericLiteralCheckerRule.java @@ -24,6 +24,7 @@ public class GenericLiteralCheckerRule extends AbstractJavaRule { private static final String PROPERTY_NAME = "regexPattern"; + // The rule is unused private static final StringProperty REGEX_PROPERTY = new StringProperty(PROPERTY_NAME, "Regular expression", "", 1.0f); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/AvoidUsingHardCodedIPRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/AvoidUsingHardCodedIPRule.java index 6e51e2b5ad..364162fecf 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/AvoidUsingHardCodedIPRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/AvoidUsingHardCodedIPRule.java @@ -4,9 +4,9 @@ package net.sourceforge.pmd.lang.java.rule.bestpractices; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -16,10 +16,14 @@ import org.apache.commons.lang3.StringUtils; import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; import net.sourceforge.pmd.lang.java.ast.ASTLiteral; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; -import net.sourceforge.pmd.properties.EnumeratedMultiProperty; +import net.sourceforge.pmd.properties.PropertyDescriptor; +import net.sourceforge.pmd.properties.PropertyFactory; + public class AvoidUsingHardCodedIPRule extends AbstractJavaRule { + // why is everything public? + public static final String IPV4 = "IPv4"; public static final String IPV6 = "IPv6"; public static final String IPV4_MAPPED_IPV6 = "IPv4 mapped IPv6"; @@ -35,10 +39,10 @@ public class AvoidUsingHardCodedIPRule extends AbstractJavaRule { } - public static final EnumeratedMultiProperty CHECK_ADDRESS_TYPES_DESCRIPTOR = new EnumeratedMultiProperty<>( - "checkAddressTypes", "Check for IP address types.", ADDRESSES_TO_CHECK, - Arrays.asList(IPV4, IPV6, IPV4_MAPPED_IPV6), - String.class, 2.0f); + public static final PropertyDescriptor> CHECK_ADDRESS_TYPES_DESCRIPTOR = + PropertyFactory.enumListProperty("checkAddressTypes", ADDRESSES_TO_CHECK) + .desc("Check for IP address types.") + .defaultValue(ADDRESSES_TO_CHECK.keySet()).build(); // Provides 4 capture groups that can be used for additional validation protected static final String IPV4_REGEXP = "([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})"; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/GuardLogStatementRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/GuardLogStatementRule.java index 22a73fc62a..15c1b578bb 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/GuardLogStatementRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/GuardLogStatementRule.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.lang.java.rule.bestpractices; +import static net.sourceforge.pmd.properties.PropertyFactory.stringListProperty; + import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -24,29 +26,29 @@ import net.sourceforge.pmd.lang.java.ast.ASTPrimaryPrefix; import net.sourceforge.pmd.lang.java.ast.ASTPrimarySuffix; import net.sourceforge.pmd.lang.java.ast.ASTStatementExpression; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; -import net.sourceforge.pmd.properties.StringMultiProperty; +import net.sourceforge.pmd.properties.PropertyDescriptor; /** * Check that log.debug, log.trace, log.error, etc... statements are guarded by * some test expression on log.isDebugEnabled() or log.isTraceEnabled(). - * + * * @author Romain Pelisse - <belaran@gmail.com> * @author Heiko Rupp - <hwr@pilhuhn.de> * @author Tammo van Lessen - provided original XPath expression - * + * */ public class GuardLogStatementRule extends AbstractJavaRule implements Rule { /* * guard methods and log levels: - * + * * log4j + apache commons logging (jakarta): * trace -> isTraceEnabled * debug -> isDebugEnabled * info -> isInfoEnabled * warn -> isWarnEnabled * error -> isErrorEnabled - * - * + * + * * java util: * log(Level.FINE) -> isLoggable * finest -> isLoggable @@ -56,14 +58,19 @@ public class GuardLogStatementRule extends AbstractJavaRule implements Rule { * warning -> isLoggable * severe -> isLoggable */ - private static final StringMultiProperty LOG_LEVELS = new StringMultiProperty("logLevels", "LogLevels to guard", - new String[] {"trace", "debug", "info", "warn", "error", - "log", "finest", "finer", "fine", "info", "warning", "severe", }, 1.0f, ','); + private static final PropertyDescriptor> LOG_LEVELS = + stringListProperty("logLevels") + .desc("LogLevels to guard") + .defaultValues("trace", "debug", "info", "warn", "error", + "log", "finest", "finer", "fine", "info", "warning", "severe") + .delim(',') + .build(); - private static final StringMultiProperty GUARD_METHODS = new StringMultiProperty("guardsMethods", - "method use to guard the log statement", - new String[] {"isTraceEnabled", "isDebugEnabled", "isInfoEnabled", "isWarnEnabled", "isErrorEnabled", - "isLoggable", }, 2.0f, ','); + private static final PropertyDescriptor> GUARD_METHODS = + stringListProperty("guardsMethods") + .desc("Method use to guard the log statement") + .defaultValues("isTraceEnabled", "isDebugEnabled", "isInfoEnabled", "isWarnEnabled", "isErrorEnabled", "isLoggable") + .delim(',').build(); private Map guardStmtByLogLevel = new HashMap<>(12); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/JUnitTestsShouldIncludeAssertRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/JUnitTestsShouldIncludeAssertRule.java index 4cbfb154b2..f7c8e7b424 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/JUnitTestsShouldIncludeAssertRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/JUnitTestsShouldIncludeAssertRule.java @@ -17,6 +17,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTName; import net.sourceforge.pmd.lang.java.ast.ASTNormalAnnotation; import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression; +import net.sourceforge.pmd.lang.java.ast.ASTPrimaryPrefix; +import net.sourceforge.pmd.lang.java.ast.ASTPrimarySuffix; import net.sourceforge.pmd.lang.java.ast.ASTReferenceType; import net.sourceforge.pmd.lang.java.ast.ASTStatementExpression; import net.sourceforge.pmd.lang.java.rule.AbstractJUnitRule; @@ -173,29 +175,25 @@ public class JUnitTestsShouldIncludeAssertRule extends AbstractJUnitRule { private boolean isExpectStatement(ASTStatementExpression expression, Map> expectables) { - - if (expression != null) { - - ASTPrimaryExpression pe = expression.getFirstChildOfType(ASTPrimaryExpression.class); - if (pe != null) { - Node name = pe.getFirstDescendantOfType(ASTName.class); - // case of an AllocationExpression - if (name == null) { - return false; + ASTPrimaryExpression pe = expression.getFirstChildOfType(ASTPrimaryExpression.class); + if (pe != null) { + ASTPrimaryPrefix primaryPrefix = pe.getFirstChildOfType(ASTPrimaryPrefix.class); + Node name = pe.getFirstDescendantOfType(ASTName.class); + if (!primaryPrefix.usesThisModifier() && name != null) { + String[] parts = name.getImage().split("\\."); + if (parts.length >= 2) { + String varname = parts[0]; + String methodName = parts[1]; + if (expectables.containsKey(varname) && "expect".equals(methodName)) { + return true; + } } - - String img = name.getImage(); - if (img.indexOf(".") == -1) { - return false; - } - String varname = img.split("\\.")[0]; - - if (!expectables.containsKey(varname)) { - return false; - } - - for (NameOccurrence occ : expectables.get(varname)) { - if (occ.getLocation() == name && img.startsWith(varname + ".expect")) { + } else if (primaryPrefix.usesThisModifier()) { + List primarySuffixes = pe.findChildrenOfType(ASTPrimarySuffix.class); + if (primarySuffixes.size() >= 2) { + String varname = primarySuffixes.get(0).getImage(); + String methodName = primarySuffixes.get(1).getImage(); + if (expectables.containsKey(varname) && "expect".equals(methodName)) { return true; } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UnusedFormalParameterRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UnusedFormalParameterRule.java index df8473acbf..2f9d9cdd8c 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UnusedFormalParameterRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UnusedFormalParameterRule.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.lang.java.rule.bestpractices; +import static net.sourceforge.pmd.properties.PropertyFactory.booleanProperty; + import java.io.InvalidObjectException; import java.io.ObjectInputStream; import java.util.List; @@ -25,12 +27,12 @@ import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; import net.sourceforge.pmd.lang.java.symboltable.JavaNameOccurrence; import net.sourceforge.pmd.lang.java.symboltable.VariableNameDeclaration; import net.sourceforge.pmd.lang.symboltable.NameOccurrence; -import net.sourceforge.pmd.properties.BooleanProperty; +import net.sourceforge.pmd.properties.PropertyDescriptor; + public class UnusedFormalParameterRule extends AbstractJavaRule { - private static final BooleanProperty CHECKALL_DESCRIPTOR = new BooleanProperty("checkAll", - "Check all methods, including non-private ones", false, 1.0f); + private static final PropertyDescriptor CHECKALL_DESCRIPTOR = booleanProperty("checkAll").desc("Check all methods, including non-private ones").defaultValue(false).build(); public UnusedFormalParameterRule() { definePropertyDescriptor(CHECKALL_DESCRIPTOR); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/AbstractNamingConventionRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/AbstractNamingConventionRule.java index e53f3a9c23..825cf30f7e 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/AbstractNamingConventionRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/AbstractNamingConventionRule.java @@ -8,9 +8,9 @@ import java.util.regex.Pattern; import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; +import net.sourceforge.pmd.properties.PropertyBuilder.RegexPropertyBuilder; import net.sourceforge.pmd.properties.PropertyDescriptor; -import net.sourceforge.pmd.properties.RegexProperty; -import net.sourceforge.pmd.properties.RegexProperty.RegexPBuilder; +import net.sourceforge.pmd.properties.PropertyFactory; import net.sourceforge.pmd.util.StringUtil; @@ -30,15 +30,15 @@ abstract class AbstractNamingConventionRule extends Abstract static final String PASCAL_CASE = "[A-Z][a-zA-Z0-9]*"; /** The argument is interpreted as the display name, and is converted to camel case to get the property name. */ - RegexPBuilder defaultProp(String displayName) { + RegexPropertyBuilder defaultProp(String displayName) { return defaultProp(StringUtil.toCamelCase(displayName, true), displayName); } /** Returns a pre-filled builder with the given name and display name (for the description). */ - RegexPBuilder defaultProp(String name, String displayName) { - return RegexProperty.named(name + "Pattern") - .desc("Regex which applies to " + displayName.trim() + " names") - .defaultValue(defaultConvention()); + RegexPropertyBuilder defaultProp(String name, String displayName) { + return PropertyFactory.regexProperty(name + "Pattern") + .desc("Regex which applies to " + displayName.trim() + " names") + .defaultValue(defaultConvention()); } /** Default regex string for this kind of entities. */ diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/ClassNamingConventionsRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/ClassNamingConventionsRule.java index 4914f88c3a..d7b71155a0 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/ClassNamingConventionsRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/ClassNamingConventionsRule.java @@ -17,7 +17,6 @@ import net.sourceforge.pmd.lang.java.ast.ASTInitializer; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; import net.sourceforge.pmd.lang.java.ast.AccessNode; import net.sourceforge.pmd.properties.PropertyDescriptor; -import net.sourceforge.pmd.properties.RegexProperty; /** @@ -25,12 +24,12 @@ import net.sourceforge.pmd.properties.RegexProperty; */ public class ClassNamingConventionsRule extends AbstractNamingConventionRule { - private final RegexProperty classRegex = defaultProp("class", "concrete class").build(); - private final RegexProperty abstractClassRegex = defaultProp("abstract class").build(); - private final RegexProperty interfaceRegex = defaultProp("interface").build(); - private final RegexProperty enumerationRegex = defaultProp("enum").build(); - private final RegexProperty annotationRegex = defaultProp("annotation").build(); - private final RegexProperty utilityClassRegex = defaultProp("utility class").defaultValue("[A-Z][a-zA-Z0-9]+(Utils?|Helper)").build(); + private final PropertyDescriptor classRegex = defaultProp("class", "concrete class").build(); + private final PropertyDescriptor abstractClassRegex = defaultProp("abstract class").build(); + private final PropertyDescriptor interfaceRegex = defaultProp("interface").build(); + private final PropertyDescriptor enumerationRegex = defaultProp("enum").build(); + private final PropertyDescriptor annotationRegex = defaultProp("annotation").build(); + private final PropertyDescriptor utilityClassRegex = defaultProp("utility class").defaultValue("[A-Z][a-zA-Z0-9]+(Utils?|Helper)").build(); public ClassNamingConventionsRule() { diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/CommentDefaultAccessModifierRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/CommentDefaultAccessModifierRule.java index 02a55f36d2..37c5eac750 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/CommentDefaultAccessModifierRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/CommentDefaultAccessModifierRule.java @@ -9,6 +9,7 @@ import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.regex.Pattern; import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration; @@ -22,7 +23,8 @@ import net.sourceforge.pmd.lang.java.ast.AbstractAnyTypeDeclaration; import net.sourceforge.pmd.lang.java.ast.AbstractJavaAccessNode; import net.sourceforge.pmd.lang.java.ast.Comment; import net.sourceforge.pmd.lang.java.rule.AbstractIgnoredAnnotationRule; -import net.sourceforge.pmd.properties.RegexProperty; +import net.sourceforge.pmd.properties.PropertyDescriptor; +import net.sourceforge.pmd.properties.PropertyFactory; /** * Check for Methods, Fields and Nested Classes that have a default access @@ -34,8 +36,8 @@ import net.sourceforge.pmd.properties.RegexProperty; */ public class CommentDefaultAccessModifierRule extends AbstractIgnoredAnnotationRule { - private static final RegexProperty REGEX_DESCRIPTOR = RegexProperty.named("regex") - .desc("Regular expression").defaultValue("\\/\\*\\s+(default|package)\\s+\\*\\/").uiOrder(1.0f).build(); + private static final PropertyDescriptor REGEX_DESCRIPTOR = PropertyFactory.regexProperty("regex") + .desc("Regular expression").defaultValue("\\/\\*\\s+(default|package)\\s+\\*\\/").build(); private static final String MESSAGE = "To avoid mistakes add a comment " + "at the beginning of the %s %s if you want a default access modifier"; private final Set interestingLineNumberComments = new HashSet<>(); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/ConfusingTernaryRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/ConfusingTernaryRule.java index 8eb681819b..2d6f748eba 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/ConfusingTernaryRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/ConfusingTernaryRule.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.lang.java.rule.codestyle; +import static net.sourceforge.pmd.properties.PropertyFactory.booleanProperty; + import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.java.ast.ASTConditionalAndExpression; import net.sourceforge.pmd.lang.java.ast.ASTConditionalExpression; @@ -15,7 +17,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression; import net.sourceforge.pmd.lang.java.ast.ASTPrimaryPrefix; import net.sourceforge.pmd.lang.java.ast.ASTUnaryExpressionNotPlusMinus; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; -import net.sourceforge.pmd.properties.BooleanProperty; +import net.sourceforge.pmd.properties.PropertyDescriptor; + /** * if (x != y) { diff(); } else { same(); } and
@@ -51,8 +54,7 @@ import net.sourceforge.pmd.properties.BooleanProperty; * */ public class ConfusingTernaryRule extends AbstractJavaRule { - private static BooleanProperty ignoreElseIfProperty = new BooleanProperty("ignoreElseIf", - "Ignore conditions with an else-if case", Boolean.FALSE, 0); + private static PropertyDescriptor ignoreElseIfProperty = booleanProperty("ignoreElseIf").desc("Ignore conditions with an else-if case").defaultValue(false).build(); public ConfusingTernaryRule() { super(); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/FieldDeclarationsShouldBeAtStartOfClassRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/FieldDeclarationsShouldBeAtStartOfClassRule.java index 3b173e06a4..eb8e90bbb0 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/FieldDeclarationsShouldBeAtStartOfClassRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/FieldDeclarationsShouldBeAtStartOfClassRule.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.lang.java.rule.codestyle; +import static net.sourceforge.pmd.properties.PropertyFactory.booleanProperty; + import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.java.ast.ASTAnnotation; import net.sourceforge.pmd.lang.java.ast.ASTAnnotationTypeDeclaration; @@ -14,7 +16,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTEnumDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; -import net.sourceforge.pmd.properties.BooleanProperty; +import net.sourceforge.pmd.properties.PropertyDescriptor; + /** * Detects fields that are declared after methods, constructors, etc. It was a @@ -36,16 +39,11 @@ import net.sourceforge.pmd.properties.BooleanProperty; */ public class FieldDeclarationsShouldBeAtStartOfClassRule extends AbstractJavaRule { - private BooleanProperty ignoreEnumDeclarations = new BooleanProperty("ignoreEnumDeclarations", - "Ignore Enum Declarations that precede fields.", true, 1.0f); - private BooleanProperty ignoreAnonymousClassDeclarations = new BooleanProperty("ignoreAnonymousClassDeclarations", - "Ignore Field Declarations, that are initialized with anonymous class declarations", true, 2.0f); - private BooleanProperty ignoreInterfaceDeclarations = new BooleanProperty("ignoreInterfaceDeclarations", - "Ignore Interface Declarations that precede fields.", false, 3.0f); + private final PropertyDescriptor ignoreEnumDeclarations = booleanProperty("ignoreEnumDeclarations").defaultValue(true).desc("Ignore Enum Declarations that precede fields.").build(); + private final PropertyDescriptor ignoreAnonymousClassDeclarations = booleanProperty("ignoreAnonymousClassDeclarations").defaultValue(true).desc("Ignore Field Declarations, that are initialized with anonymous class declarations").build(); + private final PropertyDescriptor ignoreInterfaceDeclarations = booleanProperty("ignoreInterfaceDeclarations").defaultValue(false).desc("Ignore Interface Declarations that precede fields.").build(); + - /** - * Initializes the rule {@link FieldDeclarationsShouldBeAtStartOfClassRule}. - */ public FieldDeclarationsShouldBeAtStartOfClassRule() { definePropertyDescriptor(ignoreEnumDeclarations); definePropertyDescriptor(ignoreAnonymousClassDeclarations); @@ -67,7 +65,7 @@ public class FieldDeclarationsShouldBeAtStartOfClassRule extends AbstractJavaRul continue; } if (node.hasDescendantOfType(ASTClassOrInterfaceBodyDeclaration.class) - && getProperty(ignoreAnonymousClassDeclarations).booleanValue()) { + && getProperty(ignoreAnonymousClassDeclarations)) { continue; } if (child instanceof ASTMethodDeclaration || child instanceof ASTConstructorDeclaration @@ -77,14 +75,14 @@ public class FieldDeclarationsShouldBeAtStartOfClassRule extends AbstractJavaRul } if (child instanceof ASTClassOrInterfaceDeclaration) { ASTClassOrInterfaceDeclaration declaration = (ASTClassOrInterfaceDeclaration) child; - if (declaration.isInterface() && getProperty(ignoreInterfaceDeclarations).booleanValue()) { + if (declaration.isInterface() && getProperty(ignoreInterfaceDeclarations)) { continue; } else { addViolation(data, node); break; } } - if (child instanceof ASTEnumDeclaration && !getProperty(ignoreEnumDeclarations).booleanValue()) { + if (child instanceof ASTEnumDeclaration && !getProperty(ignoreEnumDeclarations)) { addViolation(data, node); break; } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/FieldNamingConventionsRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/FieldNamingConventionsRule.java index 240e2dd647..74fff9114f 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/FieldNamingConventionsRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/FieldNamingConventionsRule.java @@ -12,7 +12,6 @@ import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; import net.sourceforge.pmd.properties.PropertyDescriptor; import net.sourceforge.pmd.properties.PropertyFactory; -import net.sourceforge.pmd.properties.RegexProperty; /** @@ -31,12 +30,12 @@ public class FieldNamingConventionsRule extends AbstractNamingConventionRule publicConstantFieldRegex = defaultProp("public constant").defaultValue("[A-Z][A-Z_0-9]*").build(); + private final PropertyDescriptor constantFieldRegex = defaultProp("constant").desc("Regex which applies to non-public static final field names").defaultValue("[A-Z][A-Z_0-9]*").build(); + private final PropertyDescriptor enumConstantRegex = defaultProp("enum constant").defaultValue("[A-Z][A-Z_0-9]*").build(); + private final PropertyDescriptor finalFieldRegex = defaultProp("final field").build(); + private final PropertyDescriptor staticFieldRegex = defaultProp("static field").build(); + private final PropertyDescriptor defaultFieldRegex = defaultProp("defaultField", "field").build(); public FieldNamingConventionsRule() { diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/FormalParameterNamingConventionsRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/FormalParameterNamingConventionsRule.java index ac748895a6..4a78682992 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/FormalParameterNamingConventionsRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/FormalParameterNamingConventionsRule.java @@ -9,7 +9,6 @@ import java.util.regex.Pattern; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; import net.sourceforge.pmd.properties.PropertyDescriptor; -import net.sourceforge.pmd.properties.RegexProperty; /** @@ -23,11 +22,11 @@ public final class FormalParameterNamingConventionsRule extends AbstractNamingCo // These are not exhaustive, but are chosen to be the most useful, for a start - private final RegexProperty formalParamRegex = defaultProp("methodParameter", "formal parameter").build(); - private final RegexProperty finalFormalParamRegex = defaultProp("finalMethodParameter", "final formal parameter").build(); + private final PropertyDescriptor formalParamRegex = defaultProp("methodParameter", "formal parameter").build(); + private final PropertyDescriptor finalFormalParamRegex = defaultProp("finalMethodParameter", "final formal parameter").build(); - private final RegexProperty lambdaParamRegex = defaultProp("lambdaParameter", "inferred-type lambda parameter").build(); - private final RegexProperty explicitLambdaParamRegex = defaultProp("explicitLambdaParameter", "explicitly-typed lambda parameter").build(); + private final PropertyDescriptor lambdaParamRegex = defaultProp("lambdaParameter", "inferred-type lambda parameter").build(); + private final PropertyDescriptor explicitLambdaParamRegex = defaultProp("explicitLambdaParameter", "explicitly-typed lambda parameter").build(); public FormalParameterNamingConventionsRule() { diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/LinguisticNamingRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/LinguisticNamingRule.java index 8af4d19a9c..061e7e4196 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/LinguisticNamingRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/LinguisticNamingRule.java @@ -4,6 +4,9 @@ package net.sourceforge.pmd.lang.java.rule.codestyle; +import static net.sourceforge.pmd.properties.PropertyFactory.booleanProperty; +import static net.sourceforge.pmd.properties.PropertyFactory.stringListProperty; + import java.util.List; import java.util.Locale; @@ -17,38 +20,39 @@ import net.sourceforge.pmd.lang.java.ast.ASTType; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclarator; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; import net.sourceforge.pmd.lang.java.typeresolution.TypeHelper; -import net.sourceforge.pmd.properties.BooleanProperty; -import net.sourceforge.pmd.properties.StringMultiProperty; +import net.sourceforge.pmd.properties.PropertyDescriptor; public class LinguisticNamingRule extends AbstractJavaRule { - private static final BooleanProperty CHECK_BOOLEAN_METHODS = BooleanProperty.named("checkBooleanMethod") - .defaultValue(true).desc("Check method names and types for inconsistent naming.").uiOrder(1.0f).build(); - private static final BooleanProperty CHECK_GETTERS = BooleanProperty.named("checkGetters").defaultValue(true) - .desc("Check return type of getters.").uiOrder(2.0f).build(); - private static final BooleanProperty CHECK_SETTERS = BooleanProperty.named("checkSetters").defaultValue(true) - .desc("Check return type of setters.").uiOrder(3.0f).build(); - private static final BooleanProperty CHECK_PREFIXED_TRANSFORM_METHODS = BooleanProperty - .named("checkPrefixedTransformMethods").defaultValue(true) - .desc("Check return type of methods whose names start with the configured prefix (see transformMethodNames property).") - .uiOrder(4.0f).build(); - private static final BooleanProperty CHECK_TRANSFORM_METHODS = BooleanProperty.named("checkTransformMethods") - .defaultValue(false) - .desc("Check return type of methods which contain the configured infix in their name (see transformMethodNames property).") - .uiOrder(4.0f).build(); - private static final StringMultiProperty BOOLEAN_METHOD_PREFIXES_PROPERTY = StringMultiProperty - .named("booleanMethodPrefixes").defaultValues("is", "has", "can", "have", "will", "should") - .desc("The prefixes of methods that return boolean.").uiOrder(5.0f).build(); - private static final StringMultiProperty TRANSFORM_METHOD_NAMES_PROPERTY = StringMultiProperty - .named("transformMethodNames").defaultValues("to", "as") - .desc("The prefixes and infixes that indicate a transform method.").uiOrder(6.0f).build(); - - private static final BooleanProperty CHECK_FIELDS = BooleanProperty.named("checkFields").defaultValue(true) - .desc("Check field names and types for inconsistent naming.").uiOrder(7.0f).build(); - private static final BooleanProperty CHECK_VARIABLES = BooleanProperty.named("checkVariables").defaultValue(true) - .desc("Check local variable names and types for inconsistent naming.").uiOrder(8.0f).build(); - private static final StringMultiProperty BOOLEAN_FIELD_PREFIXES_PROPERTY = StringMultiProperty - .named("booleanFieldPrefixes").defaultValues("is", "has", "can", "have", "will", "should") - .desc("The prefixes of fields and variables that indicate boolean.").uiOrder(9.0f).build(); + private static final PropertyDescriptor CHECK_BOOLEAN_METHODS = + booleanProperty("checkBooleanMethod").defaultValue(true).desc("Check method names and types for inconsistent naming.").build(); + private static final PropertyDescriptor CHECK_GETTERS = + booleanProperty("checkGetters").defaultValue(true).desc("Check return type of getters.").build(); + private static final PropertyDescriptor CHECK_SETTERS = + booleanProperty("checkSetters").defaultValue(true).desc("Check return type of setters.").build(); + private static final PropertyDescriptor CHECK_PREFIXED_TRANSFORM_METHODS = + booleanProperty("checkPrefixedTransformMethods") + .desc("Check return type of methods whose names start with the configured prefix (see transformMethodNames property).") + .defaultValue(true).build(); + private static final PropertyDescriptor CHECK_TRANSFORM_METHODS = + booleanProperty("checkTransformMethods") + .desc("Check return type of methods which contain the configured infix in their name (see transformMethodNames property).") + .defaultValue(false).build(); + private static final PropertyDescriptor CHECK_FIELDS = + booleanProperty("checkFields").defaultValue(true).desc("Check field names and types for inconsistent naming.").build(); + private static final PropertyDescriptor CHECK_VARIABLES = + booleanProperty("checkVariables").defaultValue(true).desc("Check local variable names and types for inconsistent naming.").build(); + private static final PropertyDescriptor> BOOLEAN_METHOD_PREFIXES_PROPERTY = + stringListProperty("booleanMethodPrefixes") + .desc("The prefixes of methods that return boolean.") + .defaultValues("is", "has", "can", "have", "will", "should").build(); + private static final PropertyDescriptor> TRANSFORM_METHOD_NAMES_PROPERTY = + stringListProperty("transformMethodNames") + .desc("The prefixes and infixes that indicate a transform method.") + .defaultValues("to", "as").build(); + private static final PropertyDescriptor> BOOLEAN_FIELD_PREFIXES_PROPERTY = + stringListProperty("booleanFieldPrefixes") + .desc("The prefixes of fields and variables that indicate boolean.") + .defaultValues("is", "has", "can", "have", "will", "should").build(); public LinguisticNamingRule() { definePropertyDescriptor(CHECK_BOOLEAN_METHODS); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/LocalVariableCouldBeFinalRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/LocalVariableCouldBeFinalRule.java index 7bf3bb424a..02678cf884 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/LocalVariableCouldBeFinalRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/LocalVariableCouldBeFinalRule.java @@ -4,22 +4,36 @@ package net.sourceforge.pmd.lang.java.rule.codestyle; +import static net.sourceforge.pmd.properties.PropertyFactory.booleanProperty; + import java.util.List; import java.util.Map; +import net.sourceforge.pmd.lang.java.ast.ASTForStatement; import net.sourceforge.pmd.lang.java.ast.ASTLocalVariableDeclaration; import net.sourceforge.pmd.lang.java.rule.performance.AbstractOptimizationRule; import net.sourceforge.pmd.lang.java.symboltable.VariableNameDeclaration; import net.sourceforge.pmd.lang.symboltable.NameOccurrence; import net.sourceforge.pmd.lang.symboltable.Scope; +import net.sourceforge.pmd.properties.PropertyDescriptor; public class LocalVariableCouldBeFinalRule extends AbstractOptimizationRule { + private static final PropertyDescriptor IGNORE_FOR_EACH = + booleanProperty("ignoreForEachDecl").defaultValue(false).desc("Ignore non-final loop variables in a for-each statement.").build(); + + public LocalVariableCouldBeFinalRule() { + definePropertyDescriptor(IGNORE_FOR_EACH); + } + @Override public Object visit(ASTLocalVariableDeclaration node, Object data) { if (node.isFinal()) { return data; } + if (getProperty(IGNORE_FOR_EACH) && node.jjtGetParent() instanceof ASTForStatement) { + return data; + } Scope s = node.getScope(); Map> decls = s.getDeclarations(VariableNameDeclaration.class); for (Map.Entry> entry : decls.entrySet()) { diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/LocalVariableNamingConventionsRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/LocalVariableNamingConventionsRule.java index d90c77512c..cc4ea66a10 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/LocalVariableNamingConventionsRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/LocalVariableNamingConventionsRule.java @@ -8,7 +8,6 @@ import java.util.regex.Pattern; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; import net.sourceforge.pmd.properties.PropertyDescriptor; -import net.sourceforge.pmd.properties.RegexProperty; /** @@ -21,10 +20,10 @@ public final class LocalVariableNamingConventionsRule extends AbstractNamingConv // These are not exhaustive, but are chosen to be the most useful, for a start - private final RegexProperty localVarRegex = defaultProp("localVar", "non-final local variable").build(); - private final RegexProperty finalVarRegex = defaultProp("finalVar", "final local variable").build(); + private final PropertyDescriptor localVarRegex = defaultProp("localVar", "non-final local variable").build(); + private final PropertyDescriptor finalVarRegex = defaultProp("finalVar", "final local variable").build(); - private final RegexProperty exceptionBlockParameterRegex = defaultProp("catchParameter", "exception block parameter").build(); + private final PropertyDescriptor exceptionBlockParameterRegex = defaultProp("catchParameter", "exception block parameter").build(); public LocalVariableNamingConventionsRule() { diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/MethodNamingConventionsRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/MethodNamingConventionsRule.java index 75de6f59de..1ead9640fa 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/MethodNamingConventionsRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/MethodNamingConventionsRule.java @@ -17,9 +17,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTEnumConstant; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; import net.sourceforge.pmd.lang.java.typeresolution.TypeHelper; import net.sourceforge.pmd.properties.BooleanProperty; +import net.sourceforge.pmd.properties.PropertyBuilder.RegexPropertyBuilder; import net.sourceforge.pmd.properties.PropertyDescriptor; -import net.sourceforge.pmd.properties.RegexProperty; -import net.sourceforge.pmd.properties.RegexProperty.RegexPBuilder; public class MethodNamingConventionsRule extends AbstractNamingConventionRule { @@ -31,11 +30,11 @@ public class MethodNamingConventionsRule extends AbstractNamingConventionRule instanceRegex = defaultProp("", "instance").build(); + private final PropertyDescriptor staticRegex = defaultProp("static").build(); + private final PropertyDescriptor nativeRegex = defaultProp("native").build(); + private final PropertyDescriptor junit3Regex = defaultProp("JUnit 3 test").defaultValue("test[A-Z0-9][a-zA-Z0-9]*").build(); + private final PropertyDescriptor junit4Regex = defaultProp("JUnit 4 test").build(); public MethodNamingConventionsRule() { @@ -110,9 +109,9 @@ public class MethodNamingConventionsRule extends AbstractNamingConventionRule STATEMENT_ORDER_MATTERS = booleanProperty("statementOrderMatters").defaultValue(true).desc("If set to false this rule no longer requires the variable declaration and return statement to be on consecutive lines. Any variable that is used solely in a return statement will be reported.").build(); + public UnnecessaryLocalBeforeReturnRule() { definePropertyDescriptor(STATEMENT_ORDER_MATTERS); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/VariableNamingConventionsRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/VariableNamingConventionsRule.java index 3e79516e91..4ec8326aad 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/VariableNamingConventionsRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/VariableNamingConventionsRule.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.lang.java.rule.codestyle; +import static net.sourceforge.pmd.properties.PropertyFactory.booleanProperty; + import java.util.List; import java.util.Locale; @@ -19,7 +21,6 @@ import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclarator; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; -import net.sourceforge.pmd.properties.BooleanProperty; import net.sourceforge.pmd.properties.PropertyDescriptor; import net.sourceforge.pmd.properties.StringMultiProperty; @@ -39,18 +40,15 @@ public class VariableNamingConventionsRule extends AbstractJavaRule { private List parameterPrefixes; private List parameterSuffixes; - private static final BooleanProperty CHECK_MEMBERS_DESCRIPTOR = new BooleanProperty("checkMembers", - "Check member variables", true, 1.0f); + private static final PropertyDescriptor CHECK_MEMBERS_DESCRIPTOR = booleanProperty("checkMembers").defaultValue(true).desc("Check member variables").build(); - private static final BooleanProperty CHECK_LOCALS_DESCRIPTOR = new BooleanProperty("checkLocals", - "Check local variables", true, 2.0f); + private static final PropertyDescriptor CHECK_LOCALS_DESCRIPTOR = booleanProperty("checkLocals").defaultValue(true).desc("Check local variables").build(); - private static final BooleanProperty CHECK_PARAMETERS_DESCRIPTOR = new BooleanProperty("checkParameters", - "Check constructor and method parameter variables", true, 3.0f); + private static final PropertyDescriptor CHECK_PARAMETERS_DESCRIPTOR = booleanProperty("checkParameters").defaultValue(true).desc("Check constructor and method parameter variables").build(); - private static final BooleanProperty CHECK_NATIVE_METHOD_PARAMETERS_DESCRIPTOR = new BooleanProperty( - "checkNativeMethodParameters", "Check method parameter of native methods", true, 3.5f); + private static final PropertyDescriptor CHECK_NATIVE_METHOD_PARAMETERS_DESCRIPTOR = booleanProperty("checkNativeMethodParameters").defaultValue(true).desc("Check method parameter of native methods").build(); + // the rule is deprecated and will be removed so its properties won't be converted private static final StringMultiProperty STATIC_PREFIXES_DESCRIPTOR = new StringMultiProperty("staticPrefix", "Static variable prefixes", new String[] { "" }, 4.0f, ','); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/AvoidDeeplyNestedIfStmtsRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/AvoidDeeplyNestedIfStmtsRule.java index 49b5012301..0bc350780a 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/AvoidDeeplyNestedIfStmtsRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/AvoidDeeplyNestedIfStmtsRule.java @@ -4,20 +4,24 @@ package net.sourceforge.pmd.lang.java.rule.design; +import static net.sourceforge.pmd.properties.constraints.NumericConstraints.positive; + import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; import net.sourceforge.pmd.lang.java.ast.ASTIfStatement; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; -import net.sourceforge.pmd.properties.IntegerProperty; +import net.sourceforge.pmd.properties.PropertyDescriptor; +import net.sourceforge.pmd.properties.PropertyFactory; + public class AvoidDeeplyNestedIfStmtsRule extends AbstractJavaRule { private int depth; private int depthLimit; - private static final IntegerProperty PROBLEM_DEPTH_DESCRIPTOR - = IntegerProperty.named("problemDepth") + private static final PropertyDescriptor PROBLEM_DEPTH_DESCRIPTOR + = PropertyFactory.intProperty("problemDepth") .desc("The if statement depth reporting threshold") - .range(1, 25).defaultValue(3).uiOrder(1.0f).build(); + .require(positive()).defaultValue(3).build(); public AvoidDeeplyNestedIfStmtsRule() { definePropertyDescriptor(PROBLEM_DEPTH_DESCRIPTOR); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/CouplingBetweenObjectsRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/CouplingBetweenObjectsRule.java index ba4ec721c0..6dbf9f9996 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/CouplingBetweenObjectsRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/CouplingBetweenObjectsRule.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.lang.java.rule.design; +import static net.sourceforge.pmd.properties.constraints.NumericConstraints.positive; + import java.util.HashSet; import java.util.Set; @@ -20,7 +22,9 @@ import net.sourceforge.pmd.lang.java.ast.ASTType; import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; import net.sourceforge.pmd.lang.java.symboltable.ClassScope; -import net.sourceforge.pmd.properties.IntegerProperty; +import net.sourceforge.pmd.properties.PropertyDescriptor; +import net.sourceforge.pmd.properties.PropertyFactory; + /** * CouplingBetweenObjects attempts to capture all unique Class attributes, local @@ -36,10 +40,10 @@ public class CouplingBetweenObjectsRule extends AbstractJavaRule { private int couplingCount; private Set typesFoundSoFar; - private static final IntegerProperty THRESHOLD_DESCRIPTOR - = IntegerProperty.named("threshold") + private static final PropertyDescriptor THRESHOLD_DESCRIPTOR + = PropertyFactory.intProperty("threshold") .desc("Unique type reporting threshold") - .range(2, 100).defaultValue(20).uiOrder(1.0f).build(); + .require(positive()).defaultValue(20).build(); public CouplingBetweenObjectsRule() { definePropertyDescriptor(THRESHOLD_DESCRIPTOR); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/CyclomaticComplexityRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/CyclomaticComplexityRule.java index 339ac0aec3..2b49c39ba1 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/CyclomaticComplexityRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/CyclomaticComplexityRule.java @@ -4,8 +4,10 @@ package net.sourceforge.pmd.lang.java.rule.design; -import java.util.Collections; +import static net.sourceforge.pmd.properties.constraints.NumericConstraints.positive; + import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.logging.Logger; @@ -20,8 +22,8 @@ import net.sourceforge.pmd.lang.java.metrics.impl.CycloMetric.CycloOption; import net.sourceforge.pmd.lang.java.rule.AbstractJavaMetricsRule; import net.sourceforge.pmd.lang.metrics.MetricOptions; import net.sourceforge.pmd.lang.metrics.ResultOption; -import net.sourceforge.pmd.properties.EnumeratedMultiProperty; -import net.sourceforge.pmd.properties.IntegerProperty; +import net.sourceforge.pmd.properties.PropertyDescriptor; +import net.sourceforge.pmd.properties.PropertyFactory; /** @@ -37,21 +39,21 @@ public class CyclomaticComplexityRule extends AbstractJavaMetricsRule { // Deprecated, kept for backwards compatibility (6.0.0) @Deprecated - private static final IntegerProperty REPORT_LEVEL_DESCRIPTOR - = IntegerProperty.named("reportLevel") + private static final PropertyDescriptor REPORT_LEVEL_DESCRIPTOR + = PropertyFactory.intProperty("reportLevel") .desc("Deprecated! Cyclomatic Complexity reporting threshold") - .range(1, 30).defaultValue(10).uiOrder(1.0f).build(); + .require(positive()).defaultValue(10).build(); - private static final IntegerProperty CLASS_LEVEL_DESCRIPTOR - = IntegerProperty.named("classReportLevel") + private static final PropertyDescriptor CLASS_LEVEL_DESCRIPTOR + = PropertyFactory.intProperty("classReportLevel") .desc("Total class complexity reporting threshold") - .range(1, 600).defaultValue(80).uiOrder(1.0f).build(); + .require(positive()).defaultValue(80).build(); - private static final IntegerProperty METHOD_LEVEL_DESCRIPTOR - = IntegerProperty.named("methodReportLevel") + private static final PropertyDescriptor METHOD_LEVEL_DESCRIPTOR + = PropertyFactory.intProperty("methodReportLevel") .desc("Cyclomatic complexity reporting threshold") - .range(1, 50).defaultValue(10).uiOrder(1.0f).build(); + .require(positive()).defaultValue(10).build(); private static final Map OPTION_MAP; @@ -60,13 +62,13 @@ public class CyclomaticComplexityRule extends AbstractJavaMetricsRule { OPTION_MAP.put(CycloOption.IGNORE_BOOLEAN_PATHS.valueName(), CycloOption.IGNORE_BOOLEAN_PATHS); OPTION_MAP.put(CycloOption.CONSIDER_ASSERT.valueName(), CycloOption.CONSIDER_ASSERT); } - - private static final EnumeratedMultiProperty CYCLO_OPTIONS_DESCRIPTOR - = EnumeratedMultiProperty.named("cycloOptions").type(CycloOption.class) - .desc("Choose options for the computation of Cyclo") - .mappings(OPTION_MAP) - .defaultValues(Collections.emptyList()) - .uiOrder(3.0f).build(); + + private static final PropertyDescriptor> CYCLO_OPTIONS_DESCRIPTOR + = PropertyFactory.enumListProperty("cycloOptions", OPTION_MAP) + .desc("Choose options for the computation of Cyclo") + .emptyDefaultValue() + .build(); + private int methodReportLevel; private int classReportLevel; private MetricOptions cycloOptions; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/GenericClassCounterRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/GenericClassCounterRule.java index 938d06b502..44849f2132 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/GenericClassCounterRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/GenericClassCounterRule.java @@ -51,6 +51,7 @@ import net.sourceforge.pmd.properties.StringProperty; */ public class GenericClassCounterRule extends AbstractJavaRule { + // Class is unused, properties won't be converted private static final StringMultiProperty NAME_MATCH_DESCRIPTOR = new StringMultiProperty("nameMatch", "A series of regex, separated by ',' to match on the classname", new String[] { "" }, 1.0f, ','); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/LoosePackageCouplingRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/LoosePackageCouplingRule.java index 6631d68531..6c0c271a5d 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/LoosePackageCouplingRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/LoosePackageCouplingRule.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.lang.java.rule.design; +import static net.sourceforge.pmd.properties.PropertyFactory.stringListProperty; + import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -12,8 +14,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; import net.sourceforge.pmd.lang.java.ast.ASTImportDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTPackageDeclaration; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; +import net.sourceforge.pmd.properties.PropertyDescriptor; import net.sourceforge.pmd.properties.PropertySource; -import net.sourceforge.pmd.properties.StringMultiProperty; /** * The loose package coupling Rule can be used to ensure coupling outside of a @@ -36,11 +38,11 @@ import net.sourceforge.pmd.properties.StringMultiProperty; */ public class LoosePackageCouplingRule extends AbstractJavaRule { - public static final StringMultiProperty PACKAGES_DESCRIPTOR = new StringMultiProperty("packages", - "Restricted packages", new String[] {}, 1.0f, ','); + public static final PropertyDescriptor> PACKAGES_DESCRIPTOR = + stringListProperty("packages").desc("Restricted packages").emptyDefaultValue().delim(',').build(); - public static final StringMultiProperty CLASSES_DESCRIPTOR = new StringMultiProperty("classes", "Allowed classes", - new String[] {}, 2.0f, ','); + public static final PropertyDescriptor> CLASSES_DESCRIPTOR = + stringListProperty("classes").desc("Allowed classes").emptyDefaultValue().delim(',').build(); // The package of this source file private String thisPackage; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/NPathComplexityRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/NPathComplexityRule.java index 59891ef461..d17eaacc48 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/NPathComplexityRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/NPathComplexityRule.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.lang.java.rule.design; +import static net.sourceforge.pmd.properties.constraints.NumericConstraints.positive; + import java.util.logging.Logger; import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; @@ -13,8 +15,8 @@ import net.sourceforge.pmd.lang.java.ast.MethodLikeNode; import net.sourceforge.pmd.lang.java.metrics.JavaMetrics; import net.sourceforge.pmd.lang.java.metrics.api.JavaOperationMetricKey; import net.sourceforge.pmd.lang.java.rule.AbstractJavaMetricsRule; -import net.sourceforge.pmd.properties.DoubleProperty; -import net.sourceforge.pmd.properties.IntegerProperty; +import net.sourceforge.pmd.properties.PropertyDescriptor; +import net.sourceforge.pmd.properties.PropertyFactory; /** @@ -28,14 +30,14 @@ public class NPathComplexityRule extends AbstractJavaMetricsRule { private static final Logger LOG = Logger.getLogger(NPathComplexityRule.class.getName()); @Deprecated - private static final DoubleProperty MINIMUM_DESCRIPTOR - = DoubleProperty.named("minimum").desc("Deprecated! Minimum reporting threshold") - .range(0d, 2000d).defaultValue(200d).uiOrder(2.0f).build(); + private static final PropertyDescriptor MINIMUM_DESCRIPTOR + = PropertyFactory.doubleProperty("minimum").desc("Deprecated! Minimum reporting threshold") + .require(positive()).defaultValue(200d).build(); - private static final IntegerProperty REPORT_LEVEL_DESCRIPTOR - = IntegerProperty.named("reportLevel").desc("N-Path Complexity reporting threshold") - .range(1, 2000).defaultValue(200).uiOrder(1.0f).build(); + private static final PropertyDescriptor REPORT_LEVEL_DESCRIPTOR + = PropertyFactory.intProperty("reportLevel").desc("N-Path Complexity reporting threshold") + .require(positive()).defaultValue(200).build(); private int reportLevel = 200; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/NcssCountRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/NcssCountRule.java index c2eff8a423..b1bd02d1db 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/NcssCountRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/NcssCountRule.java @@ -4,8 +4,10 @@ package net.sourceforge.pmd.lang.java.rule.design; -import java.util.Collections; +import static net.sourceforge.pmd.properties.constraints.NumericConstraints.positive; + import java.util.HashMap; +import java.util.List; import java.util.Locale; import java.util.Map; @@ -20,8 +22,9 @@ import net.sourceforge.pmd.lang.java.metrics.impl.NcssMetric.NcssOption; import net.sourceforge.pmd.lang.java.rule.AbstractJavaMetricsRule; import net.sourceforge.pmd.lang.metrics.MetricOptions; import net.sourceforge.pmd.lang.metrics.ResultOption; -import net.sourceforge.pmd.properties.EnumeratedMultiProperty; -import net.sourceforge.pmd.properties.IntegerProperty; +import net.sourceforge.pmd.properties.PropertyDescriptor; +import net.sourceforge.pmd.properties.PropertyFactory; + /** * Simple rule for Ncss. Maybe to be enriched with type specific thresholds. @@ -31,17 +34,17 @@ import net.sourceforge.pmd.properties.IntegerProperty; public final class NcssCountRule extends AbstractJavaMetricsRule { - private static final IntegerProperty METHOD_REPORT_LEVEL_DESCRIPTOR = - IntegerProperty.named("methodReportLevel") + private static final PropertyDescriptor METHOD_REPORT_LEVEL_DESCRIPTOR = + PropertyFactory.intProperty("methodReportLevel") .desc("NCSS reporting threshold for methods") - .range(1, 2000) + .require(positive()) .defaultValue(60) .build(); - private static final IntegerProperty CLASS_REPORT_LEVEL_DESCRIPTOR = - IntegerProperty.named("classReportLevel") + private static final PropertyDescriptor CLASS_REPORT_LEVEL_DESCRIPTOR = + PropertyFactory.intProperty("classReportLevel") .desc("NCSS reporting threshold for classes") - .range(1, 20000) + .require(positive()) .defaultValue(1500) .build(); @@ -54,9 +57,11 @@ public final class NcssCountRule extends AbstractJavaMetricsRule { } - private static final EnumeratedMultiProperty NCSS_OPTIONS_DESCRIPTOR = new EnumeratedMultiProperty<>( - "ncssOptions", "Choose options for the calculation of Ncss", - OPTION_MAP, Collections.emptyList(), NcssOption.class, 3.0f); + private static final PropertyDescriptor> NCSS_OPTIONS_DESCRIPTOR = + PropertyFactory.enumListProperty("ncssOptions", OPTION_MAP) + .desc("Choose options for the computation of Ncss") + .emptyDefaultValue() + .build(); private int methodReportLevel; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SignatureDeclareThrowsExceptionRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SignatureDeclareThrowsExceptionRule.java index 43ec9ff20b..0492e96590 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SignatureDeclareThrowsExceptionRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SignatureDeclareThrowsExceptionRule.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.lang.java.rule.design; +import static net.sourceforge.pmd.properties.PropertyFactory.booleanProperty; + import java.util.Collections; import java.util.List; @@ -18,7 +20,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTName; import net.sourceforge.pmd.lang.java.ast.ASTNameList; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; -import net.sourceforge.pmd.properties.BooleanProperty; +import net.sourceforge.pmd.properties.PropertyDescriptor; + /** * A method/constructor shouldn't explicitly throw java.lang.Exception, since it @@ -36,8 +39,7 @@ import net.sourceforge.pmd.properties.BooleanProperty; public class SignatureDeclareThrowsExceptionRule extends AbstractJavaRule { - private static final BooleanProperty IGNORE_JUNIT_COMPLETELY_DESCRIPTOR = new BooleanProperty( - "IgnoreJUnitCompletely", "Allow all methods in a JUnit testcase to throw Exceptions", false, 1.0f); + private static final PropertyDescriptor IGNORE_JUNIT_COMPLETELY_DESCRIPTOR = booleanProperty("IgnoreJUnitCompletely").defaultValue(false).desc("Allow all methods in a JUnit testcase to throw Exceptions").build(); // Set to true when the class is determined to be a JUnit testcase private boolean junitImported = false; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SingularFieldRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SingularFieldRule.java index 0914ecc49a..69ccf0c6d8 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SingularFieldRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SingularFieldRule.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.lang.java.rule.design; +import static net.sourceforge.pmd.properties.PropertyFactory.booleanProperty; + import java.util.List; import net.sourceforge.pmd.lang.ast.Node; @@ -22,7 +24,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclarator; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; import net.sourceforge.pmd.lang.java.rule.AbstractLombokAwareRule; import net.sourceforge.pmd.lang.symboltable.NameOccurrence; -import net.sourceforge.pmd.properties.BooleanProperty; +import net.sourceforge.pmd.properties.PropertyDescriptor; + /** * @author Eric Olander @@ -35,10 +38,9 @@ public class SingularFieldRule extends AbstractLombokAwareRule { * Restore old behavior by setting both properties to true, which will * result in many false positives */ - private static final BooleanProperty CHECK_INNER_CLASSES = new BooleanProperty("checkInnerClasses", - "Check inner classes", false, 1.0f); - private static final BooleanProperty DISALLOW_NOT_ASSIGNMENT = new BooleanProperty("disallowNotAssignment", - "Disallow violations where the first usage is not an assignment", false, 2.0f); + private static final PropertyDescriptor CHECK_INNER_CLASSES = booleanProperty("checkInnerClasses").defaultValue(false).desc("Check inner classes").build(); + private static final PropertyDescriptor DISALLOW_NOT_ASSIGNMENT = booleanProperty("disallowNotAssignment").defaultValue(false).desc("Disallow violations where the first usage is not an assignment").build(); + public SingularFieldRule() { definePropertyDescriptor(CHECK_INNER_CLASSES); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/StdCyclomaticComplexityRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/StdCyclomaticComplexityRule.java index 65703cd204..d659ddf25a 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/StdCyclomaticComplexityRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/StdCyclomaticComplexityRule.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.lang.java.rule.design; +import static net.sourceforge.pmd.properties.constraints.NumericConstraints.positive; + import java.util.ArrayDeque; import java.util.Deque; @@ -25,7 +27,9 @@ import net.sourceforge.pmd.lang.java.ast.ASTSwitchStatement; import net.sourceforge.pmd.lang.java.ast.ASTWhileStatement; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; import net.sourceforge.pmd.properties.BooleanProperty; -import net.sourceforge.pmd.properties.IntegerProperty; +import net.sourceforge.pmd.properties.PropertyDescriptor; +import net.sourceforge.pmd.properties.PropertyFactory; + /** * Implements the standard cyclomatic complexity rule @@ -40,10 +44,10 @@ import net.sourceforge.pmd.properties.IntegerProperty; @Deprecated public class StdCyclomaticComplexityRule extends AbstractJavaRule { - public static final IntegerProperty REPORT_LEVEL_DESCRIPTOR - = IntegerProperty.named("reportLevel") + public static final PropertyDescriptor REPORT_LEVEL_DESCRIPTOR + = PropertyFactory.intProperty("reportLevel") .desc("Cyclomatic Complexity reporting threshold") - .range(1, 30).defaultValue(10).uiOrder(1.0f).build(); + .require(positive()).defaultValue(10).build(); public static final BooleanProperty SHOW_CLASSES_COMPLEXITY_DESCRIPTOR = new BooleanProperty( "showClassesComplexity", "Add class average violations to the report", true, 2.0f); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/TooManyFieldsRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/TooManyFieldsRule.java index b0fc794f68..8dab8dac66 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/TooManyFieldsRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/TooManyFieldsRule.java @@ -4,19 +4,27 @@ package net.sourceforge.pmd.lang.java.rule.design; +import static net.sourceforge.pmd.properties.constraints.NumericConstraints.positive; + import java.util.List; import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; -import net.sourceforge.pmd.properties.IntegerProperty; +import net.sourceforge.pmd.properties.PropertyDescriptor; +import net.sourceforge.pmd.properties.PropertyFactory; + public class TooManyFieldsRule extends AbstractJavaRule { private static final int DEFAULT_MAXFIELDS = 15; - private static final IntegerProperty MAX_FIELDS_DESCRIPTOR = new IntegerProperty("maxfields", - "Max allowable fields", 1, 300, DEFAULT_MAXFIELDS, 1.0f); + private static final PropertyDescriptor MAX_FIELDS_DESCRIPTOR + = PropertyFactory.intProperty("maxfields") + .desc("Max allowable fields") + .defaultValue(DEFAULT_MAXFIELDS) + .require(positive()) + .build(); public TooManyFieldsRule() { definePropertyDescriptor(MAX_FIELDS_DESCRIPTOR); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/UselessOverridingMethodRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/UselessOverridingMethodRule.java index 87e2127a95..6759404307 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/UselessOverridingMethodRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/UselessOverridingMethodRule.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.lang.java.rule.design; +import static net.sourceforge.pmd.properties.PropertyFactory.booleanProperty; + import java.util.ArrayList; import java.util.List; @@ -29,7 +31,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTResultType; import net.sourceforge.pmd.lang.java.ast.ASTStatement; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; -import net.sourceforge.pmd.properties.BooleanProperty; +import net.sourceforge.pmd.properties.PropertyDescriptor; + /** * @author Romain Pelisse, bugfix for [ 1522517 ] False +: @@ -41,8 +44,10 @@ public class UselessOverridingMethodRule extends AbstractJavaRule { private static final String CLONE = "clone"; private static final String OBJECT = "Object"; - private static final BooleanProperty IGNORE_ANNOTATIONS_DESCRIPTOR = new BooleanProperty("ignoreAnnotations", - "Ignore annotations", false, 1.0f); + // TODO extend AbstractIgnoredAnnotationsRule node + // TODO ignore if there is javadoc + private static final PropertyDescriptor IGNORE_ANNOTATIONS_DESCRIPTOR = booleanProperty("ignoreAnnotations").defaultValue(false).desc("Ignore annotations").build(); + public UselessOverridingMethodRule() { definePropertyDescriptor(IGNORE_ANNOTATIONS_DESCRIPTOR); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentContentRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentContentRule.java index bdbbcf5576..23006ef1d6 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentContentRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentContentRule.java @@ -4,6 +4,9 @@ package net.sourceforge.pmd.lang.java.rule.documentation; +import static net.sourceforge.pmd.properties.PropertyFactory.booleanProperty; +import static net.sourceforge.pmd.properties.PropertyFactory.stringListProperty; + import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; @@ -17,10 +20,8 @@ import net.sourceforge.pmd.Rule; import net.sourceforge.pmd.RuleContext; import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; import net.sourceforge.pmd.lang.java.ast.Comment; -import net.sourceforge.pmd.properties.BooleanProperty; import net.sourceforge.pmd.properties.PropertyDescriptor; import net.sourceforge.pmd.properties.PropertySource; -import net.sourceforge.pmd.properties.StringMultiProperty; /** * A rule that checks for illegal words in the comment text. @@ -35,15 +36,13 @@ public class CommentContentRule extends AbstractCommentRule { private List originalBadWords; private List currentBadWords; - // FIXME need some better defaults (or none?) - private static final String[] BAD_WORDS = {"idiot", "jerk" }; - // ignored when property above == True - public static final BooleanProperty CASE_SENSITIVE_DESCRIPTOR = new BooleanProperty("caseSensitive", - "Case sensitive", false, 2.0f); + public static final PropertyDescriptor CASE_SENSITIVE_DESCRIPTOR = booleanProperty("caseSensitive").defaultValue(false).desc("Case sensitive").build(); - public static final StringMultiProperty DISSALLOWED_TERMS_DESCRIPTOR = new StringMultiProperty("disallowedTerms", - "Illegal terms or phrases", BAD_WORDS, 3.0f, '|'); + public static final PropertyDescriptor> DISSALLOWED_TERMS_DESCRIPTOR = + stringListProperty("disallowedTerms") + .desc("Illegal terms or phrases") + .defaultValues("idiot", "jerk").build(); // TODO make blank property? or add more defaults? private static final Set> NON_REGEX_PROPERTIES; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentRequiredRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentRequiredRule.java index 77b4870feb..56ab5c1e96 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentRequiredRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentRequiredRule.java @@ -23,8 +23,9 @@ import net.sourceforge.pmd.lang.java.ast.ASTName; import net.sourceforge.pmd.lang.java.ast.AbstractJavaAccessNode; import net.sourceforge.pmd.lang.java.ast.AbstractJavaNode; import net.sourceforge.pmd.lang.java.multifile.signature.JavaOperationSignature; -import net.sourceforge.pmd.properties.EnumeratedProperty; -import net.sourceforge.pmd.properties.EnumeratedProperty.EnumPBuilder; +import net.sourceforge.pmd.properties.PropertyBuilder.GenericPropertyBuilder; +import net.sourceforge.pmd.properties.PropertyDescriptor; +import net.sourceforge.pmd.properties.PropertyFactory; /** @@ -36,27 +37,25 @@ public class CommentRequiredRule extends AbstractCommentRule { private static final Map DESCRIPTOR_NAME_TO_COMMENT_TYPE = new HashMap<>(); - private static final EnumeratedProperty ACCESSOR_CMT_DESCRIPTOR + private static final PropertyDescriptor ACCESSOR_CMT_DESCRIPTOR = requirementPropertyBuilder("accessorCommentRequirement", "Comments on getters and setters\"") .defaultValue(CommentRequirement.Ignored).build(); - private static final EnumeratedProperty OVERRIDE_CMT_DESCRIPTOR + private static final PropertyDescriptor OVERRIDE_CMT_DESCRIPTOR = requirementPropertyBuilder("methodWithOverrideCommentRequirement", "Comments on @Override methods") .defaultValue(CommentRequirement.Ignored).build(); - private static final EnumeratedProperty HEADER_CMT_REQUIREMENT_DESCRIPTOR - = requirementPropertyBuilder("headerCommentRequirement", "Header comments").uiOrder(1.0f).build(); - private static final EnumeratedProperty FIELD_CMT_REQUIREMENT_DESCRIPTOR - = requirementPropertyBuilder("fieldCommentRequirement", "Field comments").uiOrder(2.0f).build(); - private static final EnumeratedProperty PUB_METHOD_CMT_REQUIREMENT_DESCRIPTOR - = requirementPropertyBuilder("publicMethodCommentRequirement", "Public method and constructor comments") - .uiOrder(3.0f).build(); - private static final EnumeratedProperty PROT_METHOD_CMT_REQUIREMENT_DESCRIPTOR - = requirementPropertyBuilder("protectedMethodCommentRequirement", "Protected method constructor comments") - .uiOrder(4.0f).build(); - private static final EnumeratedProperty ENUM_CMT_REQUIREMENT_DESCRIPTOR - = requirementPropertyBuilder("enumCommentRequirement", "Enum comments").uiOrder(5.0f).build(); - private static final EnumeratedProperty SERIAL_VERSION_UID_CMT_REQUIREMENT_DESCRIPTOR + private static final PropertyDescriptor HEADER_CMT_REQUIREMENT_DESCRIPTOR + = requirementPropertyBuilder("headerCommentRequirement", "Header comments").build(); + private static final PropertyDescriptor FIELD_CMT_REQUIREMENT_DESCRIPTOR + = requirementPropertyBuilder("fieldCommentRequirement", "Field comments").build(); + private static final PropertyDescriptor PUB_METHOD_CMT_REQUIREMENT_DESCRIPTOR + = requirementPropertyBuilder("publicMethodCommentRequirement", "Public method and constructor comments").build(); + private static final PropertyDescriptor PROT_METHOD_CMT_REQUIREMENT_DESCRIPTOR + = requirementPropertyBuilder("protectedMethodCommentRequirement", "Protected method constructor comments").build(); + private static final PropertyDescriptor ENUM_CMT_REQUIREMENT_DESCRIPTOR + = requirementPropertyBuilder("enumCommentRequirement", "Enum comments").build(); + private static final PropertyDescriptor SERIAL_VERSION_UID_CMT_REQUIREMENT_DESCRIPTOR = requirementPropertyBuilder("serialVersionUIDCommentRequired", "Serial version UID comments") - .defaultValue(CommentRequirement.Ignored).uiOrder(6.0f).build(); + .defaultValue(CommentRequirement.Ignored).build(); public CommentRequiredRule() { @@ -72,7 +71,7 @@ public class CommentRequiredRule extends AbstractCommentRule { private void checkCommentMeetsRequirement(Object data, AbstractJavaNode node, - EnumeratedProperty descriptor) { + PropertyDescriptor descriptor) { switch (getProperty(descriptor)) { case Ignored: break; @@ -94,7 +93,7 @@ public class CommentRequiredRule extends AbstractCommentRule { // Adds a violation private void commentRequiredViolation(Object data, AbstractJavaNode node, - EnumeratedProperty descriptor) { + PropertyDescriptor descriptor) { addViolationWithMessage(data, node, @@ -242,12 +241,10 @@ public class CommentRequiredRule extends AbstractCommentRule { // pre-filled builder - private static EnumPBuilder requirementPropertyBuilder(String name, String commentType) { + private static GenericPropertyBuilder requirementPropertyBuilder(String name, String commentType) { DESCRIPTOR_NAME_TO_COMMENT_TYPE.put(name, commentType); - return EnumeratedProperty.named(name) + return PropertyFactory.enumProperty(name, CommentRequirement.mappings()) .desc(commentType + ". Possible values: " + CommentRequirement.labels()) - .mappings(CommentRequirement.mappings()) - .defaultValue(CommentRequirement.Required) - .type(CommentRequirement.class); + .defaultValue(CommentRequirement.Required); } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentSizeRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentSizeRule.java index 4133699f0d..abf5672ada 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentSizeRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentSizeRule.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.lang.java.rule.documentation; +import static net.sourceforge.pmd.properties.constraints.NumericConstraints.positive; + import java.util.ArrayList; import java.util.List; @@ -11,7 +13,8 @@ import org.apache.commons.lang3.StringUtils; import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; import net.sourceforge.pmd.lang.java.ast.Comment; -import net.sourceforge.pmd.properties.IntegerProperty; +import net.sourceforge.pmd.properties.PropertyDescriptor; +import net.sourceforge.pmd.properties.PropertyFactory; import net.sourceforge.pmd.util.StringUtil; /** @@ -21,15 +24,15 @@ import net.sourceforge.pmd.util.StringUtil; */ public class CommentSizeRule extends AbstractCommentRule { - public static final IntegerProperty MAX_LINES - = IntegerProperty.named("maxLines") + public static final PropertyDescriptor MAX_LINES + = PropertyFactory.intProperty("maxLines") .desc("Maximum lines") - .range(2, 200).defaultValue(6).uiOrder(2.0f).build(); + .require(positive()).defaultValue(6).build(); - public static final IntegerProperty MAX_LINE_LENGTH - = IntegerProperty.named("maxLineLength") + public static final PropertyDescriptor MAX_LINE_LENGTH + = PropertyFactory.intProperty("maxLineLength") .desc("Maximum line length") - .range(1, 200).defaultValue(80).uiOrder(2.0f).build(); + .require(positive()).defaultValue(80).build(); private static final String CR = "\n"; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/documentation/HeaderCommentsRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/documentation/HeaderCommentsRule.java index 064e9c2f8a..c1a7acb12a 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/documentation/HeaderCommentsRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/documentation/HeaderCommentsRule.java @@ -15,6 +15,8 @@ import net.sourceforge.pmd.properties.StringMultiProperty; */ public class HeaderCommentsRule extends AbstractCommentRule { + // Rule is not used and not implemented, properties won't be converted + private static final String[] REQUIRED_WORKDS = new String[] { "copyright" }; private static final String[] REQUIRED_TAGS = new String[] { "author", "version" }; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/AssignmentInOperandRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/AssignmentInOperandRule.java index 783b1c7ced..35d4205cd3 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/AssignmentInOperandRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/AssignmentInOperandRule.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.lang.java.rule.errorprone; +import static net.sourceforge.pmd.properties.PropertyFactory.booleanProperty; + import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.java.ast.ASTAssignmentOperator; import net.sourceforge.pmd.lang.java.ast.ASTExpression; @@ -14,7 +16,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTPreDecrementExpression; import net.sourceforge.pmd.lang.java.ast.ASTPreIncrementExpression; import net.sourceforge.pmd.lang.java.ast.ASTWhileStatement; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; -import net.sourceforge.pmd.properties.BooleanProperty; +import net.sourceforge.pmd.properties.PropertyDescriptor; import net.sourceforge.pmd.properties.PropertySource; /** @@ -23,19 +25,26 @@ import net.sourceforge.pmd.properties.PropertySource; */ public class AssignmentInOperandRule extends AbstractJavaRule { - private static final BooleanProperty ALLOW_IF_DESCRIPTOR = new BooleanProperty("allowIf", - "Allow assignment within the conditional expression of an if statement", false, 1.0f); + private static final PropertyDescriptor ALLOW_IF_DESCRIPTOR = + booleanProperty("allowIf") + .desc("Allow assignment within the conditional expression of an if statement") + .defaultValue(false).build(); - private static final BooleanProperty ALLOW_FOR_DESCRIPTOR = new BooleanProperty("allowFor", - "Allow assignment within the conditional expression of a for statement", false, 2.0f); + private static final PropertyDescriptor ALLOW_FOR_DESCRIPTOR = + booleanProperty("allowFor") + .desc("Allow assignment within the conditional expression of a for statement") + .defaultValue(false).build(); - private static final BooleanProperty ALLOW_WHILE_DESCRIPTOR = new BooleanProperty("allowWhile", - "Allow assignment within the conditional expression of a while statement", false, 3.0f); + private static final PropertyDescriptor ALLOW_WHILE_DESCRIPTOR = + booleanProperty("allowWhile") + .desc("Allow assignment within the conditional expression of a while statement") + .defaultValue(false).build(); + + private static final PropertyDescriptor ALLOW_INCREMENT_DECREMENT_DESCRIPTOR = + booleanProperty("allowIncrementDecrement") + .desc("Allow increment or decrement operators within the conditional expression of an if, for, or while statement") + .defaultValue(false).build(); - private static final BooleanProperty ALLOW_INCREMENT_DECREMENT_DESCRIPTOR = new BooleanProperty( - "allowIncrementDecrement", - "Allow increment or decrement operators within the conditional expression of an if, for, or while statement", - false, 4.0f); public AssignmentInOperandRule() { definePropertyDescriptor(ALLOW_IF_DESCRIPTOR); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/AvoidBranchingStatementAsLastInLoopRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/AvoidBranchingStatementAsLastInLoopRule.java index 4a897421bc..b7348aa26f 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/AvoidBranchingStatementAsLastInLoopRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/AvoidBranchingStatementAsLastInLoopRule.java @@ -10,6 +10,8 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import org.apache.commons.lang3.StringUtils; + import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.java.ast.ASTBreakStatement; import net.sourceforge.pmd.lang.java.ast.ASTContinueStatement; @@ -19,7 +21,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTReturnStatement; import net.sourceforge.pmd.lang.java.ast.ASTSwitchStatement; import net.sourceforge.pmd.lang.java.ast.ASTWhileStatement; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; -import net.sourceforge.pmd.properties.EnumeratedMultiProperty; +import net.sourceforge.pmd.properties.PropertyDescriptor; +import net.sourceforge.pmd.properties.PropertyFactory; import net.sourceforge.pmd.properties.PropertySource; public class AvoidBranchingStatementAsLastInLoopRule extends AbstractJavaRule { @@ -39,15 +42,14 @@ public class AvoidBranchingStatementAsLastInLoopRule extends AbstractJavaRule { LOOP_TYPES_MAPPINGS = Collections.unmodifiableMap(mappings); } - public static final EnumeratedMultiProperty CHECK_BREAK_LOOP_TYPES = new EnumeratedMultiProperty<>( - "checkBreakLoopTypes", "Check for break statements in loop types", LOOP_TYPES_MAPPINGS, DEFAULTS, - String.class, 1); - public static final EnumeratedMultiProperty CHECK_CONTINUE_LOOP_TYPES = new EnumeratedMultiProperty<>( - "checkContinueLoopTypes", "Check for continue statements in loop types", LOOP_TYPES_MAPPINGS, DEFAULTS, - String.class, 2); - public static final EnumeratedMultiProperty CHECK_RETURN_LOOP_TYPES = new EnumeratedMultiProperty<>( - "checkReturnLoopTypes", "Check for return statements in loop types", LOOP_TYPES_MAPPINGS, DEFAULTS, - String.class, 3); + // TODO I don't think we need this configurability. + // I think we should tone that down to just be able to ignore some type of statement, + // but I can't see a use case to e.g. report only breaks in 'for' loops but not in 'while'. + + public static final PropertyDescriptor> CHECK_BREAK_LOOP_TYPES = propertyFor("break"); + public static final PropertyDescriptor> CHECK_CONTINUE_LOOP_TYPES = propertyFor("continue"); + public static final PropertyDescriptor> CHECK_RETURN_LOOP_TYPES = propertyFor("return"); + public AvoidBranchingStatementAsLastInLoopRule() { @@ -71,7 +73,7 @@ public class AvoidBranchingStatementAsLastInLoopRule extends AbstractJavaRule { } - protected Object check(EnumeratedMultiProperty property, Node node, Object data) { + protected Object check(PropertyDescriptor> property, Node node, Object data) { Node parent = node.getNthParent(5); if (parent instanceof ASTForStatement) { if (hasPropertyValue(property, CHECK_FOR)) { @@ -90,7 +92,7 @@ public class AvoidBranchingStatementAsLastInLoopRule extends AbstractJavaRule { } - protected boolean hasPropertyValue(EnumeratedMultiProperty property, String value) { + protected boolean hasPropertyValue(PropertyDescriptor> property, String value) { return getProperty(property).contains(value); } @@ -115,6 +117,12 @@ public class AvoidBranchingStatementAsLastInLoopRule extends AbstractJavaRule { return checksNothing() ? "All loop types are ignored" : null; } + private static PropertyDescriptor> propertyFor(String stmtName) { + return PropertyFactory.enumListProperty("check" + StringUtils.capitalize(stmtName) + "LoopTypes", LOOP_TYPES_MAPPINGS) + .desc("List of loop types in which " + stmtName + " statements will be checked") + .defaultValue(DEFAULTS) + .build(); + } public boolean checksNothing() { diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/AvoidDuplicateLiteralsRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/AvoidDuplicateLiteralsRule.java index e395d0e501..4deab3d85a 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/AvoidDuplicateLiteralsRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/AvoidDuplicateLiteralsRule.java @@ -4,6 +4,9 @@ package net.sourceforge.pmd.lang.java.rule.errorprone; +import static net.sourceforge.pmd.properties.PropertyFactory.booleanProperty; +import static net.sourceforge.pmd.properties.constraints.NumericConstraints.positive; + import java.io.File; import java.io.IOException; import java.io.LineNumberReader; @@ -15,6 +18,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.logging.Logger; import org.apache.commons.lang3.StringUtils; @@ -22,36 +26,56 @@ import net.sourceforge.pmd.lang.java.ast.ASTAnnotation; import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; import net.sourceforge.pmd.lang.java.ast.ASTLiteral; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; -import net.sourceforge.pmd.properties.BooleanProperty; import net.sourceforge.pmd.properties.CharacterProperty; import net.sourceforge.pmd.properties.FileProperty; -import net.sourceforge.pmd.properties.IntegerProperty; +import net.sourceforge.pmd.properties.PropertyDescriptor; +import net.sourceforge.pmd.properties.PropertyFactory; import net.sourceforge.pmd.properties.PropertySource; import net.sourceforge.pmd.properties.StringProperty; + public class AvoidDuplicateLiteralsRule extends AbstractJavaRule { + private static final Logger LOG = Logger.getLogger(AvoidDuplicateLiteralsRule.class.getName()); - public static final IntegerProperty THRESHOLD_DESCRIPTOR - = IntegerProperty.named("maxDuplicateLiterals") + public static final PropertyDescriptor THRESHOLD_DESCRIPTOR + = PropertyFactory.intProperty("maxDuplicateLiterals") .desc("Max duplicate literals") - .range(1, 20).defaultValue(4).uiOrder(1.0f).build(); + .require(positive()).defaultValue(4).build(); - public static final IntegerProperty MINIMUM_LENGTH_DESCRIPTOR = new IntegerProperty("minimumLength", - "Minimum string length to check", 1, Integer.MAX_VALUE, 3, 1.5f); + public static final PropertyDescriptor MINIMUM_LENGTH_DESCRIPTOR = PropertyFactory.intProperty("minimumLength").desc("Minimum string length to check").require(positive()).defaultValue(3).build(); - public static final BooleanProperty SKIP_ANNOTATIONS_DESCRIPTOR = new BooleanProperty("skipAnnotations", - "Skip literals within annotations", false, 2.0f); + public static final PropertyDescriptor SKIP_ANNOTATIONS_DESCRIPTOR = + booleanProperty("skipAnnotations") + .desc("Skip literals within annotations").defaultValue(false).build(); - public static final StringProperty EXCEPTION_LIST_DESCRIPTOR = new StringProperty("exceptionList", - "Strings to ignore", null, 3.0f); + // This set of properties is impossible to convert to the new framework before 7.0.0 + // It looks like it tried to implement itself delimiter escaping and such, which we + // can't emulate without significant effort (wasted effort, bc delimiters will anyway + // be scrapped). + // TODO 7.0.0: + // EXCEPTION_LIST_DESCRIPTOR -> PropertyDescriptor> + // delete SEPARATOR_DESCRIPTOR, EXCEPTION_FILE_DESCRIPTOR + // Try hard to convert the properties to the seq syntax, using the separator descriptor + + // TODO We use the old builders here, bc of the null default value + public static final StringProperty EXCEPTION_LIST_DESCRIPTOR + = StringProperty.named("exceptionList") + .desc("List of literals to ignore. " + + "A literal is ignored if its image can be found in this list. " + + "Components of this list should not be surrounded by double quotes.") + .defaultValue(null) + .build(); public static final CharacterProperty SEPARATOR_DESCRIPTOR = new CharacterProperty("separator", "Ignore list separator", ',', 4.0f); + @Deprecated public static final FileProperty EXCEPTION_FILE_DESCRIPTOR = new FileProperty("exceptionfile", - "File containing strings to skip (one string per line), only used if ignore list is not set. " + "deprecated!(Use 'exceptionList' property) File containing strings to skip (one string per line), only used if ignore list is not set. " + "File must be UTF-8 encoded.", null, 5.0f); + /** @deprecated This ad-hoc solution will be integrated into the global properties framework somehow */ + @Deprecated public static class ExceptionParser { private static final char ESCAPE_CHAR = '\\'; @@ -112,10 +136,18 @@ public class AvoidDuplicateLiteralsRule extends AbstractJavaRule { literals.clear(); if (getProperty(EXCEPTION_LIST_DESCRIPTOR) != null) { + if (isPropertyOverridden(SEPARATOR_DESCRIPTOR)) { + LOG.warning("Rule AvoidDuplicateLiterals uses deprecated property 'separator'. " + + "Future versions of PMD will remove support for this property. " + + "Please use the default separator (',') and avoid setting this property instead."); + } ExceptionParser p = new ExceptionParser(getProperty(SEPARATOR_DESCRIPTOR)); exceptions = p.parse(getProperty(EXCEPTION_LIST_DESCRIPTOR)); } else if (getProperty(EXCEPTION_FILE_DESCRIPTOR) != null) { exceptions = new HashSet<>(); + LOG.warning("Rule AvoidDuplicateLiterals uses deprecated property 'exceptionFile'. " + + "Future versions of PMD will remove support for this property. " + + "Please use 'exceptionList' instead."); try (LineNumberReader reader = getLineReader()) { String line; while ((line = reader.readLine()) != null) { @@ -144,8 +176,7 @@ public class AvoidDuplicateLiteralsRule extends AbstractJavaRule { if (occurrences.size() >= threshold) { ASTLiteral first = occurrences.get(0); String rawImage = first.getEscapedStringLiteral(); - Object[] args = new Object[] { rawImage, Integer.valueOf(occurrences.size()), - Integer.valueOf(first.getBeginLine()), }; + Object[] args = {rawImage, occurrences.size(), first.getBeginLine(), }; addViolation(data, first, args); } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/AvoidUsingOctalValuesRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/AvoidUsingOctalValuesRule.java index d4c2fd551c..c91705bfe2 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/AvoidUsingOctalValuesRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/AvoidUsingOctalValuesRule.java @@ -4,11 +4,14 @@ package net.sourceforge.pmd.lang.java.rule.errorprone; +import static net.sourceforge.pmd.properties.PropertyFactory.booleanProperty; + import java.util.regex.Pattern; import net.sourceforge.pmd.lang.java.ast.ASTLiteral; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; -import net.sourceforge.pmd.properties.BooleanProperty; +import net.sourceforge.pmd.properties.PropertyDescriptor; + public class AvoidUsingOctalValuesRule extends AbstractJavaRule { @@ -16,10 +19,10 @@ public class AvoidUsingOctalValuesRule extends AbstractJavaRule { public static final Pattern STRICT_OCTAL_PATTERN = Pattern.compile("0[0-7]+[lL]?"); - private static final BooleanProperty STRICT_METHODS_DESCRIPTOR = BooleanProperty.named("strict") + private static final PropertyDescriptor STRICT_METHODS_DESCRIPTOR = booleanProperty("strict") .desc("Detect violations between 00 and 07") .defaultValue(false) - .uiOrder(1.0f).build(); + .build(); public AvoidUsingOctalValuesRule() { diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/BeanMembersShouldSerializeRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/BeanMembersShouldSerializeRule.java index cf2785145e..b36674a30e 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/BeanMembersShouldSerializeRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/BeanMembersShouldSerializeRule.java @@ -4,12 +4,15 @@ package net.sourceforge.pmd.lang.java.rule.errorprone; +import static net.sourceforge.pmd.properties.PropertyFactory.stringProperty; + import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.Locale; import java.util.Map; +import org.apache.commons.lang3.StringUtils; + import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; @@ -23,14 +26,14 @@ import net.sourceforge.pmd.lang.java.symboltable.ClassScope; import net.sourceforge.pmd.lang.java.symboltable.MethodNameDeclaration; import net.sourceforge.pmd.lang.java.symboltable.VariableNameDeclaration; import net.sourceforge.pmd.lang.symboltable.NameOccurrence; -import net.sourceforge.pmd.properties.StringProperty; +import net.sourceforge.pmd.properties.PropertyDescriptor; public class BeanMembersShouldSerializeRule extends AbstractJavaRule { private String prefixProperty; - private static final StringProperty PREFIX_DESCRIPTOR = new StringProperty("prefix", - "A variable prefix to skip, i.e., m_", "", 1.0f); + private static final PropertyDescriptor PREFIX_DESCRIPTOR = stringProperty("prefix").desc("A variable prefix to skip, i.e., m_").defaultValue("").build(); + public BeanMembersShouldSerializeRule() { definePropertyDescriptor(PREFIX_DESCRIPTOR); @@ -81,8 +84,7 @@ public class BeanMembersShouldSerializeRule extends AbstractJavaRule { if (entry.getValue().isEmpty() || accessNodeParent.isTransient() || accessNodeParent.isStatic()) { continue; } - String varName = trimIfPrefix(decl.getImage()); - varName = varName.substring(0, 1).toUpperCase(Locale.ROOT) + varName.substring(1, varName.length()); + String varName = StringUtils.capitalize(trimIfPrefix(decl.getImage())); boolean hasGetMethod = Arrays.binarySearch(methNameArray, "get" + varName) >= 0 || Arrays.binarySearch(methNameArray, "is" + varName) >= 0; boolean hasSetMethod = Arrays.binarySearch(methNameArray, "set" + varName) >= 0; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/CloseResourceRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/CloseResourceRule.java index 8fc6b8a1bb..2febbcd39f 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/CloseResourceRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/CloseResourceRule.java @@ -4,6 +4,9 @@ package net.sourceforge.pmd.lang.java.rule.errorprone; +import static net.sourceforge.pmd.properties.PropertyFactory.booleanProperty; +import static net.sourceforge.pmd.properties.PropertyFactory.stringListProperty; + import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -33,13 +36,12 @@ import net.sourceforge.pmd.lang.java.ast.ASTType; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; import net.sourceforge.pmd.lang.java.ast.ASTVariableInitializer; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; -import net.sourceforge.pmd.properties.BooleanProperty; -import net.sourceforge.pmd.properties.StringMultiProperty; +import net.sourceforge.pmd.properties.PropertyDescriptor; /** * Makes sure you close your database connections. It does this by looking for * code patterned like this: - * + * *
  *  Connection c = X;
  *  try {
@@ -48,7 +50,7 @@ import net.sourceforge.pmd.properties.StringMultiProperty;
  *   c.close();
  *  }
  * 
- * + * * @author original author unknown * @author Contribution from Pierre Mathien */ @@ -58,14 +60,22 @@ public class CloseResourceRule extends AbstractJavaRule { private Set simpleTypes = new HashSet<>(); private Set closeTargets = new HashSet<>(); - private static final StringMultiProperty CLOSE_TARGETS_DESCRIPTOR = new StringMultiProperty("closeTargets", - "Methods which may close this resource", new String[] {}, 1.0f, ','); + private static final PropertyDescriptor> CLOSE_TARGETS_DESCRIPTOR = + stringListProperty("closeTargets") + .desc("Methods which may close this resource") + .emptyDefaultValue() + .delim(',').build(); - private static final StringMultiProperty TYPES_DESCRIPTOR = new StringMultiProperty("types", "Affected types", - new String[] { "java.sql.Connection", "java.sql.Statement", "java.sql.ResultSet" }, 2.0f, ','); + private static final PropertyDescriptor> TYPES_DESCRIPTOR = + stringListProperty("types") + .desc("Affected types") + .defaultValues("java.sql.Connection", "java.sql.Statement", "java.sql.ResultSet") + .delim(',').build(); + + private static final PropertyDescriptor USE_CLOSE_AS_DEFAULT_TARGET = + booleanProperty("closeAsDefaultTarget") + .desc("Consider 'close' as a target by default").defaultValue(true).build(); - private static final BooleanProperty USE_CLOSE_AS_DEFAULT_TARGET = new BooleanProperty("closeAsDefaultTarget", - "Consider 'close' as a target by default", true, 3.0f); public CloseResourceRule() { definePropertyDescriptor(CLOSE_TARGETS_DESCRIPTOR); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/DataflowAnomalyAnalysisRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/DataflowAnomalyAnalysisRule.java index ab529036a7..bd70eddb4e 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/DataflowAnomalyAnalysisRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/DataflowAnomalyAnalysisRule.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.lang.java.rule.errorprone; +import static net.sourceforge.pmd.properties.constraints.NumericConstraints.inRange; + import java.text.MessageFormat; import java.util.ArrayList; import java.util.HashMap; @@ -20,7 +22,9 @@ import net.sourceforge.pmd.lang.dfa.pathfinder.Executable; import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; -import net.sourceforge.pmd.properties.IntegerProperty; +import net.sourceforge.pmd.properties.PropertyDescriptor; +import net.sourceforge.pmd.properties.PropertyFactory; + /** * Starts path search for each method and runs code if found. @@ -29,18 +33,18 @@ import net.sourceforge.pmd.properties.IntegerProperty; * @author Sven Jacob */ public class DataflowAnomalyAnalysisRule extends AbstractJavaRule implements Executable { - private static final IntegerProperty MAX_PATH_DESCRIPTOR - = IntegerProperty.named("maxPaths") + private static final PropertyDescriptor MAX_PATH_DESCRIPTOR + = PropertyFactory.intProperty("maxPaths") .desc("Maximum number of checked paths per method. A lower value will increase the performance of the rule but may decrease anomalies found.") - .range(100, 8000) + .require(inRange(100, 8000)) .defaultValue(1000) - .uiOrder(1.0f).build(); - private static final IntegerProperty MAX_VIOLATIONS_DESCRIPTOR - = IntegerProperty.named("maxViolations") + .build(); + private static final PropertyDescriptor MAX_VIOLATIONS_DESCRIPTOR + = PropertyFactory.intProperty("maxViolations") .desc("Maximum number of anomalies per class") - .range(1, 2000) + .require(inRange(1, 2000)) .defaultValue(100) - .uiOrder(2.0f).build(); + .build(); private RuleContext rc; private List daaRuleViolations; private int maxRuleViolations; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/InvalidSlf4jMessageFormatRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/InvalidSlf4jMessageFormatRule.java index 0a5e1402c4..f7cd1683e4 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/InvalidSlf4jMessageFormatRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/InvalidSlf4jMessageFormatRule.java @@ -22,6 +22,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceBody; import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType; import net.sourceforge.pmd.lang.java.ast.ASTExpression; import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTInitializer; +import net.sourceforge.pmd.lang.java.ast.ASTLambdaExpression; import net.sourceforge.pmd.lang.java.ast.ASTLiteral; import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTName; @@ -31,6 +33,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTPrimarySuffix; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclarator; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; import net.sourceforge.pmd.lang.java.ast.ASTVariableInitializer; +import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; import net.sourceforge.pmd.lang.java.symboltable.VariableNameDeclaration; import net.sourceforge.pmd.lang.java.typeresolution.TypeHelper; @@ -163,11 +166,12 @@ public class InvalidSlf4jMessageFormatRule extends AbstractJavaRule { count = countPlaceholders(node); } else if (node.getFirstDescendantOfType(ASTName.class) != null) { final String variableName = node.getFirstDescendantOfType(ASTName.class).getImage(); - // look if the message is defined locally - final List localVariables = node - .getFirstParentOfType(ASTMethodOrConstructorDeclaration.class) - .findDescendantsOfType(ASTVariableDeclarator.class); - count = getAmountOfExpectedArguments(variableName, localVariables); + // look if the message is defined locally in a method/constructor, initializer block or lambda expression + final JavaNode parentBlock = node.getFirstParentOfAnyType(ASTMethodOrConstructorDeclaration.class, ASTInitializer.class, ASTLambdaExpression.class); + if (parentBlock != null) { + final List localVariables = parentBlock.findDescendantsOfType(ASTVariableDeclarator.class); + count = getAmountOfExpectedArguments(variableName, localVariables); + } if (count == 0) { // look if the message is defined in a field diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/multithreading/NonThreadSafeSingletonRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/multithreading/NonThreadSafeSingletonRule.java index 990e8b96b9..492f41bdd9 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/multithreading/NonThreadSafeSingletonRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/multithreading/NonThreadSafeSingletonRule.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.lang.java.rule.multithreading; +import static net.sourceforge.pmd.properties.PropertyFactory.booleanProperty; + import java.util.HashMap; import java.util.List; import java.util.Map; @@ -21,7 +23,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTPrimarySuffix; import net.sourceforge.pmd.lang.java.ast.ASTStatementExpression; import net.sourceforge.pmd.lang.java.ast.ASTSynchronizedStatement; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; -import net.sourceforge.pmd.properties.BooleanProperty; +import net.sourceforge.pmd.properties.PropertyDescriptor; + public class NonThreadSafeSingletonRule extends AbstractJavaRule { @@ -30,12 +33,15 @@ public class NonThreadSafeSingletonRule extends AbstractJavaRule { private boolean checkNonStaticMethods = true; private boolean checkNonStaticFields = true; - private static final BooleanProperty CHECK_NON_STATIC_METHODS_DESCRIPTOR = new BooleanProperty( - "checkNonStaticMethods", - "Check for non-static methods. Do not set this to false and checkNonStaticFields to true.", true, 1.0f); - private static final BooleanProperty CHECK_NON_STATIC_FIELDS_DESCRIPTOR = new BooleanProperty( - "checkNonStaticFields", - "Check for non-static fields. Do not set this to true and checkNonStaticMethods to false.", false, 2.0f); + private static final PropertyDescriptor CHECK_NON_STATIC_METHODS_DESCRIPTOR = + booleanProperty("checkNonStaticMethods") + .desc("Check for non-static methods. Do not set this to false and checkNonStaticFields to true.") + .defaultValue(true).build(); + private static final PropertyDescriptor CHECK_NON_STATIC_FIELDS_DESCRIPTOR = + booleanProperty("checkNonStaticFields") + .desc("Check for non-static fields. Do not set this to true and checkNonStaticMethods to false.") + .defaultValue(false).build(); + public NonThreadSafeSingletonRule() { definePropertyDescriptor(CHECK_NON_STATIC_METHODS_DESCRIPTOR); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/ConsecutiveLiteralAppendsRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/ConsecutiveLiteralAppendsRule.java index f4f328e616..17378c54bf 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/ConsecutiveLiteralAppendsRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/ConsecutiveLiteralAppendsRule.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.lang.java.rule.performance; +import static net.sourceforge.pmd.properties.constraints.NumericConstraints.inRange; + import java.util.Collections; import java.util.HashSet; import java.util.List; @@ -33,7 +35,9 @@ import net.sourceforge.pmd.lang.java.symboltable.JavaNameOccurrence; import net.sourceforge.pmd.lang.java.symboltable.VariableNameDeclaration; import net.sourceforge.pmd.lang.java.typeresolution.TypeHelper; import net.sourceforge.pmd.lang.symboltable.NameOccurrence; -import net.sourceforge.pmd.properties.IntegerProperty; +import net.sourceforge.pmd.properties.PropertyDescriptor; +import net.sourceforge.pmd.properties.PropertyFactory; + /** * This rule finds concurrent calls to StringBuffer/Builder.append where String @@ -72,10 +76,10 @@ public class ConsecutiveLiteralAppendsRule extends AbstractJavaRule { BLOCK_PARENTS.add(ASTMethodDeclaration.class); } - private static final IntegerProperty THRESHOLD_DESCRIPTOR - = IntegerProperty.named("threshold") + private static final PropertyDescriptor THRESHOLD_DESCRIPTOR + = PropertyFactory.intProperty("threshold") .desc("Max consecutive appends") - .range(1, 10).defaultValue(1).uiOrder(1.0f).build(); + .require(inRange(1, 10)).defaultValue(1).build(); private int threshold = 1; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/visitors/PMDASMVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/visitors/PMDASMVisitor.java index dce2ae802c..b9554f875a 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/visitors/PMDASMVisitor.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/visitors/PMDASMVisitor.java @@ -36,7 +36,7 @@ public class PMDASMVisitor extends ClassVisitor { public List innerClasses; public PMDASMVisitor(String outerName) { - super(Opcodes.ASM7_EXPERIMENTAL); + super(Opcodes.ASM7); this.outerName = outerName; } diff --git a/pmd-java/src/main/resources/category/java/bestpractices.xml b/pmd-java/src/main/resources/category/java/bestpractices.xml index 682293ffce..9e8ab6336f 100644 --- a/pmd-java/src/main/resources/category/java/bestpractices.xml +++ b/pmd-java/src/main/resources/category/java/bestpractices.xml @@ -812,6 +812,7 @@ can lead to quite messy code. This rule looks for several declarations on the sa 1] [$strictMode or count(distinct-values(VariableDeclarator/@BeginLine)) != count(VariableDeclarator)] | diff --git a/pmd-java/src/main/resources/category/java/design.xml b/pmd-java/src/main/resources/category/java/design.xml index 414bde44d8..476f1b5a23 100644 --- a/pmd-java/src/main/resources/category/java/design.xml +++ b/pmd-java/src/main/resources/category/java/design.xml @@ -737,7 +737,7 @@ of Object-Oriented Systems. Springer, Berlin, 1 edition, October 2006. Page 80. class="net.sourceforge.pmd.lang.java.rule.design.ImmutableFieldRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_design.html#immutablefield"> -Identifies private fields whose values never change once they are initialized either in the declaration +Identifies private fields whose values never change once object initialization ends either in the declaration of the field or by a constructor. This helps in converting existing classes to becoming immutable ones. 3 diff --git a/pmd-java/src/main/resources/category/java/errorprone.xml b/pmd-java/src/main/resources/category/java/errorprone.xml index 93930f8694..bad84763b5 100644 --- a/pmd-java/src/main/resources/category/java/errorprone.xml +++ b/pmd-java/src/main/resources/category/java/errorprone.xml @@ -2666,8 +2666,9 @@ Avoid returning from a finally block, this can discard exceptions. 3 + - //FinallyStatement//ReturnStatement + //FinallyStatement//ReturnStatement except //FinallyStatement//(MethodDeclaration|LambdaExpression)//ReturnStatement diff --git a/pmd-java/src/main/resources/category/java/performance.xml b/pmd-java/src/main/resources/category/java/performance.xml index 50db25bd81..49caa5120b 100644 --- a/pmd-java/src/main/resources/category/java/performance.xml +++ b/pmd-java/src/main/resources/category/java/performance.xml @@ -120,14 +120,22 @@ public class Test { class="net.sourceforge.pmd.lang.rule.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_performance.html#avoidfilestream"> -The FileInputStream and FileOutputStream classes contains a finalizer method which will cause garbage collection pauses. See [JDK-8080225](https://bugs.openjdk.java.net/browse/JDK-8080225) for details. +The FileInputStream and FileOutputStream classes contains a finalizer method which will cause garbage +collection pauses. +See [JDK-8080225](https://bugs.openjdk.java.net/browse/JDK-8080225) for details. -The FileReader and FileWriter constructors instantiate FileInputStream and FileOutputStream, again causing garbage collection issues while finalizer methods are called. +The FileReader and FileWriter constructors instantiate FileInputStream and FileOutputStream, +again causing garbage collection issues while finalizer methods are called. * Use `Files.newInputStream(Paths.get(fileName))` instead of `new FileInputStream(fileName)`. * Use `Files.newOutputStream(Paths.get(fileName))` instead of `new FileOutputStream(fileName)`. * Use `Files.newBufferedReader(Paths.get(fileName))` instead of `new FileReader(fileName)`. * Use `Files.newBufferedWriter(Paths.get(fileName))` instead of `new FileWriter(fileName)`. + +Please note, that the `java.nio` API does not throw a `FileNotFoundException` anymore, instead +it throws a `NoSuchFileException`. If your code dealt explicitly with a `FileNotFoundException`, +then this needs to be adjusted. Both exceptions are subclasses of `IOException`, so catching +that one covers both. 1 diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/AbstractMetricTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/AbstractMetricTestRule.java index bf24029644..afd8f068fa 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/AbstractMetricTestRule.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/AbstractMetricTestRule.java @@ -4,8 +4,8 @@ package net.sourceforge.pmd.lang.java.metrics.impl; -import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Locale; import java.util.Map; @@ -19,9 +19,9 @@ import net.sourceforge.pmd.lang.java.rule.AbstractJavaMetricsRule; import net.sourceforge.pmd.lang.metrics.MetricOption; import net.sourceforge.pmd.lang.metrics.MetricOptions; import net.sourceforge.pmd.lang.metrics.ResultOption; -import net.sourceforge.pmd.properties.BooleanProperty; -import net.sourceforge.pmd.properties.DoubleProperty; -import net.sourceforge.pmd.properties.EnumeratedMultiProperty; +import net.sourceforge.pmd.properties.PropertyDescriptor; +import net.sourceforge.pmd.properties.PropertyFactory; + /** * Abstract test rule for a metric. Tests of metrics use the standard framework for rule testing, using one dummy rule @@ -31,15 +31,26 @@ import net.sourceforge.pmd.properties.EnumeratedMultiProperty; */ public abstract class AbstractMetricTestRule extends AbstractJavaMetricsRule { - private final EnumeratedMultiProperty optionsDescriptor = new EnumeratedMultiProperty<>( - "metricOptions", "Choose a variant of the metric or the standard", - optionMappings(), Collections.emptyList(), MetricOption.class, 3.0f); - private final BooleanProperty reportClassesDescriptor = new BooleanProperty( - "reportClasses", "Add class violations to the report", isReportClasses(), 2.0f); - private final BooleanProperty reportMethodsDescriptor = new BooleanProperty( - "reportMethods", "Add method violations to the report", isReportMethods(), 3.0f); - private final DoubleProperty reportLevelDescriptor = new DoubleProperty( - "reportLevel", "Minimum value required to report", -1., Double.POSITIVE_INFINITY, defaultReportLevel(), 3.0f); + + private final PropertyDescriptor> optionsDescriptor = + PropertyFactory.enumListProperty("metricOptions", optionMappings()) + .desc("Choose a variant of the metric or the standard") + .emptyDefaultValue().build(); + + private final PropertyDescriptor reportClassesDescriptor = + PropertyFactory.booleanProperty("reportClasses") + .desc("Add class violations to the report") + .defaultValue(isReportClasses()).build(); + + private final PropertyDescriptor reportMethodsDescriptor = + PropertyFactory.booleanProperty("reportMethods") + .desc("Add method violations to the report") + .defaultValue(isReportMethods()).build(); + + private final PropertyDescriptor reportLevelDescriptor = + PropertyFactory.doubleProperty("reportLevel") + .desc("Minimum value required to report") + .defaultValue(defaultReportLevel()).build(); private MetricOptions metricOptions; private boolean reportClasses; diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/CycloTest.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/CycloTest.xml index 2a68e58e1c..0c8bb836ba 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/CycloTest.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/CycloTest.xml @@ -394,4 +394,27 @@ + + + + + + + + The guard of a ForStatement should be counted correctly (spotted #1437) + 1 + + 'Foo#compareImports(String, String)' has value 3. + + + + + diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NcssTest.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NcssTest.xml index 4a9bae7fac..96602c9e8e 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NcssTest.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NcssTest.xml @@ -417,4 +417,47 @@ + + + Lambdas themselves don't count, only the code within + 2 + + 'Koo#bar()' has value 2. + 'Koo#lambda$bar$0' has value 0. + + + i = i -> { + + }; + } + } + ]]> + + + + + Code inside lambdas is counted by default + 2 + + 'Koo#bar()' has value 4. + 'Koo#lambda$bar$0' has value 2. + + + i = i -> { + int j = 0; + j = i; + }; + } + } + ]]> + + + + diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/WmcTest.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/WmcTest.xml index 03fcd25790..62c64996c2 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/WmcTest.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/WmcTest.xml @@ -125,4 +125,32 @@ + + + + + + Classes should not factor in the complexity of nested classes + 2 + + 'Outer' has value 1. + 'Outer$Inner' has value 1. + + + + \ No newline at end of file diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/JUnitTestsShouldIncludeAssert.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/JUnitTestsShouldIncludeAssert.xml index c375a11924..b59f2caf25 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/JUnitTestsShouldIncludeAssert.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/JUnitTestsShouldIncludeAssert.xml @@ -494,6 +494,22 @@ public class FooTest { void testFoo() { softly.assertThat("doesn't matter").isEqualTo("doesn't matter"); } +}]]> + + + #647 JUnitTestsShouldIncludeAssertRule should support `this.exception` as well as just `exception` + 0 + diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/OneDeclarationPerLine.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/OneDeclarationPerLine.xml index 39768c6233..fe3c8d30c5 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/OneDeclarationPerLine.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/OneDeclarationPerLine.xml @@ -86,6 +86,19 @@ public class Foo { public class Foo { String name, lastname; +} + ]]> + + + + Don't report multiple variables in a for statement, see #658 + 0 + diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/LocalVariableCouldBeFinal.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/LocalVariableCouldBeFinal.xml index 37db064a4b..055e2ba1ee 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/LocalVariableCouldBeFinal.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/LocalVariableCouldBeFinal.xml @@ -4,9 +4,7 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests http://pmd.sourceforge.net/rule-tests_1_0_0.xsd"> - + TEST1 1 - + TEST2 0 - + TEST3 0 - + TEST4 0 - + TEST5 2 - + TEST6 0 - + TEST7 0 - + TEST8 0 - + TEST9 1 - + Bug 2614040 : false + if a += assignment operator is used inside a method call. 0 + + Parameter to ignore non-final variables in for each loops (see #1513). + true + 0 + + + + By default, for-each loops should be flagged (see #1513). + 1 + 3 + + + + Normal for-loops should not be flagged + 0 + + diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/InvalidSlf4jMessageFormat.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/InvalidSlf4jMessageFormat.xml index 0cbc4296a5..994de283ab 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/InvalidSlf4jMessageFormat.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/InvalidSlf4jMessageFormat.xml @@ -269,4 +269,70 @@ public final class Main { } ]]> + + + NPE in static block (see #1512) + 0 + + + + + missing argument in static block + 1 + 8 + + + + + NPE in lambda call (see #1512) + 0 + list = someMethod(message -> logger.info(message)); + } + ]]> + + + + missing argument in lambda call + 1 + 9 + list = someMethod(message -> { + final String pattern = "log: {}"; + + logger.info(pattern, 1, 2); + }); + } + ]]> + \ No newline at end of file diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/ReturnFromFinallyBlock.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/ReturnFromFinallyBlock.xml index 6a0c3a8795..29eb774bb7 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/ReturnFromFinallyBlock.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/ReturnFromFinallyBlock.xml @@ -4,9 +4,7 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests http://pmd.sourceforge.net/rule-tests_1_0_0.xsd"> - + throw exception but return from finally 1 - + lots of returns 1 - + ok 0 + + #1035 [java] ReturnFromFinallyBlock: False positive on lambda expression in finally block + 0 + + + + Return from Lambda in Finally + 0 + untracked = serviceExecutionTracker.untrackMatchingEntries(e -> { + ServiceExecutionIdentifiers ids = e.getIdentifiers(); + Long execBqiId = (ids == null) ? null : ids.getBqiId(); + return Objects.equals(bqiId, execBqiId); + }); + untracked.forEach(e -> logger.info("overwriteLastBqi(bqId={}, bqiId={}) untracked {}", bqId, bqiId, e)); + } + } +} + ]]> + + + return from a lambda should not cause issues + 0 + { return i + 1; }).forEach(i -> System.out.println(i)); + } + } +} + ]]> + + + Return in finally should give error but not in lambda + 1 + { return i + 1; }).forEach(i -> System.out.println(i)); + return "foo"; + } + } +} + ]]> + + + Return from anonyous class should not give any error + 0 + () { + @Override + public Integer apply(Integer i) { + return i + 1; + } + }).forEach(i -> System.out.println(i)); + } + } +} + ]]> + diff --git a/pmd-javascript/pom.xml b/pmd-javascript/pom.xml index 40f1077a77..11fb5fd85e 100644 --- a/pmd-javascript/pom.xml +++ b/pmd-javascript/pom.xml @@ -47,23 +47,6 @@ run - - pmd-clean - clean - - - PMD specific tasks: cleaning generated markdown - - - - - - - - - run - - diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/EcmascriptParserOptions.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/EcmascriptParserOptions.java index e616857df1..a30f20b4bc 100644 --- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/EcmascriptParserOptions.java +++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/EcmascriptParserOptions.java @@ -13,6 +13,7 @@ import net.sourceforge.pmd.lang.ParserOptions; import net.sourceforge.pmd.properties.BooleanProperty; import net.sourceforge.pmd.properties.EnumeratedProperty; + public class EcmascriptParserOptions extends ParserOptions { public enum Version { @@ -52,6 +53,10 @@ public class EcmascriptParserOptions extends ParserOptions { // Note: The UI order values are chosen to be larger than those built into // XPathRule. + + // These aren't converted to the new property framework + // Do we need them anyway? + public static final BooleanProperty RECORDING_COMMENTS_DESCRIPTOR = new BooleanProperty("recordingComments", "Specifies that comments are produced in the AST.", Boolean.TRUE, 3.0f); public static final BooleanProperty RECORDING_LOCAL_JSDOC_COMMENTS_DESCRIPTOR = new BooleanProperty( diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/rule/AbstractEcmascriptRule.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/rule/AbstractEcmascriptRule.java index 795ea35ad8..61ab2aa106 100644 --- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/rule/AbstractEcmascriptRule.java +++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/rule/AbstractEcmascriptRule.java @@ -12,6 +12,7 @@ import net.sourceforge.pmd.lang.ParserOptions; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.ecmascript.EcmascriptLanguageModule; import net.sourceforge.pmd.lang.ecmascript.EcmascriptParserOptions; +import net.sourceforge.pmd.lang.ecmascript.EcmascriptParserOptions.Version; import net.sourceforge.pmd.lang.ecmascript.ast.ASTArrayComprehension; import net.sourceforge.pmd.lang.ecmascript.ast.ASTArrayComprehensionLoop; import net.sourceforge.pmd.lang.ecmascript.ast.ASTArrayLiteral; @@ -65,18 +66,19 @@ import net.sourceforge.pmd.lang.ecmascript.ast.EcmascriptNode; import net.sourceforge.pmd.lang.ecmascript.ast.EcmascriptParserVisitor; import net.sourceforge.pmd.lang.rule.AbstractRule; import net.sourceforge.pmd.lang.rule.ImmutableLanguage; -import net.sourceforge.pmd.properties.BooleanProperty; -import net.sourceforge.pmd.properties.EnumeratedProperty; +import net.sourceforge.pmd.properties.PropertyDescriptor; + public abstract class AbstractEcmascriptRule extends AbstractRule implements EcmascriptParserVisitor, ImmutableLanguage { - private static final BooleanProperty RECORDING_COMMENTS_DESCRIPTOR = EcmascriptParserOptions.RECORDING_COMMENTS_DESCRIPTOR; - private static final BooleanProperty RECORDING_LOCAL_JSDOC_COMMENTS_DESCRIPTOR = EcmascriptParserOptions.RECORDING_LOCAL_JSDOC_COMMENTS_DESCRIPTOR; - private static final EnumeratedProperty RHINO_LANGUAGE_VERSION = EcmascriptParserOptions.RHINO_LANGUAGE_VERSION; + private static final PropertyDescriptor RECORDING_COMMENTS_DESCRIPTOR = EcmascriptParserOptions.RECORDING_COMMENTS_DESCRIPTOR; + private static final PropertyDescriptor RECORDING_LOCAL_JSDOC_COMMENTS_DESCRIPTOR = EcmascriptParserOptions.RECORDING_LOCAL_JSDOC_COMMENTS_DESCRIPTOR; + private static final PropertyDescriptor RHINO_LANGUAGE_VERSION = EcmascriptParserOptions.RHINO_LANGUAGE_VERSION; public AbstractEcmascriptRule() { super.setLanguage(LanguageRegistry.getLanguage(EcmascriptLanguageModule.NAME)); + // Rule-specific parser options are not supported. What do we do? definePropertyDescriptor(RECORDING_COMMENTS_DESCRIPTOR); definePropertyDescriptor(RECORDING_LOCAL_JSDOC_COMMENTS_DESCRIPTOR); definePropertyDescriptor(RHINO_LANGUAGE_VERSION); diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/rule/EcmascriptXPathRule.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/rule/EcmascriptXPathRule.java index 9696b53af0..4b5ea7f839 100644 --- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/rule/EcmascriptXPathRule.java +++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/rule/EcmascriptXPathRule.java @@ -8,15 +8,16 @@ import net.sourceforge.pmd.lang.LanguageRegistry; import net.sourceforge.pmd.lang.ParserOptions; import net.sourceforge.pmd.lang.ecmascript.EcmascriptLanguageModule; import net.sourceforge.pmd.lang.ecmascript.EcmascriptParserOptions; +import net.sourceforge.pmd.lang.ecmascript.EcmascriptParserOptions.Version; import net.sourceforge.pmd.lang.rule.XPathRule; -import net.sourceforge.pmd.properties.BooleanProperty; -import net.sourceforge.pmd.properties.EnumeratedProperty; +import net.sourceforge.pmd.properties.PropertyDescriptor; + public class EcmascriptXPathRule extends XPathRule { - private static final BooleanProperty RECORDING_COMMENTS_DESCRIPTOR = EcmascriptParserOptions.RECORDING_COMMENTS_DESCRIPTOR; - private static final BooleanProperty RECORDING_LOCAL_JSDOC_COMMENTS_DESCRIPTOR = EcmascriptParserOptions.RECORDING_LOCAL_JSDOC_COMMENTS_DESCRIPTOR; - private static final EnumeratedProperty RHINO_LANGUAGE_VERSION = EcmascriptParserOptions.RHINO_LANGUAGE_VERSION; + private static final PropertyDescriptor RECORDING_COMMENTS_DESCRIPTOR = EcmascriptParserOptions.RECORDING_COMMENTS_DESCRIPTOR; + private static final PropertyDescriptor RECORDING_LOCAL_JSDOC_COMMENTS_DESCRIPTOR = EcmascriptParserOptions.RECORDING_LOCAL_JSDOC_COMMENTS_DESCRIPTOR; + private static final PropertyDescriptor RHINO_LANGUAGE_VERSION = EcmascriptParserOptions.RHINO_LANGUAGE_VERSION; public EcmascriptXPathRule() { super.setLanguage(LanguageRegistry.getLanguage(EcmascriptLanguageModule.NAME)); diff --git a/pmd-jsp/pom.xml b/pmd-jsp/pom.xml index 38fccb8f28..ecb2101690 100644 --- a/pmd-jsp/pom.xml +++ b/pmd-jsp/pom.xml @@ -48,23 +48,6 @@ run - - pmd-clean - clean - - - PMD specific tasks: cleaning generated markdown - - - - - - - - - run - - diff --git a/pmd-lang-test/pom.xml b/pmd-lang-test/pom.xml index 86d4ec5fcd..51ff7c12de 100644 --- a/pmd-lang-test/pom.xml +++ b/pmd-lang-test/pom.xml @@ -1,7 +1,6 @@ - + 4.0.0 pmd-lang-test PMD language module testing utilities diff --git a/pmd-lang-test/src/main/java/net/sourceforge/pmd/lang/ast/test/PlaceHolder.java b/pmd-lang-test/src/main/java/net/sourceforge/pmd/lang/ast/test/PlaceHolder.java new file mode 100644 index 0000000000..e45609fc3d --- /dev/null +++ b/pmd-lang-test/src/main/java/net/sourceforge/pmd/lang/ast/test/PlaceHolder.java @@ -0,0 +1,13 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.ast.test; + +/** + * Hack to generate package javadoc. + * See: https://stackoverflow.com/questions/1138390/javadoc-for-package-info-java-only + */ +@Deprecated +public class PlaceHolder { +} diff --git a/pmd-lang-test/src/main/java/net/sourceforge/pmd/lang/ast/test/package-info.java b/pmd-lang-test/src/main/java/net/sourceforge/pmd/lang/ast/test/package-info.java new file mode 100644 index 0000000000..f648abb279 --- /dev/null +++ b/pmd-lang-test/src/main/java/net/sourceforge/pmd/lang/ast/test/package-info.java @@ -0,0 +1,8 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +/** + * Contains the Kotlin-based DSL to test AST nodes. + */ +package net.sourceforge.pmd.lang.ast.test; diff --git a/pmd-matlab/src/main/java/net/sourceforge/pmd/cpd/MatlabTokenizer.java b/pmd-matlab/src/main/java/net/sourceforge/pmd/cpd/MatlabTokenizer.java index 818c2ff282..b0eb103f4e 100644 --- a/pmd-matlab/src/main/java/net/sourceforge/pmd/cpd/MatlabTokenizer.java +++ b/pmd-matlab/src/main/java/net/sourceforge/pmd/cpd/MatlabTokenizer.java @@ -10,10 +10,8 @@ import java.io.StringReader; import net.sourceforge.pmd.cpd.token.JavaCCTokenFilter; import net.sourceforge.pmd.cpd.token.TokenFilter; -import net.sourceforge.pmd.lang.LanguageRegistry; -import net.sourceforge.pmd.lang.LanguageVersionHandler; import net.sourceforge.pmd.lang.ast.TokenMgrError; -import net.sourceforge.pmd.lang.matlab.MatlabLanguageModule; +import net.sourceforge.pmd.lang.matlab.MatlabTokenManager; import net.sourceforge.pmd.lang.matlab.ast.Token; import net.sourceforge.pmd.util.IOUtil; @@ -26,12 +24,7 @@ public class MatlabTokenizer implements Tokenizer { public void tokenize(SourceCode sourceCode, Tokens tokenEntries) { StringBuilder buffer = sourceCode.getCodeBuffer(); try (Reader reader = IOUtil.skipBOM(new StringReader(buffer.toString()))) { - LanguageVersionHandler languageVersionHandler = LanguageRegistry.getLanguage(MatlabLanguageModule.NAME) - .getDefaultVersion().getLanguageVersionHandler(); - - final TokenFilter tokenFilter = new JavaCCTokenFilter(languageVersionHandler - .getParser(languageVersionHandler.getDefaultParserOptions()) - .getTokenManager(sourceCode.getFileName(), reader)); + final TokenFilter tokenFilter = new JavaCCTokenFilter(new MatlabTokenManager(reader)); Token currentToken = (Token) tokenFilter.getNextToken(); while (currentToken != null) { tokenEntries.add(new TokenEntry(currentToken.image, sourceCode.getFileName(), currentToken.beginLine)); diff --git a/pmd-matlab/src/main/java/net/sourceforge/pmd/lang/matlab/MatlabHandler.java b/pmd-matlab/src/main/java/net/sourceforge/pmd/lang/matlab/MatlabHandler.java index f808fb37e2..6b7954b657 100644 --- a/pmd-matlab/src/main/java/net/sourceforge/pmd/lang/matlab/MatlabHandler.java +++ b/pmd-matlab/src/main/java/net/sourceforge/pmd/lang/matlab/MatlabHandler.java @@ -11,7 +11,10 @@ import net.sourceforge.pmd.lang.ParserOptions; /** * Implementation of LanguageVersionHandler for the Matlab Language. + * + * @deprecated There is no full PMD support for Matlab. */ +@Deprecated public class MatlabHandler extends AbstractCpdLanguageVersionHandler { @Override diff --git a/pmd-matlab/src/main/java/net/sourceforge/pmd/lang/matlab/MatlabLanguageModule.java b/pmd-matlab/src/main/java/net/sourceforge/pmd/lang/matlab/MatlabLanguageModule.java index 29c4621628..8c310584a6 100644 --- a/pmd-matlab/src/main/java/net/sourceforge/pmd/lang/matlab/MatlabLanguageModule.java +++ b/pmd-matlab/src/main/java/net/sourceforge/pmd/lang/matlab/MatlabLanguageModule.java @@ -8,7 +8,10 @@ import net.sourceforge.pmd.lang.BaseLanguageModule; /** * Implementation of the Matlab Language Module. + * + * @deprecated There is no full PMD support for Matlab. */ +@Deprecated public class MatlabLanguageModule extends BaseLanguageModule { /** The name, that can be used to display the language in UI. */ diff --git a/pmd-matlab/src/main/java/net/sourceforge/pmd/lang/matlab/MatlabParser.java b/pmd-matlab/src/main/java/net/sourceforge/pmd/lang/matlab/MatlabParser.java index 70ad4717ae..4548e31820 100644 --- a/pmd-matlab/src/main/java/net/sourceforge/pmd/lang/matlab/MatlabParser.java +++ b/pmd-matlab/src/main/java/net/sourceforge/pmd/lang/matlab/MatlabParser.java @@ -16,7 +16,10 @@ import net.sourceforge.pmd.lang.ast.ParseException; /** * Adapter for the Matlab Parser. + * + * @deprecated There is no full PMD support for Matlab. */ +@Deprecated public class MatlabParser extends AbstractParser { /** diff --git a/pmd-matlab/src/test/java/net/sourceforge/pmd/LanguageVersionTest.java b/pmd-matlab/src/test/java/net/sourceforge/pmd/LanguageVersionTest.java deleted file mode 100644 index 174a140aa4..0000000000 --- a/pmd-matlab/src/test/java/net/sourceforge/pmd/LanguageVersionTest.java +++ /dev/null @@ -1,27 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd; - -import java.util.Arrays; -import java.util.Collection; - -import org.junit.runners.Parameterized.Parameters; - -import net.sourceforge.pmd.lang.LanguageRegistry; -import net.sourceforge.pmd.lang.LanguageVersion; -import net.sourceforge.pmd.lang.matlab.MatlabLanguageModule; - -public class LanguageVersionTest extends AbstractLanguageVersionTest { - - public LanguageVersionTest(String name, String terseName, String version, LanguageVersion expected) { - super(name, terseName, version, expected); - } - - @Parameters - public static Collection data() { - return Arrays.asList(new Object[][] { { MatlabLanguageModule.NAME, MatlabLanguageModule.TERSE_NAME, "", - LanguageRegistry.getLanguage(MatlabLanguageModule.NAME).getDefaultVersion(), }, }); - } -} diff --git a/pmd-objectivec/src/main/java/net/sourceforge/pmd/cpd/ObjectiveCTokenizer.java b/pmd-objectivec/src/main/java/net/sourceforge/pmd/cpd/ObjectiveCTokenizer.java index 00e56d793c..2bb7e7deac 100644 --- a/pmd-objectivec/src/main/java/net/sourceforge/pmd/cpd/ObjectiveCTokenizer.java +++ b/pmd-objectivec/src/main/java/net/sourceforge/pmd/cpd/ObjectiveCTokenizer.java @@ -10,10 +10,8 @@ import java.io.StringReader; import net.sourceforge.pmd.cpd.token.JavaCCTokenFilter; import net.sourceforge.pmd.cpd.token.TokenFilter; -import net.sourceforge.pmd.lang.LanguageRegistry; -import net.sourceforge.pmd.lang.LanguageVersionHandler; import net.sourceforge.pmd.lang.ast.TokenMgrError; -import net.sourceforge.pmd.lang.objectivec.ObjectiveCLanguageModule; +import net.sourceforge.pmd.lang.objectivec.ObjectiveCTokenManager; import net.sourceforge.pmd.lang.objectivec.ast.Token; /** @@ -25,11 +23,7 @@ public class ObjectiveCTokenizer implements Tokenizer { public void tokenize(SourceCode sourceCode, Tokens tokenEntries) { StringBuilder buffer = sourceCode.getCodeBuffer(); try (Reader reader = new StringReader(buffer.toString())) { - LanguageVersionHandler languageVersionHandler = LanguageRegistry.getLanguage(ObjectiveCLanguageModule.NAME) - .getDefaultVersion().getLanguageVersionHandler(); - final TokenFilter tokenFilter = new JavaCCTokenFilter(languageVersionHandler - .getParser(languageVersionHandler.getDefaultParserOptions()) - .getTokenManager(sourceCode.getFileName(), reader)); + final TokenFilter tokenFilter = new JavaCCTokenFilter(new ObjectiveCTokenManager(reader)); Token currentToken = (Token) tokenFilter.getNextToken(); while (currentToken != null) { tokenEntries.add(new TokenEntry(currentToken.image, sourceCode.getFileName(), currentToken.beginLine)); diff --git a/pmd-objectivec/src/main/java/net/sourceforge/pmd/lang/objectivec/ObjectiveCHandler.java b/pmd-objectivec/src/main/java/net/sourceforge/pmd/lang/objectivec/ObjectiveCHandler.java index 29d45079e1..cba0669667 100644 --- a/pmd-objectivec/src/main/java/net/sourceforge/pmd/lang/objectivec/ObjectiveCHandler.java +++ b/pmd-objectivec/src/main/java/net/sourceforge/pmd/lang/objectivec/ObjectiveCHandler.java @@ -11,6 +11,8 @@ import net.sourceforge.pmd.lang.ParserOptions; /** * Implementation of LanguageVersionHandler for the Objective-C Language. + * + * @deprecated There is no full PMD support for Objective-C. */ public class ObjectiveCHandler extends AbstractCpdLanguageVersionHandler { diff --git a/pmd-objectivec/src/main/java/net/sourceforge/pmd/lang/objectivec/ObjectiveCLanguageModule.java b/pmd-objectivec/src/main/java/net/sourceforge/pmd/lang/objectivec/ObjectiveCLanguageModule.java index 30e9ccdb3c..51612b04ff 100644 --- a/pmd-objectivec/src/main/java/net/sourceforge/pmd/lang/objectivec/ObjectiveCLanguageModule.java +++ b/pmd-objectivec/src/main/java/net/sourceforge/pmd/lang/objectivec/ObjectiveCLanguageModule.java @@ -8,7 +8,10 @@ import net.sourceforge.pmd.lang.BaseLanguageModule; /** * Implementation of the Objective-C Language Module. + * + * @deprecated There is no full PMD support for Objective-C. */ +@Deprecated public class ObjectiveCLanguageModule extends BaseLanguageModule { /** The name, that can be used to display the language in UI. */ diff --git a/pmd-objectivec/src/main/java/net/sourceforge/pmd/lang/objectivec/ObjectiveCParser.java b/pmd-objectivec/src/main/java/net/sourceforge/pmd/lang/objectivec/ObjectiveCParser.java index fcc042bdab..f71bd2e595 100644 --- a/pmd-objectivec/src/main/java/net/sourceforge/pmd/lang/objectivec/ObjectiveCParser.java +++ b/pmd-objectivec/src/main/java/net/sourceforge/pmd/lang/objectivec/ObjectiveCParser.java @@ -16,7 +16,10 @@ import net.sourceforge.pmd.lang.ast.ParseException; /** * Adapter for the Objective-C Parser. + * + * @deprecated There is no full PMD support for Objective-C. */ +@Deprecated public class ObjectiveCParser extends AbstractParser { /** diff --git a/pmd-objectivec/src/test/java/net/sourceforge/pmd/LanguageVersionTest.java b/pmd-objectivec/src/test/java/net/sourceforge/pmd/LanguageVersionTest.java deleted file mode 100644 index 20f0472faa..0000000000 --- a/pmd-objectivec/src/test/java/net/sourceforge/pmd/LanguageVersionTest.java +++ /dev/null @@ -1,27 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd; - -import java.util.Arrays; -import java.util.Collection; - -import org.junit.runners.Parameterized.Parameters; - -import net.sourceforge.pmd.lang.LanguageRegistry; -import net.sourceforge.pmd.lang.LanguageVersion; -import net.sourceforge.pmd.lang.objectivec.ObjectiveCLanguageModule; - -public class LanguageVersionTest extends AbstractLanguageVersionTest { - - public LanguageVersionTest(String name, String terseName, String version, LanguageVersion expected) { - super(name, terseName, version, expected); - } - - @Parameters - public static Collection data() { - return Arrays.asList(new Object[][] { { ObjectiveCLanguageModule.NAME, ObjectiveCLanguageModule.TERSE_NAME, "", - LanguageRegistry.getLanguage(ObjectiveCLanguageModule.NAME).getDefaultVersion(), }, }); - } -} diff --git a/pmd-php/src/main/java/net/sourceforge/pmd/lang/php/PhpLanguageModule.java b/pmd-php/src/main/java/net/sourceforge/pmd/lang/php/PhpLanguageModule.java index 88929091cd..010a7c542a 100644 --- a/pmd-php/src/main/java/net/sourceforge/pmd/lang/php/PhpLanguageModule.java +++ b/pmd-php/src/main/java/net/sourceforge/pmd/lang/php/PhpLanguageModule.java @@ -8,7 +8,10 @@ import net.sourceforge.pmd.lang.BaseLanguageModule; /** * Language Module for PHP. + * + * @deprecated There is no full PMD support for PHP. */ +@Deprecated public class PhpLanguageModule extends BaseLanguageModule { /** The name. */ diff --git a/pmd-php/src/test/java/net/sourceforge/pmd/LanguageVersionTest.java b/pmd-php/src/test/java/net/sourceforge/pmd/LanguageVersionTest.java deleted file mode 100644 index b5f4c0c7b0..0000000000 --- a/pmd-php/src/test/java/net/sourceforge/pmd/LanguageVersionTest.java +++ /dev/null @@ -1,27 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd; - -import java.util.Arrays; -import java.util.Collection; - -import org.junit.runners.Parameterized.Parameters; - -import net.sourceforge.pmd.lang.LanguageRegistry; -import net.sourceforge.pmd.lang.LanguageVersion; -import net.sourceforge.pmd.lang.php.PhpLanguageModule; - -public class LanguageVersionTest extends AbstractLanguageVersionTest { - - public LanguageVersionTest(String name, String terseName, String version, LanguageVersion expected) { - super(name, terseName, version, expected); - } - - @Parameters - public static Collection data() { - return Arrays.asList(new Object[][] { { PhpLanguageModule.NAME, PhpLanguageModule.TERSE_NAME, "", - LanguageRegistry.getLanguage(PhpLanguageModule.NAME).getDefaultVersion(), }, }); - } -} diff --git a/pmd-plsql/etc/grammar/PldocAST.jjt b/pmd-plsql/etc/grammar/PldocAST.jjt index cac0995006..d6d82ae949 100644 --- a/pmd-plsql/etc/grammar/PldocAST.jjt +++ b/pmd-plsql/etc/grammar/PldocAST.jjt @@ -2494,57 +2494,68 @@ ASTEqualityExpression EqualityExpression() #EqualityExpression(>1) : } } +/** + * Relational operators: https://docs.oracle.com/en/database/oracle/oracle-database/18/lnpls/plsql-language-fundamentals.html#GUID-2EB964C8-9B36-4009-A45F-B340F44EE2A2 + */ ASTRelationalExpression RelationalExpression() #RelationalExpression(>1) : { PLSQLNode simpleNode = null; StringBuilder sb = new StringBuilder() ; } { ( //AdditiveExpression() ( ( "<" | ">" | "<=" | ">=" | [] ( | | ) ) AdditiveExpression() )* - (simpleNode = AdditiveExpression() ) { sb.append(simpleNode.getImage()); } - ( - ( + ( simpleNode = AdditiveExpression() ) { sb.append(simpleNode.getImage()); } + ( + ( + ( - ( - (("<" ) { sb.append("<"); } - [">" { sb.append(">"); } ] // <> - ) - | (">" ) { sb.append(">"); } - ) - [ ("=" ) { sb.append("="); } ] - + ("<>" { sb.append(" <> "); } ) + | ("<=" { sb.append(" <= "); } ) + | (">=" { sb.append(" >= "); } ) + | ("!=" { sb.append(" != "); } ) + | ("~=" { sb.append(" ~= "); } ) + | ("^=" { sb.append(" ^= "); } ) + | ("<" { sb.append(" < "); } ) + | (">" { sb.append(" > "); } ) ) + { sb.append(" "); } - | [() { sb.append(" NOT "); }] - (() { sb.append(" IN "); } - | ( ) { sb.append(" BETWEEN "); } - | ( ) { sb.append(" LIKE "); } - | ( - ( - () { sb.append(" MEMBER "); } - | - () { sb.append(" SUBMULTISET "); } - ) - [ { sb.append(" OF "); } ] - ) - ) - // MULTISET Operators - | ( - { sb.append (" MULTISET " );} - ( { sb.append (" EXCEPT " );} - | { sb.append (" INTERSECT " );} - | { sb.append (" UNION " ); } - ) - [ { sb.append (" DISTINCT " );} - | { sb.append (" ALL " );} - ] - ) - ) - (AdditiveExpression() ) { sb.append(simpleNode.getImage()); } - [ - { sb.append(" ESCAPE ");} - ( { sb.append(" "); sb.append(token.toString()); } - | simpleNode = StringLiteral() { sb.append(" "); sb.append(simpleNode.getImage()); } - ) - ] + | [() { sb.append(" NOT "); }] + ( + () { sb.append(" IN "); } + | ( ) { sb.append(" BETWEEN "); } + | ( ) { sb.append(" LIKE "); } + | + ( + ( + () { sb.append(" MEMBER "); } + | + () { sb.append(" SUBMULTISET "); } + ) + [ { sb.append(" OF "); } ] + ) + ) + // MULTISET Operators + | + ( + { sb.append (" MULTISET " );} + ( + { sb.append (" EXCEPT " );} + | { sb.append (" INTERSECT " );} + | { sb.append (" UNION " ); } + ) + [ + { sb.append (" DISTINCT " );} + | { sb.append (" ALL " );} + ] + ) + ) + ( AdditiveExpression() ) { sb.append(simpleNode.getImage()); } + [ + { sb.append(" ESCAPE ");} + ( + { sb.append(" "); sb.append(token.toString()); } + | simpleNode = StringLiteral() { sb.append(" "); sb.append(simpleNode.getImage()); } + ) + ] )* ) { diff --git a/pmd-plsql/pom.xml b/pmd-plsql/pom.xml index 2bd22441ff..56abfd1d71 100644 --- a/pmd-plsql/pom.xml +++ b/pmd-plsql/pom.xml @@ -48,23 +48,6 @@ run - - pmd-clean - clean - - - PMD specific tasks: cleaning generated markdown - - - - - - - - - run - - diff --git a/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/codestyle/CodeFormatRule.java b/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/codestyle/CodeFormatRule.java index 8c4516e16a..db5d6031c4 100644 --- a/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/codestyle/CodeFormatRule.java +++ b/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/codestyle/CodeFormatRule.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.lang.plsql.rule.codestyle; +import static net.sourceforge.pmd.properties.constraints.NumericConstraints.inRange; + import java.util.List; import net.sourceforge.pmd.lang.ast.Node; @@ -23,12 +25,14 @@ import net.sourceforge.pmd.lang.plsql.ast.ASTSubqueryOperation; import net.sourceforge.pmd.lang.plsql.ast.ASTUnqualifiedID; import net.sourceforge.pmd.lang.plsql.ast.ASTVariableOrConstantDeclarator; import net.sourceforge.pmd.lang.plsql.rule.AbstractPLSQLRule; -import net.sourceforge.pmd.properties.IntegerProperty; +import net.sourceforge.pmd.properties.PropertyDescriptor; +import net.sourceforge.pmd.properties.PropertyFactory; + public class CodeFormatRule extends AbstractPLSQLRule { - private static final IntegerProperty INDENTATION_PROPERTY = IntegerProperty.named("indentation") - .desc("Indentation to be used for blocks").defaultValue(2).range(0, 20).build(); + private static final PropertyDescriptor INDENTATION_PROPERTY = PropertyFactory.intProperty("indentation") + .desc("Indentation to be used for blocks").defaultValue(2).require(inRange(0, 32)).build(); private int indentation = INDENTATION_PROPERTY.defaultValue(); diff --git a/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/design/CyclomaticComplexityRule.java b/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/design/CyclomaticComplexityRule.java index fe23505c62..a125e9fc7e 100644 --- a/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/design/CyclomaticComplexityRule.java +++ b/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/design/CyclomaticComplexityRule.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.lang.plsql.rule.design; +import static net.sourceforge.pmd.properties.constraints.NumericConstraints.positive; + import java.util.Stack; import java.util.logging.Level; import java.util.logging.Logger; @@ -30,7 +32,9 @@ import net.sourceforge.pmd.lang.plsql.ast.ASTTypeSpecification; import net.sourceforge.pmd.lang.plsql.ast.ASTWhileStatement; import net.sourceforge.pmd.lang.plsql.rule.AbstractPLSQLRule; import net.sourceforge.pmd.properties.BooleanProperty; -import net.sourceforge.pmd.properties.IntegerProperty; +import net.sourceforge.pmd.properties.PropertyDescriptor; +import net.sourceforge.pmd.properties.PropertyFactory; + /** * @author Donald A. Leckie, @@ -43,10 +47,10 @@ public class CyclomaticComplexityRule extends AbstractPLSQLRule { private static final Logger LOGGER = Logger.getLogger(CyclomaticComplexityRule.class.getName()); private static final String CLASS_NAME = CyclomaticComplexityRule.class.getName(); - public static final IntegerProperty REPORT_LEVEL_DESCRIPTOR - = IntegerProperty.named("reportLevel") + public static final PropertyDescriptor REPORT_LEVEL_DESCRIPTOR + = PropertyFactory.intProperty("reportLevel") .desc("Cyclomatic Complexity reporting threshold") - .range(1, 30).defaultValue(10).uiOrder(1.0f).build(); + .require(positive()).defaultValue(10).build(); public static final BooleanProperty SHOW_CLASSES_COMPLEXITY_DESCRIPTOR = new BooleanProperty( "showClassesComplexity", "Add class average violations to the report", true, 2.0f); diff --git a/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/design/TooManyFieldsRule.java b/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/design/TooManyFieldsRule.java index 10a2bf7d7d..094f47c3ef 100644 --- a/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/design/TooManyFieldsRule.java +++ b/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/design/TooManyFieldsRule.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.lang.plsql.rule.design; +import static net.sourceforge.pmd.properties.constraints.NumericConstraints.positive; + import java.util.HashMap; import java.util.List; import java.util.Map; @@ -15,7 +17,8 @@ import net.sourceforge.pmd.lang.plsql.ast.ASTTypeSpecification; import net.sourceforge.pmd.lang.plsql.ast.ASTVariableOrConstantDeclaration; import net.sourceforge.pmd.lang.plsql.ast.PLSQLNode; import net.sourceforge.pmd.lang.plsql.rule.AbstractPLSQLRule; -import net.sourceforge.pmd.properties.IntegerProperty; +import net.sourceforge.pmd.properties.PropertyDescriptor; +import net.sourceforge.pmd.properties.PropertyFactory; import net.sourceforge.pmd.util.NumericConstants; public class TooManyFieldsRule extends AbstractPLSQLRule { @@ -25,8 +28,12 @@ public class TooManyFieldsRule extends AbstractPLSQLRule { private Map stats; private Map nodes; - private static final IntegerProperty MAX_FIELDS_DESCRIPTOR = new IntegerProperty("maxfields", - "Max allowable fields", 1, 300, DEFAULT_MAXFIELDS, 1.0f); + private static final PropertyDescriptor MAX_FIELDS_DESCRIPTOR + = PropertyFactory.intProperty("maxfields") + .desc("Max allowable fields") + .defaultValue(DEFAULT_MAXFIELDS) + .require(positive()) + .build(); public TooManyFieldsRule() { definePropertyDescriptor(MAX_FIELDS_DESCRIPTOR); @@ -87,7 +94,7 @@ public class TooManyFieldsRule extends AbstractPLSQLRule { stats.put(key, NumericConstants.ZERO); nodes.put(key, clazz); } - Integer i = Integer.valueOf(stats.get(key) + 1); + Integer i = stats.get(key) + 1; stats.put(key, i); } } diff --git a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/PLSQLParserTest.java b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/PLSQLParserTest.java index f1568e199b..afa641c06c 100644 --- a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/PLSQLParserTest.java +++ b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/PLSQLParserTest.java @@ -69,4 +69,9 @@ public class PLSQLParserTest extends AbstractPLSQLParserTst { public void testCodingStyleExample() throws Exception { parsePLSQL(IOUtils.toString(PLSQLParserTest.class.getResourceAsStream("ast/CodingStyleExample.pls"), StandardCharsets.UTF_8)); } + + @Test + public void testCaseIssue1454() throws Exception { + parsePLSQL(IOUtils.toString(PLSQLParserTest.class.getResourceAsStream("ast/CaseIssue1454.pls"), StandardCharsets.UTF_8)); + } } diff --git a/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/CaseIssue1454.pls b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/CaseIssue1454.pls new file mode 100644 index 0000000000..e4e7a4bd11 --- /dev/null +++ b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/CaseIssue1454.pls @@ -0,0 +1,31 @@ +create or replace procedure PMD_TEST_CASE( a IN NUMBER) AS + +begin + + CASE WHEN a >= 100 THEN -- Test the same with <=,!=,<> all cases fail both with IF and CASE statements + dbms_output.put_line('Number is greater than equal to 100'); + WHEN a <= 100 THEN + dbms_output.put_line('Number is less than equal to 100'); + WHEN a < 100 THEN + dbms_output.put_line('Number is less than 100'); + WHEN a > 100 THEN + dbms_output.put_line('Number is greater than 100'); + WHEN a = 42 THEN + dbms_output.put_line('Number is equal to 42'); + WHEN a != 42 THEN + dbms_output.put_line('Number is not 42'); + WHEN a ~= 42 THEN + dbms_output.put_line('Number is not 42'); + WHEN a ^= 42 THEN + dbms_output.put_line('Number is not 42'); + WHEN a <> 42 THEN + dbms_output.put_line('Number is not 42'); + ELSE + dbms_output.put_line('Number is less than 100'); + END CASE; + +exception + when others then + dbms_output.put_line('ERROR: ' || sqlerrm); + +end PMD_TEST_CASE; diff --git a/pmd-python/src/main/java/net/sourceforge/pmd/lang/python/PythonHandler.java b/pmd-python/src/main/java/net/sourceforge/pmd/lang/python/PythonHandler.java index ac209b8d1a..9f2bfa4a11 100644 --- a/pmd-python/src/main/java/net/sourceforge/pmd/lang/python/PythonHandler.java +++ b/pmd-python/src/main/java/net/sourceforge/pmd/lang/python/PythonHandler.java @@ -11,7 +11,10 @@ import net.sourceforge.pmd.lang.ParserOptions; /** * Implementation of LanguageVersionHandler for the Python Language. + * + * @deprecated There is no full PMD support for Python. */ +@Deprecated public class PythonHandler extends AbstractCpdLanguageVersionHandler { diff --git a/pmd-python/src/main/java/net/sourceforge/pmd/lang/python/PythonLanguageModule.java b/pmd-python/src/main/java/net/sourceforge/pmd/lang/python/PythonLanguageModule.java index 995810ffb2..3003d53389 100644 --- a/pmd-python/src/main/java/net/sourceforge/pmd/lang/python/PythonLanguageModule.java +++ b/pmd-python/src/main/java/net/sourceforge/pmd/lang/python/PythonLanguageModule.java @@ -8,7 +8,10 @@ import net.sourceforge.pmd.lang.BaseLanguageModule; /** * Implementation of the Python Language Module. + * + * @deprecated There is no full PMD support for Python. */ +@Deprecated public class PythonLanguageModule extends BaseLanguageModule { /** The name, that can be used to display the language in UI. */ diff --git a/pmd-python/src/main/java/net/sourceforge/pmd/lang/python/PythonParser.java b/pmd-python/src/main/java/net/sourceforge/pmd/lang/python/PythonParser.java index 03e4e4f03d..4aa11e9706 100644 --- a/pmd-python/src/main/java/net/sourceforge/pmd/lang/python/PythonParser.java +++ b/pmd-python/src/main/java/net/sourceforge/pmd/lang/python/PythonParser.java @@ -16,7 +16,10 @@ import net.sourceforge.pmd.lang.ast.ParseException; /** * Adapter for the Python Parser. + * + * @deprecated There is no full PMD support for Python. */ +@Deprecated public class PythonParser extends AbstractParser { /** diff --git a/pmd-python/src/test/java/net/sourceforge/pmd/LanguageVersionDiscovererTest.java b/pmd-python/src/test/java/net/sourceforge/pmd/LanguageVersionDiscovererTest.java deleted file mode 100644 index 2915db700e..0000000000 --- a/pmd-python/src/test/java/net/sourceforge/pmd/LanguageVersionDiscovererTest.java +++ /dev/null @@ -1,32 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd; - -import static org.junit.Assert.assertEquals; - -import java.io.File; - -import org.junit.Test; - -import net.sourceforge.pmd.lang.LanguageRegistry; -import net.sourceforge.pmd.lang.LanguageVersion; -import net.sourceforge.pmd.lang.LanguageVersionDiscoverer; -import net.sourceforge.pmd.lang.python.PythonLanguageModule; - -public class LanguageVersionDiscovererTest { - - /** - * Test on Python file with default version - */ - @Test - public void testPython() { - LanguageVersionDiscoverer discoverer = new LanguageVersionDiscoverer(); - File pythonFile = new File("/path/to/MY_PACKAGE.py"); - - LanguageVersion languageVersion = discoverer.getDefaultLanguageVersionForFile(pythonFile); - assertEquals("LanguageVersion must be Python!", - LanguageRegistry.getLanguage(PythonLanguageModule.NAME).getDefaultVersion(), languageVersion); - } -} diff --git a/pmd-python/src/test/java/net/sourceforge/pmd/LanguageVersionTest.java b/pmd-python/src/test/java/net/sourceforge/pmd/LanguageVersionTest.java deleted file mode 100644 index f4210fc481..0000000000 --- a/pmd-python/src/test/java/net/sourceforge/pmd/LanguageVersionTest.java +++ /dev/null @@ -1,27 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd; - -import java.util.Arrays; -import java.util.Collection; - -import org.junit.runners.Parameterized.Parameters; - -import net.sourceforge.pmd.lang.LanguageRegistry; -import net.sourceforge.pmd.lang.LanguageVersion; -import net.sourceforge.pmd.lang.python.PythonLanguageModule; - -public class LanguageVersionTest extends AbstractLanguageVersionTest { - - public LanguageVersionTest(String name, String terseName, String version, LanguageVersion expected) { - super(name, terseName, version, expected); - } - - @Parameters - public static Collection data() { - return Arrays.asList(new Object[][] { { PythonLanguageModule.NAME, PythonLanguageModule.TERSE_NAME, "", - LanguageRegistry.getLanguage(PythonLanguageModule.NAME).getDefaultVersion(), }, }); - } -} diff --git a/pmd-ruby/src/main/java/net/sourceforge/pmd/lang/ruby/RubyLanguageModule.java b/pmd-ruby/src/main/java/net/sourceforge/pmd/lang/ruby/RubyLanguageModule.java index 48ff5f92a7..36ec4680e2 100644 --- a/pmd-ruby/src/main/java/net/sourceforge/pmd/lang/ruby/RubyLanguageModule.java +++ b/pmd-ruby/src/main/java/net/sourceforge/pmd/lang/ruby/RubyLanguageModule.java @@ -8,7 +8,10 @@ import net.sourceforge.pmd.lang.BaseLanguageModule; /** * Language module for Ruby. + * + * @deprecated There is no full PMD support for Ruby. */ +@Deprecated public class RubyLanguageModule extends BaseLanguageModule { /** The name. */ diff --git a/pmd-ruby/src/test/java/net/sourceforge/pmd/LanguageVersionTest.java b/pmd-ruby/src/test/java/net/sourceforge/pmd/LanguageVersionTest.java deleted file mode 100644 index af5451a4aa..0000000000 --- a/pmd-ruby/src/test/java/net/sourceforge/pmd/LanguageVersionTest.java +++ /dev/null @@ -1,27 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd; - -import java.util.Arrays; -import java.util.Collection; - -import org.junit.runners.Parameterized.Parameters; - -import net.sourceforge.pmd.lang.LanguageRegistry; -import net.sourceforge.pmd.lang.LanguageVersion; -import net.sourceforge.pmd.lang.ruby.RubyLanguageModule; - -public class LanguageVersionTest extends AbstractLanguageVersionTest { - - public LanguageVersionTest(String name, String terseName, String version, LanguageVersion expected) { - super(name, terseName, version, expected); - } - - @Parameters - public static Collection data() { - return Arrays.asList(new Object[][] { { RubyLanguageModule.NAME, RubyLanguageModule.TERSE_NAME, "", - LanguageRegistry.getLanguage(RubyLanguageModule.NAME).getDefaultVersion(), }, }); - } -} diff --git a/pmd-scala/src/main/java/net/sourceforge/pmd/lang/scala/ScalaLanguageModule.java b/pmd-scala/src/main/java/net/sourceforge/pmd/lang/scala/ScalaLanguageModule.java index 135b626ebd..739a0834e7 100644 --- a/pmd-scala/src/main/java/net/sourceforge/pmd/lang/scala/ScalaLanguageModule.java +++ b/pmd-scala/src/main/java/net/sourceforge/pmd/lang/scala/ScalaLanguageModule.java @@ -8,7 +8,10 @@ import net.sourceforge.pmd.lang.BaseLanguageModule; /** * Language Module for Scala + * + * @deprecated There is no full PMD support for Scala. */ +@Deprecated public class ScalaLanguageModule extends BaseLanguageModule { /** The name. */ diff --git a/pmd-scala/src/test/java/net/sourceforge/pmd/LanguageVersionTest.java b/pmd-scala/src/test/java/net/sourceforge/pmd/LanguageVersionTest.java deleted file mode 100644 index 1a45a40e5f..0000000000 --- a/pmd-scala/src/test/java/net/sourceforge/pmd/LanguageVersionTest.java +++ /dev/null @@ -1,27 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd; - -import java.util.Arrays; -import java.util.Collection; - -import org.junit.runners.Parameterized.Parameters; - -import net.sourceforge.pmd.lang.LanguageRegistry; -import net.sourceforge.pmd.lang.LanguageVersion; -import net.sourceforge.pmd.lang.scala.ScalaLanguageModule; - -public class LanguageVersionTest extends AbstractLanguageVersionTest { - - public LanguageVersionTest(String name, String terseName, String version, LanguageVersion expected) { - super(name, terseName, version, expected); - } - - @Parameters - public static Collection data() { - return Arrays.asList(new Object[][] { { ScalaLanguageModule.NAME, ScalaLanguageModule.TERSE_NAME, "", - LanguageRegistry.getLanguage(ScalaLanguageModule.NAME).getDefaultVersion(), }, }); - } -} diff --git a/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/SwiftLanguageModule.java b/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/SwiftLanguageModule.java index fe66c3f81f..76fa53d5a6 100644 --- a/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/SwiftLanguageModule.java +++ b/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/SwiftLanguageModule.java @@ -8,7 +8,10 @@ import net.sourceforge.pmd.lang.BaseLanguageModule; /** * Language Module for Swift + * + * @deprecated There is no full PMD support for Swift. */ +@Deprecated public class SwiftLanguageModule extends BaseLanguageModule { /** The name. */ diff --git a/pmd-swift/src/test/java/net/sourceforge/pmd/LanguageVersionTest.java b/pmd-swift/src/test/java/net/sourceforge/pmd/LanguageVersionTest.java deleted file mode 100644 index fae0f9dfd2..0000000000 --- a/pmd-swift/src/test/java/net/sourceforge/pmd/LanguageVersionTest.java +++ /dev/null @@ -1,27 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd; - -import java.util.Arrays; -import java.util.Collection; - -import org.junit.runners.Parameterized.Parameters; - -import net.sourceforge.pmd.lang.LanguageRegistry; -import net.sourceforge.pmd.lang.LanguageVersion; -import net.sourceforge.pmd.lang.swift.SwiftLanguageModule; - -public class LanguageVersionTest extends AbstractLanguageVersionTest { - - public LanguageVersionTest(String name, String terseName, String version, LanguageVersion expected) { - super(name, terseName, version, expected); - } - - @Parameters - public static Collection data() { - return Arrays.asList(new Object[][] { { SwiftLanguageModule.NAME, SwiftLanguageModule.TERSE_NAME, "", - LanguageRegistry.getLanguage(SwiftLanguageModule.NAME).getDefaultVersion(), }, }); - } -} diff --git a/pmd-visualforce/pom.xml b/pmd-visualforce/pom.xml index aea3a0a990..2df2b60785 100644 --- a/pmd-visualforce/pom.xml +++ b/pmd-visualforce/pom.xml @@ -48,23 +48,6 @@ run - - pmd-clean - clean - - - PMD specific tasks: cleaning generated markdown - - - - - - - - - run - - diff --git a/pmd-vm/pom.xml b/pmd-vm/pom.xml index 8384b639fc..2ec5f0b9ac 100644 --- a/pmd-vm/pom.xml +++ b/pmd-vm/pom.xml @@ -48,23 +48,6 @@ run - - pmd-clean - clean - - - PMD specific tasks: cleaning generated markdown - - - - - - - - - run - - diff --git a/pmd-vm/src/main/java/net/sourceforge/pmd/lang/vm/rule/design/AvoidDeeplyNestedIfStmtsRule.java b/pmd-vm/src/main/java/net/sourceforge/pmd/lang/vm/rule/design/AvoidDeeplyNestedIfStmtsRule.java index ceff76e81e..7cb6c41279 100644 --- a/pmd-vm/src/main/java/net/sourceforge/pmd/lang/vm/rule/design/AvoidDeeplyNestedIfStmtsRule.java +++ b/pmd-vm/src/main/java/net/sourceforge/pmd/lang/vm/rule/design/AvoidDeeplyNestedIfStmtsRule.java @@ -4,22 +4,26 @@ package net.sourceforge.pmd.lang.vm.rule.design; +import static net.sourceforge.pmd.properties.constraints.NumericConstraints.positive; + import net.sourceforge.pmd.lang.vm.ast.ASTElseIfStatement; import net.sourceforge.pmd.lang.vm.ast.ASTIfStatement; import net.sourceforge.pmd.lang.vm.ast.ASTprocess; import net.sourceforge.pmd.lang.vm.ast.AbstractVmNode; import net.sourceforge.pmd.lang.vm.rule.AbstractVmRule; -import net.sourceforge.pmd.properties.IntegerProperty; +import net.sourceforge.pmd.properties.PropertyDescriptor; +import net.sourceforge.pmd.properties.PropertyFactory; + public class AvoidDeeplyNestedIfStmtsRule extends AbstractVmRule { private int depth; private int depthLimit; - private static final IntegerProperty PROBLEM_DEPTH_DESCRIPTOR - = IntegerProperty.named("problemDepth") + private static final PropertyDescriptor PROBLEM_DEPTH_DESCRIPTOR + = PropertyFactory.intProperty("problemDepth") .desc("The if statement depth reporting threshold") - .range(1, 25).defaultValue(3).uiOrder(1.0f).build(); + .require(positive()).defaultValue(3).build(); public AvoidDeeplyNestedIfStmtsRule() { definePropertyDescriptor(PROBLEM_DEPTH_DESCRIPTOR); diff --git a/pmd-xml/pmd-xml-ruleset.xml b/pmd-xml/pmd-xml-ruleset.xml deleted file mode 100644 index 88fc15f32b..0000000000 --- a/pmd-xml/pmd-xml-ruleset.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - Rules to check PMD itself. - - - - - - - \ No newline at end of file diff --git a/pmd-xml/pom.xml b/pmd-xml/pom.xml index 24e9b8971e..8680d44c18 100644 --- a/pmd-xml/pom.xml +++ b/pmd-xml/pom.xml @@ -27,41 +27,6 @@ - - - org.apache.maven.plugins - maven-antrun-plugin - - - pmd-clean - clean - - - PMD specific tasks: cleaning generated markdown - - - - - - - - - run - - - - - - - - org.apache.maven.plugins - maven-pmd-plugin - - - pmd-xml-ruleset.xml - - - diff --git a/pom.xml b/pom.xml index 3683608b73..b4e5861b86 100644 --- a/pom.xml +++ b/pom.xml @@ -282,7 +282,7 @@ Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code -Xmx512m -Dfile.encoding=${project.build.sourceEncoding} - 1.3-SNAPSHOT + 1.3.0 @@ -488,6 +488,36 @@ Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code org.apache.maven.plugins maven-checkstyle-plugin ${checkstyle.version} + + + checkstyle-check + verify + + check + + + + + + com.puppycrawl.tools + checkstyle + 8.12 + + + net.sourceforge.pmd + pmd-build-tools-config + ${pmd.build-tools.version} + + + + /net/sourceforge/pmd/pmd-checkstyle-config.xml + /net/sourceforge/pmd/pmd-checkstyle-suppressions.xml + true + + ${project.build.sourceDirectory} + + **/*.properties,**/*.less + org.apache.maven.plugins @@ -609,29 +639,6 @@ Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code - - org.apache.maven.plugins - maven-antrun-plugin - true - - - pmd-clean - clean - - - PMD specific tasks: cleaning generated xdocs - - - - - - - - run - - - - org.apache.maven.plugins maven-pmd-plugin @@ -640,36 +647,7 @@ Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code org.apache.maven.plugins maven-checkstyle-plugin - - - checkstyle-check - verify - - check - - - - - - com.puppycrawl.tools - checkstyle - 8.12 - - - net.sourceforge.pmd - pmd-build-tools-config - ${pmd.build-tools.version} - - - - /net/sourceforge/pmd/pmd-checkstyle-config.xml - /net/sourceforge/pmd/pmd-checkstyle-suppressions.xml - true - - ${project.build.sourceDirectory} - - **/*.properties,**/*.less - + org.apache.maven.plugins @@ -745,14 +723,7 @@ Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code org.apache.maven.plugins maven-checkstyle-plugin ${checkstyle.version} - - /net/sourceforge/pmd/pmd-checkstyle-config.xml - /net/sourceforge/pmd/pmd-checkstyle-suppressions.xml - true - - ${project.build.sourceDirectory} - - + @@ -848,7 +819,7 @@ Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code org.ow2.asm asm - 6.2.1 + 7.0 net.sourceforge.pmd
MethodViolation