2018-06-16 20:39:36 +00:00
<!DOCTYPE html>
< html >
< head >
< meta charset = "utf-8" >
< meta http-equiv = "X-UA-Compatible" content = "IE=edge" >
< meta name = "viewport" content = "width=device-width, initial-scale=1" >
< meta name = "description" content = "Learn how to define your own properties both for Java and XPath rules." >
< meta name = "keywords" content = "extendinguserdocs, " >
< title > Defining rule properties | PMD Source Code Analyzer< / title >
< link rel = "stylesheet" href = "css/syntax.css" >
< link rel = "stylesheet" type = "text/css" href = "https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css" >
<!-- <link rel="stylesheet" type="text/css" href="css/bootstrap.min.css"> -->
< link rel = "stylesheet" href = "css/modern-business.css" >
< link rel = "stylesheet" href = "css/lavish-bootstrap.css" >
< link rel = "stylesheet" href = "css/customstyles.css" >
< link rel = "stylesheet" href = "css/theme-blue.css" >
< link rel = "stylesheet" href = "css/pmd-customstyles.css" >
< script src = "https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js" > < / script >
< script src = "https://cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.min.js" > < / script >
< script src = "js/jquery.navgoco.min.js" > < / script >
< script src = "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js" > < / script >
< script src = "https://cdnjs.cloudflare.com/ajax/libs/anchor-js/2.0.0/anchor.min.js" > < / script >
< script src = "js/toc.js" > < / script >
< script src = "js/customscripts.js" > < / script >
< link rel = "shortcut icon" href = "images/favicon.ico" type = "image/x-icon" >
< link rel = "icon" href = "images/favicon.ico" type = "image/x-icon" >
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!-- [if lt IE 9]>
< script src = "https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js" > < / script >
< script src = "https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js" > < / script >
<![endif]-->
< link rel = "alternate" type = "application/rss+xml" title = "" href = "https://pmd.github.io/pmd/feed.xml" >
< script >
$(document).ready(function() {
// Initialize navgoco with default options
$("#mysidebar").navgoco({
caretHtml: '',
accordion: true,
openClass: 'active', // open
save: false, // leave false or nav highlighting doesn't work right
cookie: {
name: 'navgoco',
expires: false,
path: '/'
},
slide: {
duration: 400,
easing: 'swing'
}
});
$("#collapseAll").click(function(e) {
e.preventDefault();
$("#mysidebar").navgoco('toggle', false);
});
$("#expandAll").click(function(e) {
e.preventDefault();
$("#mysidebar").navgoco('toggle', true);
});
});
< / script >
< script >
$(function () {
$('[data-toggle="tooltip"]').tooltip()
})
< / script >
< script >
$(document).ready(function() {
$("#tg-sb-link").click(function() {
$("#tg-sb-sidebar").toggle();
$("#tg-sb-content").toggleClass('col-md-9');
$("#tg-sb-content").toggleClass('col-md-12');
$("#tg-sb-icon").toggleClass('fa-toggle-on');
$("#tg-sb-icon").toggleClass('fa-toggle-off');
});
});
< / script >
< / head >
< body >
<!-- Content is offset by the height of the topnav bar. -->
<!-- There's already a padding - top rule in modern - business.css, but it apparently doesn't work on Firefox 60 and Chrome 67 -->
< div id = "topbar-content-offset" >
<!-- Navigation -->
< nav class = "navbar navbar-inverse navbar-fixed-top" >
< div class = "container topnavlinks" >
< div class = "navbar-header" >
< button type = "button" class = "navbar-toggle" data-toggle = "collapse" data-target = "#bs-example-navbar-collapse-1" >
< span class = "sr-only" > Toggle navigation< / span >
< span class = "icon-bar" > < / span >
< span class = "icon-bar" > < / span >
< span class = "icon-bar" > < / span >
< / button >
< a class = "fa fa-home fa-lg navbar-brand" href = "index.html" > < span class = "projectTitle" > PMD Source Code Analyzer Project< / span > < / a >
< / div >
< div class = "collapse navbar-collapse" id = "bs-example-navbar-collapse-1" >
< ul class = "nav navbar-nav navbar-right" >
<!-- toggle sidebar button -->
< li > < a id = "tg-sb-link" href = "#" > < i id = "tg-sb-icon" class = "fa fa-toggle-on" > < / i > Nav< / a > < / li >
<!-- entries without drop - downs appear here -->
< li > < a href = "https://github.com/pmd/pmd/releases/latest" target = "_blank" > Download< / a > < / li >
< li > < a href = "https://github.com/pmd/pmd" target = "_blank" > Fork us on github< / a > < / li >
<!-- entries with drop - downs appear here -->
<!-- conditional logic to control which topnav appears for the audience defined in the configuration file. -->
<!-- comment out this block if you want to hide search -->
< li >
<!-- start search -->
< div id = "search-demo-container" >
< input type = "text" id = "search-input" placeholder = "search..." >
< ul id = "results-container" > < / ul >
< / div >
< script src = "js/jekyll-search.js" type = "text/javascript" > < / script >
< script type = "text/javascript" >
SimpleJekyllSearch.init({
searchInput: document.getElementById('search-input'),
resultsContainer: document.getElementById('results-container'),
dataSource: 'search.json',
searchResultTemplate: '< li > < a href = "{url}" title = "Defining rule properties" > {title}< / a > < / li > ',
noResultsText: 'No results found.',
limit: 10,
fuzzy: true,
})
< / script >
<!-- end search -->
< / li >
< / ul >
< / div >
< / div >
<!-- /.container -->
< / nav >
<!-- Page Content -->
< div class = "container" >
< div class = "col-lg-12" > < / div >
<!-- Content Row -->
< div class = "row" >
<!-- Sidebar Column -->
< div class = "col-md-3" id = "tg-sb-sidebar" >
< ul id = "mysidebar" class = "nav" >
2019-07-28 08:45:42 +00:00
< li class = "sidebarTitle" > PMD 6.18.0< / li >
2018-06-16 20:39:36 +00:00
< li >
< a href = "#" > About< / a >
< ul >
< li > < a href = "index.html" > Home< / a > < / li >
< li > < a href = "pmd_release_notes.html" > Release notes< / a > < / li >
2018-11-12 19:21:12 +00:00
< li > < a href = "pmd_next_major_development.html" > PMD 7.0.0 development< / a > < / li >
2018-06-16 20:39:36 +00:00
< li > < a href = "pmd_about_help.html" > Getting help< / a > < / li >
< / ul >
< / li >
< li >
< a href = "#" > User Documentation< / a >
< ul >
< li > < a href = "pmd_userdocs_installation.html" > Installation and basic CLI usage< / a > < / li >
< li > < a href = "pmd_userdocs_making_rulesets.html" > Making rulesets< / a > < / li >
< li > < a href = "pmd_userdocs_configuring_rules.html" > Configuring rules< / a > < / li >
< li > < a href = "pmd_userdocs_best_practices.html" > Best practices< / a > < / li >
< li > < a href = "pmd_userdocs_suppressing_warnings.html" > Suppressing warnings< / a > < / li >
< li > < a href = "pmd_userdocs_incremental_analysis.html" > Incremental analysis< / a > < / li >
< li > < a href = "pmd_userdocs_cli_reference.html" > PMD CLI reference< / a > < / li >
< li class = "subfolders" >
< a href = "#" > Extending PMD< / a >
< ul >
< li > < a href = "pmd_userdocs_extending_writing_pmd_rules.html" > Writing a rule< / a > < / li >
< li > < a href = "pmd_userdocs_extending_writing_xpath_rules.html" > Writing XPath rules< / a > < / li >
2019-08-10 20:25:08 +00:00
< li > < a href = "pmd_userdocs_extending_designer_reference.html" > Rule designer reference< / a > < / li >
2018-06-16 20:39:36 +00:00
< li class = "active" > < a href = "pmd_userdocs_extending_defining_properties.html" > Defining rule properties< / a > < / li >
< li > < a href = "pmd_userdocs_extending_metrics_howto.html" > Using and defining code metrics< / a > < / li >
< li > < a href = "pmd_userdocs_extending_rule_guidelines.html" > Rule guidelines< / a > < / li >
< li > < a href = "pmd_userdocs_extending_testing.html" > Testing your rules< / a > < / li >
< / ul >
< / li >
< li > < a href = "pmd_userdocs_cpd.html" > Copy-paste detection< / a > < / li >
< li class = "subfolders" >
< a href = "#" > Tools / Integrations< / a >
< ul >
< li > < a href = "pmd_userdocs_tools_maven.html" > Maven PMD plugin< / a > < / li >
< li > < a href = "pmd_userdocs_tools_ant.html" > Ant< / a > < / li >
< li > < a href = "pmd_userdocs_tools_ci.html" > CI integrations< / a > < / li >
< li > < a href = "pmd_userdocs_tools.html" > Other Tools / Integrations< / a > < / li >
< / ul >
< / li >
< / ul >
< / li >
< li >
< a href = "#" > Rule Reference< / a >
< ul >
< li class = "subfolders" >
< a href = "#" > Apex Rules< / a >
< ul >
< li > < a href = "pmd_rules_apex.html" > Index< / a > < / li >
< li > < a href = "pmd_rules_apex_bestpractices.html" > Best Practices< / a > < / li >
< li > < a href = "pmd_rules_apex_codestyle.html" > Code Style< / a > < / li >
< li > < a href = "pmd_rules_apex_design.html" > Design< / a > < / li >
2018-12-22 23:00:47 +00:00
< li > < a href = "pmd_rules_apex_documentation.html" > Documentation< / a > < / li >
2018-06-16 20:39:36 +00:00
< li > < a href = "pmd_rules_apex_errorprone.html" > Error Prone< / a > < / li >
< li > < a href = "pmd_rules_apex_performance.html" > Performance< / a > < / li >
< li > < a href = "pmd_rules_apex_security.html" > Security< / a > < / li >
< / ul >
< / li >
< li class = "subfolders" >
< a href = "#" > Ecmascript Rules< / a >
< ul >
< li > < a href = "pmd_rules_ecmascript.html" > Index< / a > < / li >
< li > < a href = "pmd_rules_ecmascript_bestpractices.html" > Best Practices< / a > < / li >
< li > < a href = "pmd_rules_ecmascript_codestyle.html" > Code Style< / a > < / li >
< li > < a href = "pmd_rules_ecmascript_errorprone.html" > Error Prone< / a > < / li >
< / ul >
< / li >
< li class = "subfolders" >
< a href = "#" > Java Rules< / a >
< ul >
< li > < a href = "pmd_rules_java.html" > Index< / a > < / li >
< li > < a href = "pmd_rules_java_bestpractices.html" > Best Practices< / a > < / li >
< li > < a href = "pmd_rules_java_codestyle.html" > Code Style< / a > < / li >
< li > < a href = "pmd_rules_java_design.html" > Design< / a > < / li >
< li > < a href = "pmd_rules_java_documentation.html" > Documentation< / a > < / li >
< li > < a href = "pmd_rules_java_errorprone.html" > Error Prone< / a > < / li >
< li > < a href = "pmd_rules_java_multithreading.html" > Multithreading< / a > < / li >
< li > < a href = "pmd_rules_java_performance.html" > Performance< / a > < / li >
< li > < a href = "pmd_rules_java_security.html" > Security< / a > < / li >
< / ul >
< / li >
< li class = "subfolders" >
< a href = "#" > Java Server Pages Rules< / a >
< ul >
< li > < a href = "pmd_rules_jsp.html" > Index< / a > < / li >
< li > < a href = "pmd_rules_jsp_bestpractices.html" > Best Practices< / a > < / li >
< li > < a href = "pmd_rules_jsp_codestyle.html" > Code Style< / a > < / li >
< li > < a href = "pmd_rules_jsp_design.html" > Design< / a > < / li >
< li > < a href = "pmd_rules_jsp_errorprone.html" > Error Prone< / a > < / li >
< li > < a href = "pmd_rules_jsp_security.html" > Security< / a > < / li >
< / ul >
< / li >
< li class = "subfolders" >
< a href = "#" > Maven POM Rules< / a >
< ul >
< li > < a href = "pmd_rules_pom.html" > Index< / a > < / li >
< li > < a href = "pmd_rules_pom_errorprone.html" > Error Prone< / a > < / li >
< / ul >
< / li >
< li class = "subfolders" >
< a href = "#" > PLSQL Rules< / a >
< ul >
< li > < a href = "pmd_rules_plsql.html" > Index< / a > < / li >
< li > < a href = "pmd_rules_plsql_bestpractices.html" > Best Practices< / a > < / li >
< li > < a href = "pmd_rules_plsql_codestyle.html" > Code Style< / a > < / li >
< li > < a href = "pmd_rules_plsql_design.html" > Design< / a > < / li >
< li > < a href = "pmd_rules_plsql_errorprone.html" > Error Prone< / a > < / li >
< / ul >
< / li >
< li class = "subfolders" >
< a href = "#" > Salesforce VisualForce Rules< / a >
< ul >
< li > < a href = "pmd_rules_vf.html" > Index< / a > < / li >
< li > < a href = "pmd_rules_vf_security.html" > Security< / a > < / li >
< / ul >
< / li >
< li class = "subfolders" >
< a href = "#" > VM Rules< / a >
< ul >
< li > < a href = "pmd_rules_vm.html" > Index< / a > < / li >
< li > < a href = "pmd_rules_vm_bestpractices.html" > Best Practices< / a > < / li >
< li > < a href = "pmd_rules_vm_design.html" > Design< / a > < / li >
< li > < a href = "pmd_rules_vm_errorprone.html" > Error Prone< / a > < / li >
< / ul >
< / li >
< li class = "subfolders" >
< a href = "#" > XML Rules< / a >
< ul >
< li > < a href = "pmd_rules_xml.html" > Index< / a > < / li >
< li > < a href = "pmd_rules_xml_errorprone.html" > Error Prone< / a > < / li >
< / ul >
< / li >
< li class = "subfolders" >
< a href = "#" > XSL Rules< / a >
< ul >
< li > < a href = "pmd_rules_xsl.html" > Index< / a > < / li >
< li > < a href = "pmd_rules_xsl_codestyle.html" > Code Style< / a > < / li >
< li > < a href = "pmd_rules_xsl_performance.html" > Performance< / a > < / li >
< / ul >
< / li >
< / ul >
< / li >
< li >
< a href = "#" > Language Specific Documentation< / a >
< ul >
< li > < a href = "pmd_languages_jsp.html" > JSP Support< / a > < / li >
< li > < a href = "pmd_java_metrics_index.html" > Java code metrics< / a > < / li >
< li > < a href = "pmd_apex_metrics_index.html" > Apex code metrics< / a > < / li >
< / ul >
< / li >
< li >
< a href = "#" > Developer Documentation< / a >
< ul >
< li > < a href = "pmd_devdocs_development.html" > Developer resources< / a > < / li >
< li > < a href = "pmd_devdocs_building.html" > Building PMD from source< / a > < / li >
< li > < a href = "https://github.com/pmd/pmd/blob/master/CONTRIBUTING.md" target = "_blank" > Contributing< / a > < / li >
< li > < a href = "pmd_devdocs_writing_documentation.html" > Writing documentation< / a > < / li >
< li > < a href = "pmd_devdocs_roadmap.html" > Roadmap< / a > < / li >
< li > < a href = "pmd_devdocs_how_pmd_works.html" > How PMD works< / a > < / li >
2018-08-08 06:36:04 +00:00
< li > < a href = "pmd_devdocs_pmdtester.html" > Pmdtester< / a > < / li >
2018-06-16 20:39:36 +00:00
< li class = "subfolders" >
< a href = "#" > Major contributions< / a >
< ul >
< li > < a href = "pmd_devdocs_major_adding_new_language.html" > Adding a new language< / a > < / li >
< li > < a href = "pmd_devdocs_major_adding_new_cpd_language.html" > Adding a new CPD language< / a > < / li >
< li > < a href = "pmd_devdocs_major_adding_new_metrics_framework.html" > Adding metrics support to a language< / a > < / li >
< / ul >
< / li >
< / ul >
< / li >
< li >
< a href = "#" > Project documentation< / a >
< ul >
< li class = "subfolders" >
< a href = "#" > Trivia about PMD< / a >
< ul >
< li > < a href = "pmd_projectdocs_trivia_news.html" > PMD in the press< / a > < / li >
< li > < a href = "pmd_projectdocs_trivia_products.html" > Products & books related to PMD< / a > < / li >
< li > < a href = "pmd_projectdocs_trivia_similarprojects.html" > Similar projects< / a > < / li >
< li > < a href = "pmd_projectdocs_trivia_meaning.html" > What does 'PMD' mean?< / a > < / li >
< / ul >
< / li >
< li > < a href = "pmd_projectdocs_faq.html" > FAQ< / a > < / li >
< li > < a href = "license.html" > License< / a > < / li >
< li > < a href = "pmd_projectdocs_credits.html" > Credits< / a > < / li >
< li > < a href = "pmd_release_notes_old.html" > Old release notes< / a > < / li >
< li class = "subfolders" >
< a href = "#" > Project management< / a >
< ul >
< li > < a href = "pmd_projectdocs_committers_releasing.html" > Release process< / a > < / li >
< li > < a href = "pmd_projectdocs_committers_merging_pull_requests.html" > Merging pull requests< / a > < / li >
< / ul >
< / li >
< / ul >
< / li >
<!-- if you aren't using the accordion, uncomment this block:
< p class = "external" >
< a href = "#" id = "collapseAll" > Collapse All< / a > | < a href = "#" id = "expandAll" > Expand All< / a >
< / p >
-->
< / ul >
<!-- this highlights the active parent class in the navgoco sidebar. this is critical so that the parent expands when you're viewing a page. This must appear below the sidebar code above. Otherwise, if placed inside customscripts.js, the script runs before the sidebar code runs and the class never gets inserted. -->
< script > $ ( "li.active" ) . parents ( 'li' ) . toggleClass ( "active" ) ; < / script >
< / div >
<!-- Content Column -->
< div class = "col-md-9" id = "tg-sb-content" >
< div class = "post-header" >
< h1 class = "post-title-main" > Defining rule properties< / h1 >
< / div >
< div class = "post-content" >
< div class = "summary" > Learn how to define your own properties both for Java and XPath rules.< / div >
<!-- this handles the automatic toc. use ## for subheads to auto - generate the on - page minitoc. if you use html tags, you must supply an ID for the heading element in order for it to appear in the minitoc. -->
< script >
$( document ).ready(function() {
// Handler for .ready() called.
$('#toc').toc({ minimumHeaders: 0, listType: 'ul', showSpeed: 0, headers: 'h2,h3,h4' });
});
< / script >
< div id = "toc" > < / div >
< a target = "_blank" href = "https://github.com/pmd/pmd/blob/master/docs/pages/pmd/userdocs/extending/defining_properties.md" class = "btn btn-default githubEditButton" role = "button" > < i class = "fa fa-github fa-lg" > < / i > Edit me< / a >
2018-11-22 19:43:38 +00:00
< h2 id = "defining-properties" > Defining properties< / h2 >
2018-06-16 20:39:36 +00:00
< p > If you’ re a rule developer, you may want to think about what would be useful for a user of your rule to parameterise. It could be a numeric report level, a boolean flag changing the behaviour of your rule… PMD ships with many types of properties ready to use!< / p >
< h3 id = "overview-of-properties" > Overview of properties< / h3 >
< p > The basic thing you need to do as a developer is to define a < strong > property descriptor< / strong > and declare that your rule uses it. A property descriptor defines a number of attributes for your property:< / p >
< ul >
< li > Its < em > name< / em > , with which the user will refer to your property;< / li >
< li > Its < em > description< / em > , for documentation purposes;< / li >
< li > Its < em > default value< / em > < / li >
< / ul >
< p > Don’ t worry, all of these attributes can be specified in a single Java statement (or xml element for XPath rules).< / p >
< p > Without further ado, here is the list of available (single-value) properties:< / p >
< table >
< thead >
< tr >
< th > Class name< / th >
< th > Value type< / th >
< / tr >
< / thead >
< tbody >
< tr >
< td > IntegerProperty< / td >
< td > int< / td >
< / tr >
< tr >
< td > DoubleProperty< / td >
< td > double< / td >
< / tr >
< tr >
< td > FloatProperty< / td >
< td > float< / td >
< / tr >
< tr >
< td > LongProperty< / td >
< td > long< / td >
< / tr >
< tr >
< td > EnumeratedProperty< < em > E< / em > > < / td >
< td > < em > E< / em > < / td >
< / tr >
< tr >
< td > StringProperty< / td >
< td > String< / td >
< / tr >
< tr >
< td > BooleanProperty< / td >
< td > boolean< / td >
< / tr >
< tr >
< td > CharacterProperty< / td >
< td > char< / td >
< / tr >
< tr >
< td > FileProperty< / td >
< td > java.io.File< / td >
< / tr >
< tr >
< td > MethodProperty< / td >
< td > java.lang.reflect.Method< / td >
< / tr >
< tr >
< td > TypeProperty< / td >
< td > java.lang.Class< ?> < / td >
< / tr >
< tr >
< td > RegexProperty< / td >
< td > java.util.regex.Pattern< / td >
< / tr >
< / tbody >
< / table >
< p > Each of these is complemented by a multivalued variant, whose name ends with “MultiProperty”, and which returns a list of values, e.g.< / p >
< table >
< thead >
< tr >
< th > Class name< / th >
< th > Value type< / th >
< / tr >
< / thead >
< tbody >
< tr >
< td > LongMultiProperty< / td >
< td > List< Long> < / td >
< / tr >
< tr >
< td > EnumeratedMultiProperty< < em > E< / em > > < / td >
< td > List< < em > E< / em > > < / td >
< / tr >
< / tbody >
< / table >
< p > Note that RegexProperty doesn’ t have a multivalued variant, since the delimiters could be part of a specific value.< / p >
< h3 id = "for-java-rules" > For Java rules< / h3 >
< p > The procedure to define a property is quite straightforward:< / p >
< ul >
< li > Create a property descriptor of the type you want, using its builder;< / li >
2019-07-28 08:45:42 +00:00
< li > Call < a href = "https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.18.0/net/sourceforge/pmd/properties/PropertySource.html#definePropertyDescriptor(net.sourceforge.pmd.properties.PropertyDescriptor)" > < code class = "highlighter-rouge" > definePropertyDescriptor(PropertyDescriptor)< / code > < / a > ` in the rule’ s noarg constructor.< / li >
2018-06-16 20:39:36 +00:00
< / ul >
2019-07-28 08:45:42 +00:00
< p > You can then retrieve the value of the property at any time using < a href = "https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.18.0/net/sourceforge/pmd/properties/PropertySource.html#getProperty(net.sourceforge.pmd.properties.PropertyDescriptor)" > < code class = "highlighter-rouge" > getProperty(PropertyDescriptor)< / code > < / a > .< / p >
2018-06-16 20:39:36 +00:00
< h4 id = "creating-a-descriptor" > Creating a descriptor< / h4 >
< p > From version 6.0.0 on, properties can be built using specific < strong > builders< / strong > . For example, to build a string property, you’ d call< / p >
< div class = "language-java highlighter-rouge" > < div class = "highlight" > < pre class = "highlight" > < code > < span class = "n" > StringProperty< / span > < span class = "o" > .< / span > < span class = "na" > named< / span > < span class = "o" > (< / span > < span class = "s" > "myProperty"< / span > < span class = "o" > )< / span >
< span class = "o" > .< / span > < span class = "na" > desc< / span > < span class = "o" > (< / span > < span class = "s" > "This is my property"< / span > < span class = "o" > )< / span >
< span class = "o" > .< / span > < span class = "na" > defaultValue< / span > < span class = "o" > (< / span > < span class = "s" > "foo"< / span > < span class = "o" > )< / span >
< span class = "o" > .< / span > < span class = "na" > build< / span > < span class = "o" > ();< / span >
< / code > < / pre > < / div > < / div >
< p > This is fairly more readable than a constructor call, but keep in mind the description and the default value are not optional.< / p >
< div class = "alert alert-info" role = "alert" > < i class = "fa fa-info-circle" > < / i > < b > Note:< / b > The constructors may be deprecated in a future release, so please use the builders instead.< / div >
< p > For < strong > numeric properties< / strong > , you’ d add a call to < code class = "highlighter-rouge" > range< / code > to define the range of acceptable values, e.g.< / p >
< div class = "language-java highlighter-rouge" > < div class = "highlight" > < pre class = "highlight" > < code > < span class = "n" > IntegerProperty< / span > < span class = "o" > .< / span > < span class = "na" > named< / span > < span class = "o" > (< / span > < span class = "s" > "myIntProperty"< / span > < span class = "o" > )< / span >
< span class = "o" > .< / span > < span class = "na" > desc< / span > < span class = "o" > (< / span > < span class = "s" > "This is my property"< / span > < span class = "o" > )< / span >
< span class = "o" > .< / span > < span class = "na" > defaultValue< / span > < span class = "o" > (< / span > < span class = "mi" > 3< / span > < span class = "o" > )< / span >
< span class = "o" > .< / span > < span class = "na" > range< / span > < span class = "o" > (< / span > < span class = "mi" > 0< / span > < span class = "o" > ,< / span > < span class = "mi" > 100< / span > < span class = "o" > )< / span >
< span class = "o" > .< / span > < span class = "na" > build< / span > < span class = "o" > ();< / span >
< / code > < / pre > < / div > < / div >
< p > < strong > Enumerated properties< / strong > are a bit less straightforward to define, though they are arguably more powerful. These properties don’ t have a specific value type, instead, you can choose any type of value, provided the values are from a closed set. To make that actionable, you give string labels to each of the acceptable values, and the user will provide one of those labels as a value in the XML. The property will give you back the associated value, not the label. Here’ s an example:< / p >
< div class = "language-java highlighter-rouge" > < div class = "highlight" > < pre class = "highlight" > < code > < span class = "kd" > static< / span > < span class = "n" > Map< / span > < span class = "o" > < < / span > < span class = "n" > String< / span > < span class = "o" > ,< / span > < span class = "n" > ModeStrategy< / span > < span class = "o" > > < / span > < span class = "n" > map< / span > < span class = "o" > =< / span > < span class = "k" > new< / span > < span class = "n" > HashMap< / span > < span class = "o" > < > ();< / span >
< span class = "kd" > static< / span > < span class = "o" > {< / span >
< span class = "n" > map< / span > < span class = "o" > .< / span > < span class = "na" > put< / span > < span class = "o" > (< / span > < span class = "s" > "easyMode"< / span > < span class = "o" > ,< / span > < span class = "k" > new< / span > < span class = "n" > EasyStrategy< / span > < span class = "o" > ());< / span >
< span class = "n" > map< / span > < span class = "o" > .< / span > < span class = "na" > put< / span > < span class = "o" > (< / span > < span class = "s" > "hardMode"< / span > < span class = "o" > ,< / span > < span class = "k" > new< / span > < span class = "n" > HardStrategy< / span > < span class = "o" > ());< / span >
< span class = "o" > }< / span >
< span class = "kd" > static< / span > < span class = "n" > EnumeratedProperty< / span > < span class = "o" > < < / span > < span class = "n" > ModeStrategy< / span > < span class = "o" > > < / span > < span class = "n" > modeProperty< / span >
< span class = "o" > =< / span > < span class = "n" > EnumeratedProperty< / span > < span class = "o" > .< < / span > < span class = "n" > ModeStrategy< / span > < span class = "o" > > < / span > < span class = "n" > named< / span > < span class = "o" > (< / span > < span class = "s" > "modeProperty"< / span > < span class = "o" > )< / span >
< span class = "o" > .< / span > < span class = "na" > desc< / span > < span class = "o" > (< / span > < span class = "s" > "This is my property"< / span > < span class = "o" > )< / span >
< span class = "o" > .< / span > < span class = "na" > defaultValue< / span > < span class = "o" > (< / span > < span class = "k" > new< / span > < span class = "n" > EasyStrategy< / span > < span class = "o" > ())< / span >
< span class = "o" > .< / span > < span class = "na" > mappings< / span > < span class = "o" > (< / span > < span class = "n" > map< / span > < span class = "o" > )< / span >
< span class = "o" > .< / span > < span class = "na" > type< / span > < span class = "o" > (< / span > < span class = "n" > ModeStrategy< / span > < span class = "o" > .< / span > < span class = "na" > class< / span > < span class = "o" > )< / span >
< span class = "o" > .< / span > < span class = "na" > build< / span > < span class = "o" > ();< / span >
< / code > < / pre > < / div > < / div >
< p > Note that you’ re required to fill in the type of the values too, using < code class = "highlighter-rouge" > type()< / code > .< / p >
< h4 id = "example" > Example< / h4 >
< p > You can see an example of properties used in a PMD rule < a href = "https://github.com/pmd/pmd/blob/ac2ff0f6af8d16f739584ba8d00b7ea1a6311ccc/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/AvoidDeeplyNestedIfStmtsRule.java#L17" > here< / a > .
There are several things to notice here:< / p >
< ul >
< li > The property descriptor is declared < code class = "highlighter-rouge" > static final< / code > , which should generally be the case, as descriptors are immutable and can be shared between instances of the same rule;< / li >
< li > The property is declared using < code class = "highlighter-rouge" > definePropertyDescriptor< / code > < em > in the constructor< / em > , which ensures the property gets recognised by PMD;< / li >
< li > The value of the property is < em > not retrieved in the constructor< / em > , but in one of the < code class = "highlighter-rouge" > visit< / code > methods (typically on the highest node in the tree, since the property doesn’ t change).< / li >
< / ul >
< h3 id = "for-xpath-rules" > For XPath rules< / h3 >
< p > XPath rules can also define their own properties. To do so, you must add a < code class = "highlighter-rouge" > property< / code > element in the < code class = "highlighter-rouge" > properties< / code > element of your rule, which < strong > declares the < code class = "highlighter-rouge" > type< / code > attribute< / strong > . This attribute conditions what type the underlying property has, and can have the following values:< / p >
< table >
< thead >
< tr >
< th > < code class = "highlighter-rouge" > type< / code > attribute< / th >
< th > Property type< / th >
< / tr >
< / thead >
< tbody >
< tr >
< td > Integer< / td >
< td > IntegerProperty< / td >
< / tr >
< tr >
< td > Double< / td >
< td > DoubleProperty< / td >
< / tr >
< tr >
< td > Float< / td >
< td > FloatProperty< / td >
< / tr >
< tr >
< td > Long< / td >
< td > LongProperty< / td >
< / tr >
< tr >
< td > String< / td >
< td > StringProperty< / td >
< / tr >
< tr >
< td > Character< / td >
< td > CharacterProperty< / td >
< / tr >
< tr >
< td > Boolean< / td >
< td > BooleanProperty< / td >
< / tr >
< tr >
< td > Class< / td >
< td > TypeProperty< / td >
< / tr >
< tr >
< td > Regex< / td >
< td > RegexProperty< / td >
< / tr >
< / tbody >
< / table >
< p > Note that enumerated properties are not available in XPath rules (yet?).< / p >
< p > Properties defined in XPath also < em > must< / em > declare the < code class = "highlighter-rouge" > description< / code > attribute. Numeric properties also expect the < code class = "highlighter-rouge" > min< / code > and < code class = "highlighter-rouge" > max< / code > attributes. Here are a few examples to sum it up:< / p >
< div class = "language-xml highlighter-rouge" > < div class = "highlight" > < pre class = "highlight" > < code > < span class = "nt" > < property< / span > < span class = "na" > name=< / span > < span class = "s" > "stringProp"< / span > < span class = "na" > type=< / span > < span class = "s" > "Boolean"< / span > < span class = "na" > value=< / span > < span class = "s" > "true"< / span > < span class = "na" > description=< / span > < span class = "s" > "A BooleanProperty."< / span > < span class = "nt" > /> < / span >
< span class = "nt" > < property< / span > < span class = "na" > name=< / span > < span class = "s" > "intProp"< / span > < span class = "na" > type=< / span > < span class = "s" > "Integer"< / span > < span class = "na" > value=< / span > < span class = "s" > "3"< / span > < span class = "na" > min=< / span > < span class = "s" > "1"< / span > < span class = "na" > max=< / span > < span class = "s" > "20"< / span > < span class = "na" > description=< / span > < span class = "s" > "An IntegerProperty."< / span > < span class = "nt" > /> < / span >
< / code > < / pre > < / div > < / div >
< p > You can then use the property in XPath with the syntax < code class = "highlighter-rouge" > $propertyName< / code > , for example:< / p >
< div class = "language-xml highlighter-rouge" > < div class = "highlight" > < pre class = "highlight" > < code > < span class = "nt" > < rule< / span > < span class = "na" > name=< / span > < span class = "s" > "MyXpathRule"< / span > < span class = "err" > ...< / span > < span class = "nt" > > < / span >
< span class = "nt" > < properties> < / span >
< span class = "nt" > < property< / span > < span class = "na" > name=< / span > < span class = "s" > "maxStatements"< / span > < span class = "na" > type=< / span > < span class = "s" > "Integer"< / span > < span class = "na" > value=< / span > < span class = "s" > "10"< / span > < span class = "na" > min=< / span > < span class = "s" > "1"< / span > < span class = "na" > max=< / span > < span class = "s" > "40"< / span >
< span class = "na" > description=< / span > < span class = "s" > "Max number of statements per method"< / span > < span class = "nt" > /> < / span >
< span class = "nt" > < property< / span > < span class = "na" > name=< / span > < span class = "s" > "xpath"< / span > < span class = "nt" > > < / span >
< span class = "cp" > < ![CDATA[
//MethodDeclaration/Block[count(//BlockStatement) > < / span > $maxStatements]
]]> < span class = "nt" > < /property> < / span >
< span class = "nt" > < /properties> < / span >
< span class = "nt" > < /rule> < / span >
< / code > < / pre > < / div > < / div >
< h4 id = "multivalued-properties" > Multivalued properties< / h4 >
< p > Multivalued properties are also allowed and their < code class = "highlighter-rouge" > type< / code > attribute has the form < code class = "highlighter-rouge" > List[Boolean]< / code > or < code class = "highlighter-rouge" > List[Character]< / code > , with every above type allowed. These properties < strong > require XPath 2.0< / strong > to work properly, and make use of the < strong > sequence datatype< / strong > provided by that language. You thus need to set the < code class = "highlighter-rouge" > version< / code > property to < code class = "highlighter-rouge" > 2.0< / code > to use them. Properties can also declare the < code class = "highlighter-rouge" > delimiter< / code > attribute.< / p >
< div class = "language-xml highlighter-rouge" > < div class = "highlight" > < pre class = "highlight" > < code > < span class = "nt" > < rule< / span > < span class = "na" > name=< / span > < span class = "s" > "MyXpathRule"< / span > < span class = "err" > ...< / span > < span class = "nt" > > < / span >
< span class = "nt" > < properties> < / span >
< span class = "nt" > < property< / span > < span class = "na" > name=< / span > < span class = "s" > "version"< / span > < span class = "na" > value=< / span > < span class = "s" > "2.0"< / span > < span class = "nt" > /> < / span >
< span class = "nt" > < property< / span > < span class = "na" > name=< / span > < span class = "s" > "intProp"< / span > < span class = "na" > type=< / span > < span class = "s" > "List[Integer]"< / span > < span class = "na" > value=< / span > < span class = "s" > "1,2,5"< / span > < span class = "na" > description=< / span > < span class = "s" > "An IntegerMultiProperty."< / span > < span class = "nt" > /> < / span >
< span class = "nt" > < property< / span > < span class = "na" > name=< / span > < span class = "s" > "reportedIdentifiers"< / span > < span class = "na" > type=< / span > < span class = "s" > "List[String]"< / span > < span class = "na" > value=< / span > < span class = "s" > "foo$bar"< / span > < span class = "na" > delimiter=< / span > < span class = "s" > "$"< / span >
< span class = "na" > description=< / span > < span class = "s" > "A StringMultiProperty."< / span > < span class = "nt" > /> < / span >
< span class = "nt" > < property< / span > < span class = "na" > name=< / span > < span class = "s" > "xpath"< / span > < span class = "nt" > > < / span >
< span class = "cp" > < ![CDATA[
//VariableDeclaratorId[@Image = $reportedIdentifiers]
]]> < / span > < span class = "nt" > < /property> < / span >
< span class = "nt" > < /properties> < / span >
< span class = "nt" > < /rule> < / span >
< / code > < / pre > < / div > < / div >
< p > Notice that in the example above, < code class = "highlighter-rouge" > @Image = $reportedIdentifiers< / code > doesn’ t test < code class = "highlighter-rouge" > @Image< / code > for equality with the whole sequence < code class = "highlighter-rouge" > ('foo', 'bar')< / code > , it tests whether the sequence < em > contains< / em > < code class = "highlighter-rouge" > @Image< / code > . That is, the above rule will report all variables named < code class = "highlighter-rouge" > foo< / code > or < code class = "highlighter-rouge" > bar< / code > . All other XPath 2.0 < a href = "https://www.w3.org/TR/xpath-functions/#sequence-functions" > functions operating on sequences< / a > are supported.< / p >
2018-11-22 19:43:38 +00:00
2018-06-16 20:39:36 +00:00
< div class = "tags" >
< b > Tags: < / b >
< a href = "tag_extending.html" class = "btn btn-default navbar-btn cursorNorm" role = "button" > extending< / a >
< a href = "tag_userdocs.html" class = "btn btn-default navbar-btn cursorNorm" role = "button" > userdocs< / a >
< / div >
< / div >
< hr class = "shaded" / >
< footer >
< div class = "row" >
< div class = "col-lg-12 footer" >
2019-01-06 21:49:33 +00:00
© 2019 PMD Open Source Project. All rights reserved. < br / >
2019-09-14 00:12:47 +00:00
< span > Page last updated:< / span > December 2017 (6.0.0)< br / > Site last generated: Sep 14, 2019 < br / >
2018-06-16 20:39:36 +00:00
< p > < img src = "images/pmd-logo-small.png" alt = "Company logo" / > < / p >
< / div >
< / div >
< / footer >
< / div >
<!-- /.row -->
< / div >
<!-- /.container -->
< / div >
< / div >
< / body >
< / html >