Sorry, but the page you were trying to view does not exist. Check the URL for correctness, or try using keyword search using our search bar.
+ + + + + + + + +diff --git a/404.html b/404.html new file mode 100644 index 0000000000..29fd3ea54b --- /dev/null +++ b/404.html @@ -0,0 +1,1440 @@ + + +
+ + + + + +Sorry, but the page you were trying to view does not exist. Check the URL for correctness, or try using keyword search using our search bar.
+ + + + + + + + +PMD is a static source code analyzer. It finds common programming flaws like +unused variables, empty catch blocks, unnecessary object creation, and +so forth. It’s mainly concerned with Java and Apex, but supports six other +languages.
+ +PMD features many built-in checks (in PMD lingo, rules), which are documented +for each language in our Rule references. We +also support an extensive API to write your own rules, +which you can do either in Java or as a self-contained XPath query.
+ +PMD is most useful when integrated into your build process. It can then be +used as a quality gate, to enforce a coding standard for your codebase. Among other +things, PMD can be run:
+CPD, the copy-paste detector, is also distributed with PMD. You can also use it +in a variety of ways, which are documented here.
+ +The latest release of PMD can be downloaded from our Github releases page.
+ +The rest of this page exposes the contents of the documentation site thematically, +which you can further scope down using the blue filter buttons. To navigate the site, +you may also use the search bar in the top right, or the sidebar on the left.
+ ++ These pages summarize the gist of PMD usage to get you started quickly. +
++ Pick your language to find out about the rule it supports. +
++ These pages document the process of writing and testing custom rules and metrics for PMD. +
++ Learn how to build effective and versatile rulesets. +
++ If you'd like to help us build PMD, these topics may interest you. See you around! +
++ These pages describe solutions that integrate PMD within your build process. +
++ +
+")[0],f=t.each;p.style.cssText="background-color:rgba(1,1,1,.5)",d.rgba=p.style.backgroundColor.indexOf("rgba")>-1,f(c,function(t,e){e.cache="_"+t,e.props.alpha={idx:3,type:"percent",def:1}}),h.fn=t.extend(h.prototype,{parse:function(n,a,r,l){if(n===e)return this._rgba=[null,null,null,null],this;(n.jquery||n.nodeType)&&(n=t(n).css(a),a=e);var u=this,d=t.type(n),p=this._rgba=[];return a!==e&&(n=[n,a,r,l],d="array"),"string"===d?this.parse(s(n)||o._default):"array"===d?(f(c.rgba.props,function(t,e){p[e.idx]=i(n[e.idx],e)}),this):"object"===d?(n instanceof h?f(c,function(t,e){n[e.cache]&&(u[e.cache]=n[e.cache].slice())}):f(c,function(e,s){var o=s.cache;f(s.props,function(t,e){if(!u[o]&&s.to){if("alpha"===t||null==n[t])return;u[o]=s.to(u._rgba)}u[o][e.idx]=i(n[t],e,!0)}),u[o]&&0>t.inArray(null,u[o].slice(0,3))&&(u[o][3]=1,s.from&&(u._rgba=s.from(u[o])))}),this):e},is:function(t){var i=h(t),s=!0,n=this;return f(c,function(t,o){var a,r=i[o.cache];return r&&(a=n[o.cache]||o.to&&o.to(n._rgba)||[],f(o.props,function(t,i){return null!=r[i.idx]?s=r[i.idx]===a[i.idx]:e})),s}),s},_space:function(){var t=[],e=this;return f(c,function(i,s){e[s.cache]&&t.push(i)}),t.pop()},transition:function(t,e){var s=h(t),n=s._space(),o=c[n],a=0===this.alpha()?h("transparent"):this,r=a[o.cache]||o.to(a._rgba),l=r.slice();return s=s[o.cache],f(o.props,function(t,n){var o=n.idx,a=r[o],h=s[o],c=u[n.type]||{};null!==h&&(null===a?l[o]=h:(c.mod&&(h-a>c.mod/2?a+=c.mod:a-h>c.mod/2&&(a-=c.mod)),l[o]=i((h-a)*e+a,n)))}),this[n](l)},blend:function(e){if(1===this._rgba[3])return this;var i=this._rgba.slice(),s=i.pop(),n=h(e)._rgba;return h(t.map(i,function(t,e){return(1-s)*n[e]+s*t}))},toRgbaString:function(){var e="rgba(",i=t.map(this._rgba,function(t,e){return null==t?e>2?1:0:t});return 1===i[3]&&(i.pop(),e="rgb("),e+i.join()+")"},toHslaString:function(){var e="hsla(",i=t.map(this.hsla(),function(t,e){return null==t&&(t=e>2?1:0),e&&3>e&&(t=Math.round(100*t)+"%"),t});return 1===i[3]&&(i.pop(),e="hsl("),e+i.join()+")"},toHexString:function(e){var i=this._rgba.slice(),s=i.pop();return e&&i.push(~~(255*s)),"#"+t.map(i,function(t){return t=(t||0).toString(16),1===t.length?"0"+t:t}).join("")},toString:function(){return 0===this._rgba[3]?"transparent":this.toRgbaString()}}),h.fn.parse.prototype=h.fn,c.hsla.to=function(t){if(null==t[0]||null==t[1]||null==t[2])return[null,null,null,t[3]];var e,i,s=t[0]/255,n=t[1]/255,o=t[2]/255,a=t[3],r=Math.max(s,n,o),l=Math.min(s,n,o),h=r-l,c=r+l,u=.5*c;return e=l===r?0:s===r?60*(n-o)/h+360:n===r?60*(o-s)/h+120:60*(s-n)/h+240,i=0===h?0:.5>=u?h/c:h/(2-c),[Math.round(e)%360,i,u,null==a?1:a]},c.hsla.from=function(t){if(null==t[0]||null==t[1]||null==t[2])return[null,null,null,t[3]];var e=t[0]/360,i=t[1],s=t[2],o=t[3],a=.5>=s?s*(1+i):s+i-s*i,r=2*s-a;return[Math.round(255*n(r,a,e+1/3)),Math.round(255*n(r,a,e)),Math.round(255*n(r,a,e-1/3)),o]},f(c,function(s,n){var o=n.props,a=n.cache,l=n.to,c=n.from;h.fn[s]=function(s){if(l&&!this[a]&&(this[a]=l(this._rgba)),s===e)return this[a].slice();var n,r=t.type(s),u="array"===r||"object"===r?s:arguments,d=this[a].slice();return f(o,function(t,e){var s=u["object"===r?t:e.idx];null==s&&(s=d[e.idx]),d[e.idx]=i(s,e)}),c?(n=h(c(d)),n[a]=d,n):h(d)},f(o,function(e,i){h.fn[e]||(h.fn[e]=function(n){var o,a=t.type(n),l="alpha"===e?this._hsla?"hsla":"rgba":s,h=this[l](),c=h[i.idx];return"undefined"===a?c:("function"===a&&(n=n.call(this,c),a=t.type(n)),null==n&&i.empty?this:("string"===a&&(o=r.exec(n),o&&(n=c+parseFloat(o[2])*("+"===o[1]?1:-1))),h[i.idx]=n,this[l](h)))})})}),h.hook=function(e){var i=e.split(" ");f(i,function(e,i){t.cssHooks[i]={set:function(e,n){var o,a,r="";if("transparent"!==n&&("string"!==t.type(n)||(o=s(n)))){if(n=h(o||n),!d.rgba&&1!==n._rgba[3]){for(a="backgroundColor"===i?e.parentNode:e;(""===r||"transparent"===r)&&a&&a.style;)try{r=t.css(a,"backgroundColor"),a=a.parentNode}catch(l){}n=n.blend(r&&"transparent"!==r?r:"_default")}n=n.toRgbaString()}try{e.style[i]=n}catch(l){}}},t.fx.step[i]=function(e){e.colorInit||(e.start=h(e.elem,i),e.end=h(e.end),e.colorInit=!0),t.cssHooks[i].set(e.elem,e.start.transition(e.end,e.pos))}})},h.hook(a),t.cssHooks.borderColor={expand:function(t){var e={};return f(["Top","Right","Bottom","Left"],function(i,s){e["border"+s+"Color"]=t}),e}},o=t.Color.names={aqua:"#00ffff",black:"#000000",blue:"#0000ff",fuchsia:"#ff00ff",gray:"#808080",green:"#008000",lime:"#00ff00",maroon:"#800000",navy:"#000080",olive:"#808000",purple:"#800080",red:"#ff0000",silver:"#c0c0c0",teal:"#008080",white:"#ffffff",yellow:"#ffff00",transparent:[null,null,null,0],_default:"#ffffff"}}(n),function(){function e(e){var i,s,n=e.ownerDocument.defaultView?e.ownerDocument.defaultView.getComputedStyle(e,null):e.currentStyle,o={};if(n&&n.length&&n[0]&&n[n[0]])for(s=n.length;s--;)i=n[s],"string"==typeof n[i]&&(o[t.camelCase(i)]=n[i]);else for(i in n)"string"==typeof n[i]&&(o[i]=n[i]);return o}function i(e,i){var s,n,a={};for(s in i)n=i[s],e[s]!==n&&(o[s]||(t.fx.step[s]||!isNaN(parseFloat(n)))&&(a[s]=n));return a}var s=["add","remove","toggle"],o={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};t.each(["borderLeftStyle","borderRightStyle","borderBottomStyle","borderTopStyle"],function(e,i){t.fx.step[i]=function(t){("none"!==t.end&&!t.setAttr||1===t.pos&&!t.setAttr)&&(n.style(t.elem,i,t.end),t.setAttr=!0)}}),t.fn.addBack||(t.fn.addBack=function(t){return this.add(null==t?this.prevObject:this.prevObject.filter(t))}),t.effects.animateClass=function(n,o,a,r){var l=t.speed(o,a,r);return this.queue(function(){var o,a=t(this),r=a.attr("class")||"",h=l.children?a.find("*").addBack():a;h=h.map(function(){var i=t(this);return{el:i,start:e(this)}}),o=function(){t.each(s,function(t,e){n[e]&&a[e+"Class"](n[e])})},o(),h=h.map(function(){return this.end=e(this.el[0]),this.diff=i(this.start,this.end),this}),a.attr("class",r),h=h.map(function(){var e=this,i=t.Deferred(),s=t.extend({},l,{queue:!1,complete:function(){i.resolve(e)}});return this.el.animate(this.diff,s),i.promise()}),t.when.apply(t,h.get()).done(function(){o(),t.each(arguments,function(){var e=this.el;t.each(this.diff,function(t){e.css(t,"")})}),l.complete.call(a[0])})})},t.fn.extend({addClass:function(e){return function(i,s,n,o){return s?t.effects.animateClass.call(this,{add:i},s,n,o):e.apply(this,arguments)}}(t.fn.addClass),removeClass:function(e){return function(i,s,n,o){return arguments.length>1?t.effects.animateClass.call(this,{remove:i},s,n,o):e.apply(this,arguments)}}(t.fn.removeClass),toggleClass:function(e){return function(i,s,n,o,a){return"boolean"==typeof s||void 0===s?n?t.effects.animateClass.call(this,s?{add:i}:{remove:i},n,o,a):e.apply(this,arguments):t.effects.animateClass.call(this,{toggle:i},s,n,o)}}(t.fn.toggleClass),switchClass:function(e,i,s,n,o){return t.effects.animateClass.call(this,{add:i,remove:e},s,n,o)}})}(),function(){function n(e,i,s,n){return t.isPlainObject(e)&&(i=e,e=e.effect),e={effect:e},null==i&&(i={}),t.isFunction(i)&&(n=i,s=null,i={}),("number"==typeof i||t.fx.speeds[i])&&(n=s,s=i,i={}),t.isFunction(s)&&(n=s,s=null),i&&t.extend(e,i),s=s||i.duration,e.duration=t.fx.off?0:"number"==typeof s?s:s in t.fx.speeds?t.fx.speeds[s]:t.fx.speeds._default,e.complete=n||i.complete,e}function o(e){return!e||"number"==typeof e||t.fx.speeds[e]?!0:"string"!=typeof e||t.effects.effect[e]?t.isFunction(e)?!0:"object"!=typeof e||e.effect?!1:!0:!0}function a(t,e){var i=e.outerWidth(),s=e.outerHeight(),n=/^rect\((-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto)\)$/,o=n.exec(t)||["",0,i,s,0];return{top:parseFloat(o[1])||0,right:"auto"===o[2]?i:parseFloat(o[2]),bottom:"auto"===o[3]?s:parseFloat(o[3]),left:parseFloat(o[4])||0}}t.expr&&t.expr.filters&&t.expr.filters.animated&&(t.expr.filters.animated=function(e){return function(i){return!!t(i).data(s)||e(i)}}(t.expr.filters.animated)),t.uiBackCompat!==!1&&t.extend(t.effects,{save:function(t,i){for(var s=0,n=i.length;n>s;s++)null!==i[s]&&t.data(e+i[s],t[0].style[i[s]])},restore:function(t,i){for(var s,n=0,o=i.length;o>n;n++)null!==i[n]&&(s=t.data(e+i[n]),t.css(i[n],s))},setMode:function(t,e){return"toggle"===e&&(e=t.is(":hidden")?"show":"hide"),e},createWrapper:function(e){if(e.parent().is(".ui-effects-wrapper"))return e.parent();var i={width:e.outerWidth(!0),height:e.outerHeight(!0),"float":e.css("float")},s=t("
").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),n={width:e.width(),height:e.height()},o=document.activeElement;try{o.id}catch(a){o=document.body}return e.wrap(s),(e[0]===o||t.contains(e[0],o))&&t(o).trigger("focus"),s=e.parent(),"static"===e.css("position")?(s.css({position:"relative"}),e.css({position:"relative"})):(t.extend(i,{position:e.css("position"),zIndex:e.css("z-index")}),t.each(["top","left","bottom","right"],function(t,s){i[s]=e.css(s),isNaN(parseInt(i[s],10))&&(i[s]="auto")}),e.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})),e.css(n),s.css(i).show()},removeWrapper:function(e){var i=document.activeElement;return e.parent().is(".ui-effects-wrapper")&&(e.parent().replaceWith(e),(e[0]===i||t.contains(e[0],i))&&t(i).trigger("focus")),e}}),t.extend(t.effects,{version:"1.12.1",define:function(e,i,s){return s||(s=i,i="effect"),t.effects.effect[e]=s,t.effects.effect[e].mode=i,s},scaledDimensions:function(t,e,i){if(0===e)return{height:0,width:0,outerHeight:0,outerWidth:0};var s="horizontal"!==i?(e||100)/100:1,n="vertical"!==i?(e||100)/100:1;return{height:t.height()*n,width:t.width()*s,outerHeight:t.outerHeight()*n,outerWidth:t.outerWidth()*s}},clipToBox:function(t){return{width:t.clip.right-t.clip.left,height:t.clip.bottom-t.clip.top,left:t.clip.left,top:t.clip.top}},unshift:function(t,e,i){var s=t.queue();e>1&&s.splice.apply(s,[1,0].concat(s.splice(e,i))),t.dequeue()},saveStyle:function(t){t.data(i,t[0].style.cssText)},restoreStyle:function(t){t[0].style.cssText=t.data(i)||"",t.removeData(i)},mode:function(t,e){var i=t.is(":hidden");return"toggle"===e&&(e=i?"show":"hide"),(i?"hide"===e:"show"===e)&&(e="none"),e},getBaseline:function(t,e){var i,s;switch(t[0]){case"top":i=0;break;case"middle":i=.5;break;case"bottom":i=1;break;default:i=t[0]/e.height}switch(t[1]){case"left":s=0;break;case"center":s=.5;break;case"right":s=1;break;default:s=t[1]/e.width}return{x:s,y:i}},createPlaceholder:function(i){var s,n=i.css("position"),o=i.position();return i.css({marginTop:i.css("marginTop"),marginBottom:i.css("marginBottom"),marginLeft:i.css("marginLeft"),marginRight:i.css("marginRight")}).outerWidth(i.outerWidth()).outerHeight(i.outerHeight()),/^(static|relative)/.test(n)&&(n="absolute",s=t("<"+i[0].nodeName+">").insertAfter(i).css({display:/^(inline|ruby)/.test(i.css("display"))?"inline-block":"block",visibility:"hidden",marginTop:i.css("marginTop"),marginBottom:i.css("marginBottom"),marginLeft:i.css("marginLeft"),marginRight:i.css("marginRight"),"float":i.css("float")}).outerWidth(i.outerWidth()).outerHeight(i.outerHeight()).addClass("ui-effects-placeholder"),i.data(e+"placeholder",s)),i.css({position:n,left:o.left,top:o.top}),s},removePlaceholder:function(t){var i=e+"placeholder",s=t.data(i);s&&(s.remove(),t.removeData(i))},cleanUp:function(e){t.effects.restoreStyle(e),t.effects.removePlaceholder(e)},setTransition:function(e,i,s,n){return n=n||{},t.each(i,function(t,i){var o=e.cssUnit(i);o[0]>0&&(n[i]=o[0]*s+o[1])}),n}}),t.fn.extend({effect:function(){function e(e){function n(){l.removeData(s),t.effects.cleanUp(l),"hide"===i.mode&&l.hide(),r()}function r(){t.isFunction(h)&&h.call(l[0]),t.isFunction(e)&&e()}var l=t(this);i.mode=u.shift(),t.uiBackCompat===!1||a?"none"===i.mode?(l[c](),r()):o.call(l[0],i,n):(l.is(":hidden")?"hide"===c:"show"===c)?(l[c](),r()):o.call(l[0],i,r)}var i=n.apply(this,arguments),o=t.effects.effect[i.effect],a=o.mode,r=i.queue,l=r||"fx",h=i.complete,c=i.mode,u=[],d=function(e){var i=t(this),n=t.effects.mode(i,c)||a;i.data(s,!0),u.push(n),a&&("show"===n||n===a&&"hide"===n)&&i.show(),a&&"none"===n||t.effects.saveStyle(i),t.isFunction(e)&&e()};return t.fx.off||!o?c?this[c](i.duration,h):this.each(function(){h&&h.call(this)}):r===!1?this.each(d).each(e):this.queue(l,d).queue(l,e)},show:function(t){return function(e){if(o(e))return t.apply(this,arguments);var i=n.apply(this,arguments);return i.mode="show",this.effect.call(this,i)}}(t.fn.show),hide:function(t){return function(e){if(o(e))return t.apply(this,arguments);var i=n.apply(this,arguments);return i.mode="hide",this.effect.call(this,i)}}(t.fn.hide),toggle:function(t){return function(e){if(o(e)||"boolean"==typeof e)return t.apply(this,arguments);var i=n.apply(this,arguments);return i.mode="toggle",this.effect.call(this,i)}}(t.fn.toggle),cssUnit:function(e){var i=this.css(e),s=[];return t.each(["em","px","%","pt"],function(t,e){i.indexOf(e)>0&&(s=[parseFloat(i),e])}),s},cssClip:function(t){return t?this.css("clip","rect("+t.top+"px "+t.right+"px "+t.bottom+"px "+t.left+"px)"):a(this.css("clip"),this)},transfer:function(e,i){var s=t(this),n=t(e.to),o="fixed"===n.css("position"),a=t("body"),r=o?a.scrollTop():0,l=o?a.scrollLeft():0,h=n.offset(),c={top:h.top-r,left:h.left-l,height:n.innerHeight(),width:n.innerWidth()},u=s.offset(),d=t("").appendTo("body").addClass(e.className).css({top:u.top-r,left:u.left-l,height:s.innerHeight(),width:s.innerWidth(),position:o?"fixed":"absolute"}).animate(c,e.duration,e.easing,function(){d.remove(),t.isFunction(i)&&i()})}}),t.fx.step.clip=function(e){e.clipInit||(e.start=t(e.elem).cssClip(),"string"==typeof e.end&&(e.end=a(e.end,e.elem)),e.clipInit=!0),t(e.elem).cssClip({top:e.pos*(e.end.top-e.start.top)+e.start.top,right:e.pos*(e.end.right-e.start.right)+e.start.right,bottom:e.pos*(e.end.bottom-e.start.bottom)+e.start.bottom,left:e.pos*(e.end.left-e.start.left)+e.start.left})}}(),function(){var e={};t.each(["Quad","Cubic","Quart","Quint","Expo"],function(t,i){e[i]=function(e){return Math.pow(e,t+2)}}),t.extend(e,{Sine:function(t){return 1-Math.cos(t*Math.PI/2)},Circ:function(t){return 1-Math.sqrt(1-t*t)},Elastic:function(t){return 0===t||1===t?t:-Math.pow(2,8*(t-1))*Math.sin((80*(t-1)-7.5)*Math.PI/15)},Back:function(t){return t*t*(3*t-2)},Bounce:function(t){for(var e,i=4;((e=Math.pow(2,--i))-1)/11>t;);return 1/Math.pow(4,3-i)-7.5625*Math.pow((3*e-2)/22-t,2)}}),t.each(e,function(e,i){t.easing["easeIn"+e]=i,t.easing["easeOut"+e]=function(t){return 1-i(1-t)},t.easing["easeInOut"+e]=function(t){return.5>t?i(2*t)/2:1-i(-2*t+2)/2}})}();var o=t.effects;t.effects.define("blind","hide",function(e,i){var s={up:["bottom","top"],vertical:["bottom","top"],down:["top","bottom"],left:["right","left"],horizontal:["right","left"],right:["left","right"]},n=t(this),o=e.direction||"up",a=n.cssClip(),r={clip:t.extend({},a)},l=t.effects.createPlaceholder(n);r.clip[s[o][0]]=r.clip[s[o][1]],"show"===e.mode&&(n.cssClip(r.clip),l&&l.css(t.effects.clipToBox(r)),r.clip=a),l&&l.animate(t.effects.clipToBox(r),e.duration,e.easing),n.animate(r,{queue:!1,duration:e.duration,easing:e.easing,complete:i})}),t.effects.define("bounce",function(e,i){var s,n,o,a=t(this),r=e.mode,l="hide"===r,h="show"===r,c=e.direction||"up",u=e.distance,d=e.times||5,p=2*d+(h||l?1:0),f=e.duration/p,m=e.easing,g="up"===c||"down"===c?"top":"left",_="up"===c||"left"===c,v=0,b=a.queue().length;for(t.effects.createPlaceholder(a),o=a.css(g),u||(u=a["top"===g?"outerHeight":"outerWidth"]()/3),h&&(n={opacity:1},n[g]=o,a.css("opacity",0).css(g,_?2*-u:2*u).animate(n,f,m)),l&&(u/=Math.pow(2,d-1)),n={},n[g]=o;d>v;v++)s={},s[g]=(_?"-=":"+=")+u,a.animate(s,f,m).animate(n,f,m),u=l?2*u:u/2;l&&(s={opacity:0},s[g]=(_?"-=":"+=")+u,a.animate(s,f,m)),a.queue(i),t.effects.unshift(a,b,p+1)}),t.effects.define("clip","hide",function(e,i){var s,n={},o=t(this),a=e.direction||"vertical",r="both"===a,l=r||"horizontal"===a,h=r||"vertical"===a;s=o.cssClip(),n.clip={top:h?(s.bottom-s.top)/2:s.top,right:l?(s.right-s.left)/2:s.right,bottom:h?(s.bottom-s.top)/2:s.bottom,left:l?(s.right-s.left)/2:s.left},t.effects.createPlaceholder(o),"show"===e.mode&&(o.cssClip(n.clip),n.clip=s),o.animate(n,{queue:!1,duration:e.duration,easing:e.easing,complete:i})}),t.effects.define("drop","hide",function(e,i){var s,n=t(this),o=e.mode,a="show"===o,r=e.direction||"left",l="up"===r||"down"===r?"top":"left",h="up"===r||"left"===r?"-=":"+=",c="+="===h?"-=":"+=",u={opacity:0};t.effects.createPlaceholder(n),s=e.distance||n["top"===l?"outerHeight":"outerWidth"](!0)/2,u[l]=h+s,a&&(n.css(u),u[l]=c+s,u.opacity=1),n.animate(u,{queue:!1,duration:e.duration,easing:e.easing,complete:i})}),t.effects.define("explode","hide",function(e,i){function s(){b.push(this),b.length===u*d&&n()}function n(){p.css({visibility:"visible"}),t(b).remove(),i()}var o,a,r,l,h,c,u=e.pieces?Math.round(Math.sqrt(e.pieces)):3,d=u,p=t(this),f=e.mode,m="show"===f,g=p.show().css("visibility","hidden").offset(),_=Math.ceil(p.outerWidth()/d),v=Math.ceil(p.outerHeight()/u),b=[];for(o=0;u>o;o++)for(l=g.top+o*v,c=o-(u-1)/2,a=0;d>a;a++)r=g.left+a*_,h=a-(d-1)/2,p.clone().appendTo("body").wrap("").css({position:"absolute",visibility:"visible",left:-a*_,top:-o*v}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:_,height:v,left:r+(m?h*_:0),top:l+(m?c*v:0),opacity:m?0:1}).animate({left:r+(m?0:h*_),top:l+(m?0:c*v),opacity:m?1:0},e.duration||500,e.easing,s)}),t.effects.define("fade","toggle",function(e,i){var s="show"===e.mode;t(this).css("opacity",s?0:1).animate({opacity:s?1:0},{queue:!1,duration:e.duration,easing:e.easing,complete:i})}),t.effects.define("fold","hide",function(e,i){var s=t(this),n=e.mode,o="show"===n,a="hide"===n,r=e.size||15,l=/([0-9]+)%/.exec(r),h=!!e.horizFirst,c=h?["right","bottom"]:["bottom","right"],u=e.duration/2,d=t.effects.createPlaceholder(s),p=s.cssClip(),f={clip:t.extend({},p)},m={clip:t.extend({},p)},g=[p[c[0]],p[c[1]]],_=s.queue().length;l&&(r=parseInt(l[1],10)/100*g[a?0:1]),f.clip[c[0]]=r,m.clip[c[0]]=r,m.clip[c[1]]=0,o&&(s.cssClip(m.clip),d&&d.css(t.effects.clipToBox(m)),m.clip=p),s.queue(function(i){d&&d.animate(t.effects.clipToBox(f),u,e.easing).animate(t.effects.clipToBox(m),u,e.easing),i()}).animate(f,u,e.easing).animate(m,u,e.easing).queue(i),t.effects.unshift(s,_,4)}),t.effects.define("highlight","show",function(e,i){var s=t(this),n={backgroundColor:s.css("backgroundColor")};"hide"===e.mode&&(n.opacity=0),t.effects.saveStyle(s),s.css({backgroundImage:"none",backgroundColor:e.color||"#ffff99"}).animate(n,{queue:!1,duration:e.duration,easing:e.easing,complete:i})}),t.effects.define("size",function(e,i){var s,n,o,a=t(this),r=["fontSize"],l=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"],h=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"],c=e.mode,u="effect"!==c,d=e.scale||"both",p=e.origin||["middle","center"],f=a.css("position"),m=a.position(),g=t.effects.scaledDimensions(a),_=e.from||g,v=e.to||t.effects.scaledDimensions(a,0);t.effects.createPlaceholder(a),"show"===c&&(o=_,_=v,v=o),n={from:{y:_.height/g.height,x:_.width/g.width},to:{y:v.height/g.height,x:v.width/g.width}},("box"===d||"both"===d)&&(n.from.y!==n.to.y&&(_=t.effects.setTransition(a,l,n.from.y,_),v=t.effects.setTransition(a,l,n.to.y,v)),n.from.x!==n.to.x&&(_=t.effects.setTransition(a,h,n.from.x,_),v=t.effects.setTransition(a,h,n.to.x,v))),("content"===d||"both"===d)&&n.from.y!==n.to.y&&(_=t.effects.setTransition(a,r,n.from.y,_),v=t.effects.setTransition(a,r,n.to.y,v)),p&&(s=t.effects.getBaseline(p,g),_.top=(g.outerHeight-_.outerHeight)*s.y+m.top,_.left=(g.outerWidth-_.outerWidth)*s.x+m.left,v.top=(g.outerHeight-v.outerHeight)*s.y+m.top,v.left=(g.outerWidth-v.outerWidth)*s.x+m.left),a.css(_),("content"===d||"both"===d)&&(l=l.concat(["marginTop","marginBottom"]).concat(r),h=h.concat(["marginLeft","marginRight"]),a.find("*[width]").each(function(){var i=t(this),s=t.effects.scaledDimensions(i),o={height:s.height*n.from.y,width:s.width*n.from.x,outerHeight:s.outerHeight*n.from.y,outerWidth:s.outerWidth*n.from.x},a={height:s.height*n.to.y,width:s.width*n.to.x,outerHeight:s.height*n.to.y,outerWidth:s.width*n.to.x};n.from.y!==n.to.y&&(o=t.effects.setTransition(i,l,n.from.y,o),a=t.effects.setTransition(i,l,n.to.y,a)),n.from.x!==n.to.x&&(o=t.effects.setTransition(i,h,n.from.x,o),a=t.effects.setTransition(i,h,n.to.x,a)),u&&t.effects.saveStyle(i),i.css(o),i.animate(a,e.duration,e.easing,function(){u&&t.effects.restoreStyle(i)})})),a.animate(v,{queue:!1,duration:e.duration,easing:e.easing,complete:function(){var e=a.offset();0===v.opacity&&a.css("opacity",_.opacity),u||(a.css("position","static"===f?"relative":f).offset(e),t.effects.saveStyle(a)),i()}})}),t.effects.define("scale",function(e,i){var s=t(this),n=e.mode,o=parseInt(e.percent,10)||(0===parseInt(e.percent,10)?0:"effect"!==n?0:100),a=t.extend(!0,{from:t.effects.scaledDimensions(s),to:t.effects.scaledDimensions(s,o,e.direction||"both"),origin:e.origin||["middle","center"]},e);e.fade&&(a.from.opacity=1,a.to.opacity=0),t.effects.effect.size.call(this,a,i)}),t.effects.define("puff","hide",function(e,i){var s=t.extend(!0,{},e,{fade:!0,percent:parseInt(e.percent,10)||150});t.effects.effect.scale.call(this,s,i)}),t.effects.define("pulsate","show",function(e,i){var s=t(this),n=e.mode,o="show"===n,a="hide"===n,r=o||a,l=2*(e.times||5)+(r?1:0),h=e.duration/l,c=0,u=1,d=s.queue().length;for((o||!s.is(":visible"))&&(s.css("opacity",0).show(),c=1);l>u;u++)s.animate({opacity:c},h,e.easing),c=1-c;s.animate({opacity:c},h,e.easing),s.queue(i),t.effects.unshift(s,d,l+1)}),t.effects.define("shake",function(e,i){var s=1,n=t(this),o=e.direction||"left",a=e.distance||20,r=e.times||3,l=2*r+1,h=Math.round(e.duration/l),c="up"===o||"down"===o?"top":"left",u="up"===o||"left"===o,d={},p={},f={},m=n.queue().length;for(t.effects.createPlaceholder(n),d[c]=(u?"-=":"+=")+a,p[c]=(u?"+=":"-=")+2*a,f[c]=(u?"-=":"+=")+2*a,n.animate(d,h,e.easing);r>s;s++)n.animate(p,h,e.easing).animate(f,h,e.easing);n.animate(p,h,e.easing).animate(d,h/2,e.easing).queue(i),t.effects.unshift(n,m,l+1)}),t.effects.define("slide","show",function(e,i){var s,n,o=t(this),a={up:["bottom","top"],down:["top","bottom"],left:["right","left"],right:["left","right"]},r=e.mode,l=e.direction||"left",h="up"===l||"down"===l?"top":"left",c="up"===l||"left"===l,u=e.distance||o["top"===h?"outerHeight":"outerWidth"](!0),d={};t.effects.createPlaceholder(o),s=o.cssClip(),n=o.position()[h],d[h]=(c?-1:1)*u+n,d.clip=o.cssClip(),d.clip[a[l][1]]=d.clip[a[l][0]],"show"===r&&(o.cssClip(d.clip),o.css(h,d[h]),d.clip=s,d[h]=n),o.animate(d,{queue:!1,duration:e.duration,easing:e.easing,complete:i})});var o;t.uiBackCompat!==!1&&(o=t.effects.define("transfer",function(e,i){t(this).transfer(e,i)}))}); \ No newline at end of file diff --git a/js/jquery.ba-throttle-debounce.min.js b/js/jquery.ba-throttle-debounce.min.js new file mode 100644 index 0000000000..07205508eb --- /dev/null +++ b/js/jquery.ba-throttle-debounce.min.js @@ -0,0 +1,9 @@ +/* + * jQuery throttle / debounce - v1.1 - 3/7/2010 + * http://benalman.com/projects/jquery-throttle-debounce-plugin/ + * + * Copyright (c) 2010 "Cowboy" Ben Alman + * Dual licensed under the MIT and GPL licenses. + * http://benalman.com/about/license/ + */ +(function(b,c){var $=b.jQuery||b.Cowboy||(b.Cowboy={}),a;$.throttle=a=function(e,f,j,i){var h,d=0;if(typeof f!=="boolean"){i=j;j=f;f=c}function g(){var o=this,m=+new Date()-d,n=arguments;function l(){d=+new Date();j.apply(o,n)}function k(){h=c}if(i&&!h){l()}h&&clearTimeout(h);if(i===c&&m>e){l()}else{if(f!==true){h=setTimeout(i?k:l,i===c?e-m:e)}}}if($.guid){g.guid=j.guid=j.guid||$.guid++}return g};$.debounce=function(d,e,f){return f===c?a(d,e,false):a(d,f,e!==false)}})(this); \ No newline at end of file diff --git a/js/jquery.localScroll.min.js b/js/jquery.localScroll.min.js new file mode 100644 index 0000000000..48a6e168f6 --- /dev/null +++ b/js/jquery.localScroll.min.js @@ -0,0 +1,7 @@ +/** + * Copyright (c) 2007-2014 Ariel Flesler - afleslergmail+{ + "apples": "red fruit at the store", + "bananas": "yellow bananas in a bunch", + "carrots": "orange vegetables that grow in the ground", + "dingbats": "a type of character symbol on a computer", + "eggs": "chickens lay them, and people eat them", + "falafel": "a Mediterranean sandwich consisting of lots of different stuff i don't know much about", + "giraffe": "tall animal, has purple tongue", + "hippo": "surprisingly dangerous amphibian", + "igloo": "an ice shelter made by eskimos", + "jeep: "the only car that starts with a j", + "kilt": "something worn by scottish people, not a dress", + "lamp": "you use it to read by your bedside at night" + "manifold": "an intake mechanism on a car, like a valve, i think", + "octopus": "eight tentacles, shoots ink, lives in dark caves, very mysterious", + "paranoia": "the constant feeling that others are out to get you, conspiring against your success", + "qui": "a life force that runs through your body", + "radical": "someone who opposes the status quo in major ways", + "silly": "how I feel writing this dummy copy", + "taffy": "the sweets children like the most and dentists hate the worst", + "umbrella": "an invention that has not had any advancements in 200 years", + "vampire": "a paranormal figure that is surprisingly in vogue despite its basic nature", + "washington": "the place where tom was born", + "xylophone": "some kind of pinging instrument used to sound chime-like notes", + "yahoo": "an expression of exuberance, said under breath when something works right", + "zeta": "the way british people pronounce z", + "alpha": "the original letter of the alphabet, which has since come to mean the first. however, i think the original symbol of alpha is actually an ox. it is somewhat of a mystery to linquists as to the exact origin of the letter alpha, but it basically represents the dawn of the alphabet, which proved to be a huge step forward for human thought and expression.", + "beta": "the period of time when something is finished but undergoing testing by a group of people.", + "cappa": "how italians refer to their baseball caps", + "dunno": "informal expression for 'don't know'" + } + ++ +
This product is licensed under a “BSD-style” license; see below for the full text.
+ +Part of this product (mostly the package net.sourceforge.pmd.lang.vm) +is licensed under the Apache License, Version 2.0; +see below for the full text.
+ ++Copyright (c) 2002-2009, InfoEther, Inc +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * The end-user documentation included with the redistribution, if + any, must include the following acknowledgement: + "This product includes software developed in part by support from + the Defense Advanced Research Project Agency (DARPA)" + * Neither the name of InfoEther, LLC nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ +
+ Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. ++ + + + + + +
There are numerous ways of getting help:
+ +Search for already existing questions on StackOverflow.
+If you can’t find your problem, post a new question. Don’t forget to tag the question with pmd
.
If you found a bug, please create a new github issue.
+You can also ask questions in our sourceforge forum.
+Or you can join the Mailing List or browse +through the archives (archive1, archive2).
+Of course, you can also directly jump to our source code on github.
+Operation metric. Can be calculated on any non-abstract operation.
+ +Number of independent paths through a block of code [Lanza05].
+Formally, given that the control flow graph of the block has n
vertices, e
+edges and p
connected components, the cyclomatic complexity of the block is
+given by CYCLO = e - n + 2p
[McCabe76]. In practice it can be
+calculated by counting control flow statements following the standard rules given
+below.
The standard version of the metric complies with McCabe’s original definition:
+ +if
, catch
, throw
, do
,
+while
, for
, break
, continue
) and conditional expression (?:
).else
, finally
and default
don’t count;&&
, ||
) in the guard condition of a control
+flow statement.class Foo {
+ void baseCyclo() { // Cyclo = 1
+ highCyclo();
+ }
+
+ void highCyclo() { // Cyclo = 10
+ int x = 0, y = 2;
+ boolean a = false, b = true;
+
+ if (a && (y == 1 ? b : true)) { // +3
+ if (y == x) { // +1
+ while (true) { // +1
+ if (x++ < 20) { // +1
+ break; // +1
+ }
+ }
+ } else if (y == t && !d) { // +2
+ x = a ? y : x; // +1
+ } else {
+ x = 2;
+ }
+ }
+ }
+}
+
Class metric. Can be computed on classes and enums.
+ +Lanza05: Lanza, Marinescu; Object-Oriented Metrics in Practice, 2005.
+ +McCabe76: McCabe, A Complexity Measure, in Proceedings of the 2nd ICSE (1976).
+ + + + + + +You’ll need to either check out the source code or download the latest source release. Assuming you’ve got the latest source release, unzip it to a directory:
+ +[tom@hal building]$ ls -l
+total 5716
+-rw-rw-r-- 1 tom tom 5837216 Jul 17 13:09 pmd-src-6.30.0-SNAPSHOT.zip
+[tom@hal building]$ unzip -q pmd-src-6.30.0-SNAPSHOT.zip
+[tom@hal building]$
+
Now cd down into the pmd
directory:
[tom@hal building]$ cd pmd-src-6.30.0-SNAPSHOT
+[tom@hal pmd-src-6.30.0-SNAPSHOT]$ ls -l | grep pom.xml
+-rw-rw-r-- 1 tom tom 36482 14\. Nov 17:36 pom.xml
+[tom@hal pmd-src-6.30.0-SNAPSHOT]$
+
That’s the project configuration for maven… let’s compile!
+ +[tom@hal pmd-src-6.30.0-SNAPSHOT]$ ./mvnw clean verify
+[INFO] Scanning for projects...
+[INFO] ------------------------------------------------------------------------
+[INFO] Reactor Build Order:
+[INFO]
+[INFO] PMD
+[INFO] PMD Core
+...
+... after a few minutes ...
+[INFO] ------------------------------------------------------------------------
+[INFO] Reactor Summary:
+[INFO]
+[INFO] PMD ................................................ SUCCESS [ 3.061 s]
+[INFO] PMD Core ........................................... SUCCESS [ 25.675 s]
+[INFO] PMD Test Framework ................................. SUCCESS [ 0.457 s]
+[INFO] PMD C++ ............................................ SUCCESS [ 1.893 s]
+[INFO] PMD C# ............................................. SUCCESS [ 0.619 s]
+[INFO] PMD Fortran ........................................ SUCCESS [ 0.609 s]
+[INFO] PMD Go ............................................. SUCCESS [ 0.103 s]
+[INFO] PMD Java ........................................... SUCCESS [01:08 min]
+[INFO] PMD JavaScript ..................................... SUCCESS [ 3.279 s]
+[INFO] PMD JSP ............................................ SUCCESS [ 3.944 s]
+[INFO] PMD Matlab ......................................... SUCCESS [ 1.342 s]
+[INFO] PMD Objective-C .................................... SUCCESS [ 2.281 s]
+[INFO] PMD PHP ............................................ SUCCESS [ 0.536 s]
+[INFO] PMD PL/SQL ......................................... SUCCESS [ 10.973 s]
+[INFO] PMD Python ......................................... SUCCESS [ 1.758 s]
+[INFO] PMD Ruby ........................................... SUCCESS [ 0.438 s]
+[INFO] PMD Velocity ....................................... SUCCESS [ 3.941 s]
+[INFO] PMD XML and XSL .................................... SUCCESS [ 2.174 s]
+[INFO] PMD Scala .......................................... SUCCESS [ 11.901 s]
+[INFO] PMD Distribution Packages .......................... SUCCESS [ 11.366 s]
+[INFO] PMD Java 8 Integration ............................. SUCCESS [ 0.560 s]
+[INFO] ------------------------------------------------------------------------
+[INFO] BUILD SUCCESS
+[INFO] ------------------------------------------------------------------------
+[INFO] Total time: 02:36 min
+[INFO] Finished at: 2015-11-14T17:46:06+01:00
+[INFO] Final Memory: 63M/765M
+[INFO] ------------------------------------------------------------------------
+[tom@hal pmd-src-6.30.0-SNAPSHOT]$
+
Now the source and binary distribution zip files can be found in the folder pmd-dist/target
.
Notes:
+ +src/main/resources/rulesets/
directories of
+the specific languages, e.g. pmd-java/src/main/resources/rulesets
.
+They’re also in the jar file that’s included with both the source and binary distributions.A paucity of detail, I’m sure you’d agree. If you think this document can be improved, +please post here and let me know how. Thanks!
+ + + + + + +The next version of PMD will be developed in parallel with this release. We will release additional bugfix versions as needed.
+ +The complete source code can be found on github:
+ +We use Travis CI as our ci service. The main repo and the eclipse plugin are built for +every push. Each pull request is built as well.
+ +The maven snapshot artifacts are deployed at Sonatypes OSS snapshot repository.
+ +Ready-to-use binary packages are uploaded to sourceforge at https://sourceforge.net/projects/pmd/files/pmd/.
+ +A snapshot of the web site for the new version is generated travis-ci as well.
+ +First off, thanks for taking the time to contribute!
+ +Please have a look at CONTRIBUTING.md and +BUILDING.md.
+ + + + + + +$ run.sh ast-dump --help
+Usage: ast-dump [options]
+ Options:
+ --encoding, -e
+ Encoding of the source file.
+ Default: UTF-8
+ --file
+ The file to dump
+ --format, -f
+ The output format.
+ Default: xml
+ --help, -h
+ Display usage.
+ --language, -l
+ Specify the language to use.
+ Default: java
+ --read-stdin, -i
+ Read source from standard input
+ Default: false
+ -P
+ Properties for the renderer.
+ Syntax: -Pkey=value
+ Default: {}
+
+Available languages: apex ecmascript java jsp modelica plsql pom scala text vf vm wsdl xml xsl
+Available formats: xml XML format with the same structure as the one used in XPath
++ Properties
+ + singleQuoteAttributes Use single quotes to delimit attribute values (default true)
+ + lineSeparator Line separator to use. The default is platform-specific. (default \n)
+ + renderProlog True to output a prolog (default true)
+ + renderCommonAttributes True to render attributes like BeginLine, EndLine, etc. (default false)
+
$ cat Foo.java
+public class Foo {
+ int a;
+}
+
+$ run.sh ast-dump --format xml --language java --file Foo.java > Foo.xml
+-------------------------------------------------------------------------------
+This command line utility is experimental. It might change at any time without
+prior notice.
+-------------------------------------------------------------------------------
+
+$ cat Foo.xml
+<?xml version='1.0' encoding='UTF-8' ?>
+<CompilationUnit Image='' PackageName='' declarationsAreInDefaultPackage='true'>
+ <TypeDeclaration Image=''>
+ <ClassOrInterfaceDeclaration Abstract='false' BinaryName='Foo' Default='false' Final='false' Image='Foo' Interface='false' Local='false' Modifiers='1' Native='false' Nested='false' PackagePrivate='false' Private='false' Protected='false' Public='true' SimpleName='Foo' Static='false' Strictfp='false' Synchronized='false' Transient='false' TypeKind='CLASS' Volatile='false'>
+ <ClassOrInterfaceBody AnonymousInnerClass='false' EnumChild='false' Image=''>
+ <ClassOrInterfaceBodyDeclaration AnonymousInnerClass='false' EnumChild='false' Image='' Kind='FIELD'>
+ <FieldDeclaration Abstract='false' AnnotationMember='false' Array='false' ArrayDepth='0' Default='false' Final='false' Image='' InterfaceMember='false' Modifiers='0' Native='false' PackagePrivate='true' Private='false' Protected='false' Public='false' Static='false' Strictfp='false' Synchronized='false' SyntacticallyFinal='false' SyntacticallyPublic='false' SyntacticallyStatic='false' Transient='false' VariableName='a' Volatile='false'>
+ <Type Array='false' ArrayDepth='0' ArrayType='false' Image='' TypeImage='int'>
+ <PrimitiveType Array='false' ArrayDepth='0' Boolean='false' Image='int' />
+ </Type>
+ <VariableDeclarator Image='' Initializer='false' Name='a'>
+ <VariableDeclaratorId Array='false' ArrayDepth='0' ArrayType='false' ExceptionBlockParameter='false' ExplicitReceiverParameter='false' Field='true' Final='false' FormalParameter='false' Image='a' LambdaParameter='false' LocalVariable='false' ResourceDeclaration='false' TypeInferred='false' VariableName='a' />
+ </VariableDeclarator>
+ </FieldDeclaration>
+ </ClassOrInterfaceBodyDeclaration>
+ </ClassOrInterfaceBody>
+ </ClassOrInterfaceDeclaration>
+ </TypeDeclaration>
+</CompilationUnit>
+
+$ xmlstarlet select -t -c "//VariableDeclaratorId[@VariableName='a']" Foo.xml
+<VariableDeclaratorId Array="false" ArrayDepth="0" ArrayType="false" ExceptionBlockParameter="false" ExplicitReceiverParameter="false" Field="true" Final="false" FormalParameter="false" Image="a" LambdaParameter="false" LocalVariable="false" ResourceDeclaration="false" TypeInferred="false" VariableName="a"/>
+
This example uses xmlstarlet to query the xml document for any variables/fields +with the name “a”.
+ +Just parse your source code to get the AST and pass it on to the XmlTreeRenderer
:
import java.io.IOException;
+import java.io.StringReader;
+
+import net.sourceforge.pmd.lang.LanguageRegistry;
+import net.sourceforge.pmd.lang.LanguageVersionHandler;
+import net.sourceforge.pmd.lang.Parser;
+import net.sourceforge.pmd.lang.ast.Node;
+import net.sourceforge.pmd.util.treeexport.XmlTreeRenderer;
+
+public class TreeExport {
+ public static void main(String[] args) throws IOException {
+ LanguageVersionHandler java = LanguageRegistry.getLanguage("Java").getDefaultVersion().getLanguageVersionHandler();
+ Parser parser = java.getParser(java.getDefaultParserOptions());
+ Node root = parser.parse("foo", new StringReader("class Foo {}"));
+
+ new XmlTreeRenderer().renderSubtree(root, System.out);
+ }
+}
+
The processing starts e.g. with the main class: net.sourceforge.pmd.PMD
net.sourceforge.pmd.processor.PMDRunnable
:
+ net.sourceforge.pmd.SourceCodeProcessor
):
+ First of all, thanks for the contribution!
+ +Happily for you, to add CPD support for a new language is now easier than ever!
+ +All you need to do is follow this few steps:
+ +Create a Tokenizer
+ + public class GoTokenizer extends AntlrTokenizer {
+
+ @Override protected AntlrTokenManager getLexerForSource(SourceCode sourceCode) {
+ CharStream charStream = AntlrTokenizer.getCharStreamFromSourceCode(sourceCode);
+ return new AntlrTokenManager(new GolangLexer(charStream), sourceCode.getFileName());
+ }
+ }
+
Create your Language class
+ + public class GoLanguage extends AbstractLanguage {
+
+ public GoLanguage() {
+ super("Go", "go", new GoTokenizer(), ".go");
+ }
+ }
+
You are almost there!
+Update the list of supported languages
+ +Write the fully-qualified name of your Language class to the file src/main/resources/META-INF/services/net.sourceforge.pmd.cpd.Language
Update the test that asserts the list of supported languages by updating the SUPPORTED_LANGUAGES
constant in BinaryDistributionIT
Please don’t forget to add some test, you can again.. look at Go implementation ;)
+ +If you read this far, I’m keen to think you would also love to support some extra CPD configuration (ignore imports or crazy things like that)
+ If that’s your case , you came to the right place!
You can add your custom properties using a Token filter
+ +For Antlr grammars all you need to do is implement your own AntlrTokenFilter
+ +And by now, I know where you are going to look…
+ +WRONG
+ +Why do you want GO to solve all your problems?
+ +You should take a look to Kotlin token filter implementation
+For non-Antlr grammars you can use BaseTokenFilter directly or take a peek to Java’s token filter
+Add a Maven dependency on pmd-lang-test
(scope test
) in your pom.xml
.
+This contains utilities to test your Tokenizer.
For simple tests, create a test class extending from CpdTextComparisonTest
.
+That class is written in Kotlin, but you can extend it in Java as well.
To add tests, you need to write regular JUnit @Test
-annotated methods, and
+call the method doTest
with the name of the test file.
For example, for the Dart language:
+ +
+public class DartTokenizerTest extends CpdTextComparisonTest {
+
+ /**********************************
+ Implementation of the superclass
+ ***********************************/
+
+
+ public DartTokenizerTest() {
+ super(".dart"); // the file extension for the dart language
+ }
+
+ @Override
+ protected String getResourcePrefix() {
+ // If your class is in src/test/java /some/package
+ // you need to place the test files in src/test/resources/some/package/cpdData
+ return "cpdData";
+ }
+
+ @Override
+ public Tokenizer newTokenizer() {
+ // Override this abstract method to return the correct tokenizer
+ return new DartTokenizer();
+ }
+
+ /**************
+ Test methods
+ ***************/
+
+
+ @Test // don't forget the JUnit annotation
+ public void testLiterals() {
+ // This will look for a file named literals.dart
+ // in the directory identified by getResourcePrefix,
+ // tokenize it, then compare the result against a baseline
+ // literals.txt file in the same directory
+
+ // If the baseline file does not exist, it is created automatically
+ doTest("literals");
+ }
+
+}
+
pmd-<lang>/src/main/ant/alljavacc.xml
file.alljavacc.xml
file for your language, you can use one from pmd-java
as an example.<delete>
tag: start with an empty <fileset>
and add there <include>
s for those AST nodes you had to manually rewrite (moving those node classes from autogenerated directory to the regular source tree).TokenManager
interface (see VmTokenManager or JavaTokenManager for example)createTokenManager
method should return a new instance of a token manager for your language (see step #5)parse
method should return the root node of the AST tree obtained by parsing the Reader sourceVmParser
class as an exampleAbstractRuleViolationFactory
(see VmRuleViolationFactory for example)AbstractLanguageVersionHandler
(see VmHandler for example)getRuleViolationFactory
method returns an instance of your rule violation factory (see step #7)getParser
returns an instance of your parser adapter (see step #6)getDumpFacade
returns a VisitorStarter
that allows to dump a text representation of the AST into a writer (likely for debugging purposes)visitor
implementation, which, for all AST types in your language, just executes visit on the base AST typeAbstractRuleChainVisitor
(see VmRuleChainVisitor for example)implement
two important
methods:
+ indexNodes
generates a map of “node type” to “list of nodes of that type”. This is used to visit all applicable nodes when a rule is applied.visit
method should evaluate what kind of rule is being applied, and execute appropriate logic. Usually it will just check if the rule is a “parser visitor” kind of rule specific to your language, then execute the visitor. If it’s an XPath rule, then we just need to execute evaluate on that.net.sourceforge.pmd.lang.BaseLanguageModule
. (see VmLanguageModule or JavaLanguageModule as an example)addVersion
in your language module’s constructor.src/main/resources/META-INF/services/net.sourceforge.pmd.lang.Language
. Add your fully qualified class name as a single line into it.For languages, that use an external library for parsing, the AST can easily change when upgrading the library. +Also for languages, where we have the grammar under our control, it useful to have such tests.
+ +The tests parse one or more source files and generate a textual representation of the AST. This text is compared +against a previously recorded version. If there are differences, the test fails.
+ +This helps to detect anything in the AST structure, that changed, maybe unexpectedly.
+ +net.sourceforge.pmd.lang.$lang.ast
with the name $langTreeDumpTest
.net.sourceforge.pmd.lang.ast.test.BaseTreeDumpTest
. Note: This class
+is written in kotlin and is available in the module “lang-test”.Add a default constructor, that calls the super constructor like so:
+ + public $langTreeDumpTest() {
+ super(NodePrintersKt.getSimpleNodePrinter(), ".$extension");
+ }
+
Replace “$lang” and “$extension” accordingly.
+getParser()
. It must return a
+subclass of net.sourceforge.pmd.lang.ast.test.BaseParsingHelper
. See
+net.sourceforge.pmd.lang.ecmascript.ast.JsParsingHelper
for a example.
+With this parser helper you can also specify, where the test files are searched, by using
+the method withResourceContext(Class<?>, String)
.Add one or more test methods. Each test method parses one file and compares the result. The base
+class has a helper method doTest(String)
that does all the work. This method just needs to be called:
@Test
+ public void myFirstAstTest() {
+ doTest("filename-without-extension");
+ }
+
.txt
) is created, that records the
+current AST. On the next run, the text file is used as comparison and the test should pass. Don’t forget
+to commit the generated text file.A complete example can be seen in the JavaScript module: net.sourceforge.pmd.lang.ecmascript.ast.JsTreeDumpTest
.
+The test resources are in the subpackage “testdata”: pmd-javascript/src/test/resources/net/sourceforge/pmd/lang/ecmascript/ast/testdata/
.
The Scala module also has a test, written in Kotlin instead of Java:
+net.sourceforge.pmd.lang.scala.ast.ScalaParserTests
.
AbstractRule
and implement the parser visitor interface for your language (see AbstractVmRule for example)EmptyForeachStmtRule
for example)addRule
method in setUp of the unit test
+ EmptyForeachStmtRule.xml
for example)To verify the validity of the created ruleset, create a subclass of AbstractRuleSetFactoryTest
(see RuleSetFactoryTest
in pmd-vm for example).
+This will load all rulesets and verify, that all required attributes are provided.
Note: You’ll need to add your ruleset to rulesets.properties
, so that it can be found.
When implementing your grammar it may be very useful to see how PMD parses your example files. +This can be achieved with Rule Designer:
+getXPathNodeName
in your AST nodes for Designer to show node names.jjtOpen
and jjtClose
in your AST node base class so that they set both start and end line and column for proper node bound highlighting.net.sourceforge.pmd.util.fxdesigner.util.codearea.syntaxhighlighting
(you could use Java as an example).AvailableSyntaxHighlighters
enumeration.target/pmd-ui-<version>-SNAPSHOT.jar
to the lib
directory inside your pmd-bin-...
distribution (you have to delete old pmd-ui-*.jar
from there).The framework is pretty simple. On a high level, a Metric<N>
describes some numeric computation on a node of type N
.
+You should wrap it into a MetricKey<N>
, so that it can be cached on nodes (implemented by MetricsUtil
).
At the very least, a metrics framework has those two components and is just a convenient way to compute and memoize +metrics on a single file. The expressive power of metrics can be improved by implementing signature matching capabilities, +which allows a metric to count signatures matching a specific pattern (a mask) over a whole class. This was originally +designed to work across files, given a working usage resolution. However, making that work with incremental analysis is +harder than it looks, and has been rescheduled to another project.
+ +LanguageMetricsProvider
, to expose your metrics to the designerMetricsUtil
You can match the signature of anything: method, field, class, package… It depends on what’s useful for you.
+Suppose you want to be able to match signatures for nodes of type N
. What you have to do then is the following:
Signature<N>
. Signatures describe basic information about the node,
+which typically includes most of the modifiers they declare (eg visibility, abstract or virtual, etc.).
+It’s up to you to define the right level of detail, depending on the accuracy of the pattern matching required.N
implement SignedNode<N>
. This makes the node capable of giving its signature. Factory methods to
+build a Signature<N>
from a N
are a good idea.JavaOperationSigMask
that matches all method signatures with visibility
+ public
. A sigmask implements SigMask<S>
, where S
is the type of signature your mask handles.Pmdtester is a regression testing tool that ensures no new problems and unexpected behaviors will be introduced to PMD after fixing an issue. +It can also be used to verify, that new rules work as expected. It has been integrated into travis CI and is actually used automatically for PRs. +Regression difference reports are commented back to the PR for the reviewer’s information e.g. https://github.com/pmd/pmd/pull/1265#issuecomment-408945709
+ +Install pmdtester
+ +gem install pmdtester --pre
Verifying your local changes and generate a diff-report locally
+ +pmdtester -r YOUR_LOCAL_PMD_GIT_REPO_ROOT_DIR -b master -p YOUR_DEVELOPMENT_BRANCH
The regression difference report is placed in the YOUR_WORKING_DIR/target/reports/diff
directory.
For more documentation on pmdtester, see README.rdoc
+ + + + + + +TODO:
+ +Want to know what’s coming? Or, better, wanna contribute ? Here is the page listing what are our plans - +when we have ones, for the future of PMD. It also give you hints at part of the code we would like to clean - +that you may want to clean to contribute to the project!
+ +Of course, an easy way to contribute is too check out the bug tracker and see if you can fix some issues - +some could be quite easy, we simply have not the time to look at them all!
+ +At last, if you want to contribute, register on the pmd-devel mailing list, and come discuss with us!
+ +This roadmap contains all the different ‘workshops’ PMD’s developers are working right now.
+ +Please note that, of course, there is no warranty about when those ‘features’ will be finished, if they ever are.
+ +Currently PMD only looks at one source file at a time. Instead, it should resolve symbols across classes. +This will eliminate some open bugs and enable a lot more rules to be written. However, it’ll taken some doing, +because it’ll require parsing of class files. Lots of work here.
+ +Raik Schroeder, a graduate student at Fachhochschule Stralsund has written a DFA layer that should enable
+us to write some more complicated rules - stuff like common subexpression elimination, loop invariant code motion
+(and code hoisting suggestions), shrink wrapping, and partial redundancy elimination. The code is currently in the net.sourceforge.pmd.dfa
packages, and we’re going through it now figuring out what rules we can write
+that use it. We should be able to use it to simplify some current rules, as well.
These are things which really should be done, but just haven’t been gotten to yet:
+ +These are food for thought, perhaps future items. If you think you’d like to +work on one of these, check with pmd-devel to see what the current thoughts +on the topic.
+ +CPD needs work on use of Language. It currently is hardcoded to only +handled Java 1.4. Integrate CPD needs into core PMD where appropriate. +Otherwise, drive CPD behavior based off of core PMD, instead of duplicating +some logic.
+Need a more flexible and powerful scheme for classifying files to various +Languages. At a minimum, should have the ability to specify which +file extensions you want to be used for a language (e.g. not everyone uses +.jsp for JSP extensions, some use .jspx, .xhtml, etc.). Also, consider +hooks into the LanguageVersionDiscoverer process for classifying a +File/String to a LanguageVersion of a specific Language, one could imaging +using a ‘magic’ system like Unix uses to tell different versions of files +apart based on actual content.
+Should we change Node interface to something like ‘Node<T extends Node<T>>’, +and then declare the language specific node interfaces to be something like +‘JavaNode extends Node<JavaNode>’? This could allow anything on the Node +interface to return the language specific node type instead of generic +node. For example, ASTStatement.jjtGetParent() to return a JavaNode, +instead of a Node. This is a rather huge change, as the Node interface is +one of the pervasive things in the PMD code base. Is the extra work of using +the Node interface with properly with generics, worth the omission of +occasional some casting?
+Should multiple Languages be able to claim a single source file? Imagine +XML format JSP file, for which you’ve defined a ruleset which uses JSP and +XML rules. Stating that certain XML rules also can map to the JSP language +extensions could be useful. This means Source file to LanguageVersion +mapping is not 1-1, but 1-many, we’d need to deal with this accordingly.
+Additional changes to Rule organization within RuleSets as discussed on +this forum thread.
+Figure out a way to allow Rules to deal with parentheses and blocks, which +introduce certain repetitive (and generally ignorable for most Rules) +structures into the AST tree. Some rules are making special effort +(e.g. ConfusingTernaryRule) to detect these AST patterns. Perhaps a +“normalized” AST structure can be created which will make the AST appear +consistent regardless of how many parens are presented, or how many blocks +have been created (e.g. default block inserted, duplicates collapsed). +This should be configurable on per Rule basis similar to TR and SymbolTable.
+Some of the code is a bit sloppy:
+ +When improving PMD over time, some rules might become obsolete. This could be because the underlying +technology a specific rule is checking (such as a specific JVM version) is not relevant anymore or a rule +has been replaced by a better implementation.
+ +In order to remove the requirement to maintain such rules forever, these rules can be marked as deprecated. +This means, that such rules can entirely be removed in the future. +However, the rules must not be removed immediately, since that would break any (custom) ruleset, that +references this rule.
+ +This policy tries to establish some ground rules about how and when rules are deprecated and removed. +The main goal is, to maintain compatibility of custom rulesets throughout the deprecation process.
+ +If a rule is enhanced, it might make sense to also rename the rule, to reflect that enhancement. However, +simply renaming the rule would break existing (custom) ruleset. Therefore the following procedure should be used:
+ +Add a deprecated rule reference with the old name, that points to the new rule name:
+ +<rule name="OldRuleName" ref="NewRuleName" deprecated="true" />
Note: When referencing the complete rulesets or categories, +these deprecated rule references are ignored, so that the rule is not used twice.
+ +Every rule is in one category. It might happen, that the focus of the rule shifts and it makes more +sense, if it would be in a different, better fitting category.
+ +Add a deprecated rule reference in the old category, that points to the rule in the new category:
+ +<rule name="MyRule" ref="category/java/errorprone.xml/MyRule" deprecated="true" />
Note: When referencing the complete rulesets or categories, +these deprecated rule references are ignored, so that the rule is not used twice, if both categories +are used.
+ +Before a rule can be removed, it must have been marked as deprecated:
+ +<rule name="MyRule" class="...." deprecated="true">
+...
+</rule>
+
This has the effect, that it is automatically disabled if the complete ruleset or category +is referenced. The rule can still be used, if it is referenced directly.
+ +The reasons for the deprecation should be explained in the rule description. If there is a replacement rule +available, then this rule should be mentioned in the description as well.
+ +Removing rules completely can only be done
+ +Removing a rule from a ruleset or category will break any custom ruleset, that references +this rule directly. Therefore rules can only be removed with the next major release of PMD.
+ +Renaming or removing rule properties is not backwards compatible and can only be done +with a major release of PMD.
+ +In order to prepare for the change, properties can be deprecated as well: If the property description
+starts with the magic string deprecated!
, then this property is rendered in the rule documentation
+as deprecated. However, there is no automatic check done if such a property is used and no
+deprecation warning is issued with the log.
Therefore, the process for renaming a property looks like this:
+ +deprecated!
and also add a explanation
+either in the property description or in the rule description, which property should be used
+instead of the deprecated property.Changing the default value of a property might have some results, that make the rule +behavioral incompatible: E.g. it could find many more violations with a different default +configuration and therefore lead to a sudden increase of violations after a PMD upgrade. +It should be judged per case, whether the new default can be considered compatible or not. +If it is not compatible, then the new default value should be configured only with the next +major release of PMD.
+ + + + + + + +PMD’s documentation uses Jekyll with +the I’d rather be writing Jekyll Theme.
+ +Here are some quick tips.
+ +The pages are in general in Github Flavored Markdown.
+ +The documentation sources can be found in two places based on how they are generated:
+All handwritten documentation is stored in the subfolders under docs/pages
. The folder structure resembles the sidebar structure.
+Since all pages use a simple permalink, in the rendered html pages, all pages are flattened in one directory.
+This makes it easy to view the documentation also offline.
The categories for a language %lang%
are located in
+pmd-%lang%/src/main/resources/category/%lang%
. So for Java the categories
+can be found under pmd-java/src/main/resources/category/java.
+The XML category files in this directory are transformed during build into markdown pages
+describing the rules they contain. These pages are placed under docs/
like the handwritten
+documentation, and are then rendered with Jekyll like the rest of them. The rule documentation
+generator is the separate submodule pmd-doc
.
Modifying the documentation of a rule should thus not be done on the markdown page,
+but directly on the XML rule
tag corresponding to the rule, in the relevant
+category file.
The XML documentation of rules can contain GitHub flavoured markdown. +Just wrap the markdown inside CDATA section in the xml. CDATA sections preserve +all formatting inside the delimiters, and allow to write code samples without + escaping special xml characters. For example:
+<rule ...>
+ <description>
+ <![CDATA[
+ Full description, can contain markup
+
+ And paragraphs
+ ]]>
+ </description>
+ ...
+</rule>
+
We have some additional custom liquid tags that help in writing the documentation.
+ +Here’s a short overview:
+ +Liquid | +Rendered as | +
---|---|
{% rule "java/codestyle/LinguisticNaming" %} |
+ LinguisticNaming |
+
{% jdoc core::Rule %} |
+ Rule |
+
{% jdoc !q!core::Rule %} |
+ net.sourceforge.pmd.Rule |
+
{% jdoc core::Rule#setName(java.lang.String) %} |
+ setName |
+
{% jdoc !c!core::Rule#setName(java.lang.String) %} |
+ Rule#setName |
+
{% jdoc !a!core::Rule#setName(java.lang.String) %} |
+ setName(String) |
+
{% jdoc !ac!core::Rule#setName(java.lang.String) %} |
+ Rule#setName(String) |
+
{% jdoc core::properties.PropertyDescriptor %} |
+ PropertyDescriptor |
+
{% jdoc_nspace :jast java::lang.java.ast %}{% jdoc jast::ASTAnyTypeDeclaration %} |
+ ASTAnyTypeDeclaration |
+
{% jdoc_nspace :jast java::lang.java.ast %}{% jdoc_package :jast %} |
+ net.sourceforge.pmd.lang.java.ast |
+
{% jdoc_nspace :PrD core::properties.PropertyDescriptor %}{% jdoc !ac!:PrD#uiOrder() %} |
+ PropertyDescriptor#uiOrder() |
+
{% jdoc_old core::Rule %} |
+ Rule |
+
For the javadoc tags, the standard PMD maven modules are already defined as namespaces, e.g. core
, java
, apex
, ….
For the implementation of these tags, see the _plugins folder.
+ +There are two ways, to execute jekyll:
+ +Using bundler. This will install all the needed ruby packages locally and execute jekyll:
+ +# this is required only once, to download and install the dependencies
+bundle install
+# this builds the documentation under _site
+bundle exec jekyll build
+# this runs a local webserver as http://localhost:4005
+bundle exec jekyll serve
+
Using docker. This will create a local docker image, into which all needed ruby +packages and jekyll is installed.
+ +# this is required only once to create a local docker image named "pmd-doc"
+docker build --no-cache -t pmd-doc .
+# this builds the documentation under _site
+docker run --rm=true -v "$PWD:/src" pmd-doc build -H 0.0.0.0
+# this runs a local webserver as http://localhost:4005
+docker run --rm=true -v "$PWD:/src" -p 4005:4005 pmd-doc serve -H 0.0.0.0
+
The built site is stored locally in the (git ignored) directory _site
. You can
+point your browser to _site/index.html
to see the pmd documentation.
Alternatively, you can start the local webserver, that will serve the documentation. +Just go to http://localhost:4005. +If a page is modified, the documentation will automatically be rendered again and +all you need to do, is refreshing the page in your browser.
+ +See also the script pmd-jekyll.sh. +It starts the jekyll server in the background and doesn’t block the current shell.
+ +The sidebar is stored as a YAML document under _data/sidebars/pmd_sidebar.yml
.
Make sure to add an entry there, whenever you create a new page.
+ +Each page in jekyll begins with a YAML section at the beginning. This section
+is separated by 3 dashes (---
). Example:
---
+title: Writing Documentation
+last_update: August 2017
+permalink: pmd_devdocs_writing_documentation.html
+---
+
+Some Text
+
+# Some header
+
There are a couple of possible fields. Most important and always +required are title and permalink.
+ +By default, a page toc (table of contents) is automatically generated. +You can prevent this with “toc: false”.
+ +You can add keywords, that will be used for the on-site search: “keywords: documentation, jekyll, markdown”
+ +It’s useful to maintain a last_update field. This will be added at the bottom of the +page.
+ +A summary can also be provided. It will be added in a box before the content.
+ +For a more exhaustive list, see Pages - Frontmatter.
+ +See Alerts.
+ +For example, a info-box can be created like this:
+ +{% include note.html content="This is a note." %}
+
It renders as:
+ +Other available types are:
+ +A callout is created like this:
+ +{% include callout.html content="This is a callout of type default.<br/><br/>There are the following types available: danger, default, primary, success, info, and warning." type="default" %}
+
It renders as:
+ +This is as easy as:
+ +``` java
+public class Foo {
+ public void bar() { System.out.println("x"); }
+}
+```
+
This looks as follows:
+ +public class Foo {
+ public void bar() { System.out.println("x"); }
+}
+
mvn verify -pl pmd-doc
. This only checks links within the site. HTTP links can be checked
+by specifying -Dpmd.doc.checkExternalLinks=true
on the command line.
Operation metric, class metric. Can be computed on classes, enums and +concrete operations.
+ +Number of usages of foreign attributes, both directly and through accessors. +High values of ATFD (> 3 for an operation) may suggest that the class or operation +breaks encapsulation by relying on the internal representation of the classes +it uses instead of the services they provide.
+ +ATFD can be used to detect God Classes and Feature Envy. [Lanza05]
+ +Operation metric, class metric. Can be computed on classes, enums and +concrete operations.
+ +This counts the number of other classes a given class or operation relies on.
+Classes from the package java.lang
are ignored by default (can be changed via options).
+Also primitives are not included into the count.
import java.util.*;
+import java.io.IOException;
+
+public class Foo { // total 8
+ public Set set = new HashSet(); // +2
+ public Map map = new HashMap(); // +2
+ public String string = ""; // from java.lang -> does not count by default
+ public Double number = 0.0; // from java.lang -> does not count by default
+ public int[] intArray = new int[3]; // primitive -> does not count
+
+ @Deprecated // from java.lang -> does not count by default
+ @Override // from java.lang -> does not count by default
+ public void foo(List list) throws Exception { // +1 (Exception is from java.lang)
+ throw new IOException(); // +1
+ }
+
+ public int getMapSize() {
+ return map.size(); // +1 because it uses the Class from the 'map' field
+ }
+}
+
includeJavaLang
: Also include classes from the package java.lang
Operation metric. Can be calculated on any non-abstract operation.
+ +Number of independent paths through a block of code [Lanza05].
+Formally, given that the control flow graph of the block has n
vertices, e
+edges and p
connected components, the cyclomatic complexity of the block is
+given by CYCLO = e - n + 2p
[McCabe76]. In practice it can be
+calculated by counting control flow statements following the standard rules given
+below.
The standard version of the metric complies with McCabe’s original definition:
+ +if
, case
, catch
, throw
, do
,
+while
, for
, break
, continue
) and conditional expression (?:
)
+[Sonarqube]. Notice switch cases count as one, but not the
+switch itself: the point is that a switch should have the same complexity
+value as the equivalent series of if
statements.else
, finally
and default
don’t count;&&
, ||
) in the guard condition of a control
+flow statement. That’s because Java has short-circuit evaluation semantics for
+boolean operators, which makes every boolean operator kind of a control flow
+statement in itself.class Foo {
+ void baseCyclo() { // Cyclo = 1
+ highCyclo();
+ }
+
+ void highCyclo() { // Cyclo = 10
+ int x = 0, y = 2;
+ boolean a = false, b = true;
+
+ if (a && (y == 1 ? b : true)) { // +3
+ if (y == x) { // +1
+ while (true) { // +1
+ if (x++ < 20) { // +1
+ break; // +1
+ }
+ }
+ } else if (y == t && !d) { // +2
+ x = a ? y : x; // +1
+ } else {
+ x = 2;
+ }
+ }
+ }
+}
+
CycloVersion#IGNORE_BOOLEAN_PATHS
: Boolean operators are not counted,
+nor are empty fall-through cases in switch
statements. You can use this
+option to get results similar to those of the old StdCyclomaticComplexityRule
,
+which is to be replaced.CycloVersion#CONSIDER_ASSERTS
: Assert statements are counted as if
+they were if (..) throw new AssertionError(..)
. Compatible with
+IGNORE_BOOLEAN_PATHS
.Operation metric, class metric. Can be calculated on any of those nodes.
+ +Simply counts the number of lines of code the operation or class takes up in +the source. This metric doesn’t discount comments or blank lines. See also +NCSS.
+ +Operation metric, class metric. Can be calculated on any of those nodes.
+ +Number of statements in a class or operation. That’s roughly equivalent to
+counting the number of semicolons and opening braces in the program. Comments
+and blank lines are ignored, and statements spread on multiple lines count as
+only one (e.g. int\n a;
counts a single statement).
The standard version of the metric is based off JavaNCSS’s version
+[JavaNcss]:
if
, else
, while
, do
, for
,
+switch
, break
, continue
, return
, throw
, synchronized
, catch
,
+finally
.for
loop initializers)
+or statement expression. We count variables declared on the same line (e.g.
+int a, b, c;
) as a single statement.COUNT_IMPORTS
option.import java.util.Collections; // +0
+import java.io.IOException; // +0
+
+class Foo { // +1, total Ncss = 12
+
+ public void bigMethod() // +1
+ throws IOException {
+ int x = 0, y = 2; // +1
+ boolean a = false, b = true; // +1
+
+ if (a || b) { // +1
+ try { // +1
+ do { // +1
+ x += 2; // +1
+ } while (x < 12);
+
+ System.exit(0); // +1
+ } catch (IOException ioe) { // +1
+ throw new PatheticFailException(ioe); // +1
+ }
+ } else {
+ assert false; // +1
+ }
+ }
+}
+
NcssVersion#COUNT_IMPORTS
: Import and package statements are counted
+as well. This version fully complies with JavaNCSS.Operation metric. Can be computed on any non-abstract operation.
+ +Number of acyclic execution paths through a piece of code. This is related to +cyclomatic complexity, but the two metrics don’t count the same thing: NPath +counts the number of distinct full paths from the beginning to the end of the +method, while Cyclo only counts the number of decision points. NPath is not +computed as simply as Cyclo. With NPath, two decision points appearing sequentially +have their complexity multiplied.
+ +The fact that NPath multiplies the complexity of statements makes it grow
+exponentially: 10 if
- else
statements in a row would give an NPath of 1024,
+while Cyclo would evaluate to 20. Methods with an NPath complexity over 200 are
+generally considered too complex.
We compute NPath recursively, with the following set of rules:
+for
, do
and while
statements is 1, plus the
+complexity of the block, plus the complexity of the guard condition.if
statement (if .. else if ..
) is the
+number of if
statements in the chain, plus the complexity of their guard
+condition, plus the complexity of the unguarded else
block (or 1 if there
+is none).switch
statement is the number of cases, plus the
+complexity of each case
block. It’s equivalent to the complexity of the
+equivalent cascade of if
statements.?:
) is the complexity of the guard
+condition, plus the complexity of both expressions. It’s equivalent to the
+complexity of the equivalent if .. else
construct.try .. catch
statement is the complexity of the try
+block, plus the complexity of each catch block.return
statement is the complexity of the expression
+(or 1 if there is none).void fun(boolean a, boolean b, boolean c) { // NPath = 6
+
+ // block #0
+
+ if (a) {
+ // block #1
+ } else {
+ // block #2
+ }
+
+ // block #3
+
+ if (b) {
+ // block #4
+ } else if (c) {
+ // block #5
+ }
+
+ // block #6
+}
+
After block 0, the control flow can either execute block 1 or 2 before jumping
+to block 3. From block three, the control flow will again have the choice
+between blocks 4 and 5 before jumping to block 6. The first if
offers 2
+choices, the second offers 3, so the cyclomatic complexity of this method is
+2 + 3 = 5. NPath, however, sees 2 * 3 = 6 full paths from the beginning to the end.
Class metric. Can be computed on classes.
+ +Class metric. Can be computed on classes.
+ +Class metric. Can be computed on classes and enums.
+ +The relative number of method pairs of a class that access in common at +least one attribute of the measured class. TCC only counts +direct attribute accesses, that is, only those attributes that are accessed in +the body of the method [BK95].
+ +TCC is taken to be a reliable cohesion metric for a class. High values (>70%) +indicate a class with one basic function, which is hard to break into subcomponents. +On the other hand, low values (<50%) may indicate that the class tries to do too much and +defines several unrelated services, which is undesirable.
+ +TCC can be used to detect God Classes and Brain Classes [Lanza05].
+ +Class metric. Can be computed on classes and enums.
+ +Sum of the statistical complexity of the operations in the class. We use +CYCLO to quantify the complexity of an operation +[Lanza05].
+ +WMC uses the same options as CYCLO, which are provided to CYCLO when +computing it.
+ +Class metric. Can be computed on classes.
+ +Number of “functional” public methods divided by the total number of +public methods. Our definition of “functional method” excludes +constructors, getters, and setters.
+ +This metric tries to quantify whether the measured class’ interface reveals +more data than behaviour. Low values (less than 30%) indicate that the class +reveals much more data than behaviour, which is a sign of poor encapsulation.
+ +This metric is used to detect Data Classes, in conjunction with WMC, +NOPA and NOAM.
+ +BK95: Bieman, Kang; Cohesion and reuse in an object-oriented system. +In Proceedings ACM Symposium on Software Reusability, 1995.
+ +Lanza05: Lanza, Marinescu; Object-Oriented Metrics in Practice, 2005.
+ +McCabe76: McCabe, A Complexity Measure, in Proceedings of the 2nd ICSE (1976).
+ + + + + + + + + + +In short, JSP files that are XHTML-compliant, are supported. +Except for files that contain inline DTDs; only references to external +DTD files are supported (having inline DTD will result in a parsing +error).
+ +The XHTML support means that:
+ +opening tags must be accompanied by corresponding closing tags +(or they must be empty tags). This means that currently a “<HR>” +tag without corresponding closing tag will result in a parsing error.
+attribute values must be surrounded by single or double quotes. This means that the following syntax +will result in a parsing error:
+ +<MyTag myAttr1=true myAttr2=1024/>
+< and > characters must be escaped, or put inside a CDATA section.
+ +PMD creates a “Abstract Syntax Tree” representation of source code; the rules use such a tree as input. +For JSP files, the following constructs are parsed into nodes of the tree:
+ +Java code (e.g. in JSP-scriptlets) and EL expressions are not parsed or +further broken down. If you want to create rules that check the code +inside EL expressions or JSP scriptlets (a.o.), you currently would +have to do “manual” string manipulation (e.g. using regular expressions).
+Using the command-line interface, two new options can be used in the arguments string:
+ +Using the Ant task, you decide if PMD must check JSP files by choosing +what files are given to the PMD task. If you use a fileset that +contains only “.java” files, JSP files obviously will not be checked.
+ +If you want to call the PMD API for checking JSP files, you should investigate the javadoc of PMD.
+ + + + + + +We’re excited to bring you the next major version of PMD! +Here is a summary of what is planned for PMD 7.
+ +To give us feedback or to suggest a new feature, drop us a line on Gitter!
+ +We decided it’s time to have a modernized logo and get rid of the gun. This allows to include +the logo in anywhere without offense.
+ +The current tasks are listed here: Integrate new PMD logo #1931
+ +The API of PMD has been growing over the years and needs to be cleaned up. The goal is, to +have a clear separation between a well-defined API and the implementation, which is internal. +This should help us in future development. This however entails some incompatibilities and +deprecations, see also the sections New API support guidelines and +[Planned API removals](#planned-api-removals] below.
+ +PMD 6 only supports JavaCC based grammars, but with Antlr parsers +can be generated as well. PMD 7 adds full support for grammars written in Antlr, which allows +to leverage existing grammars.
+ +The current tasks are listed here: Support for ANTLR based grammars with Swift as an example language #2499
+ +We have quite some ideas how we want to improve the documentation. The goal is, that the documentation is +up to date and nearly complete. One big task is, how the built-in rules are presented, so that users +can easier see, what exactly is available and decide, which rules are useful for the project at hand.
+ +The current tasks are listed here: Documentations improvements tracker #1139
+ +PMD 6 supports XPath 1.0 via the Jaxen library. This library is old and unmaintained creating some problems
+(one of which is duplicated classes in the package org.w3c.dom
which is a Java API actually).
+Therefore XPath 1.0 support will be dropped and we upgrade our XPath 2.0 implementation with Saxon moving
+on to Saxon HE. This will eventually add support in PMD for XPath 3.1.
The current tasks are listed here: XPath Improvements for PMD 7 #2523
+ +Like the main PMD API, the Java AST has been growing over time and the grammar doesn’t support +all edge cases (e.g. annotation are not supported everywhere). The goal is to simplify the AST by reducing +unnecessary nodes and abstractions and fix the parsing issues. +This helps in the end to provide a better type resolution implementation, but changing the AST is a breaking +API change.
+ +Some first results of the Java AST changes are for now documented in the Wiki: +Java clean changes.
+ +There are also some small improvements, refactoring and internal tasks that are planned for PMD 7.
+ +The current tasks are listed here: PMD 7 Miscellaneous Tasks #2524
+ +Until now, all released public members and types were implicitly considered part +of PMD’s public API, including inheritance-specific members (protected members, abstract methods). +We have maintained those APIs with the goal to preserve full binary compatibility between minor releases, +only breaking those APIs infrequently, for major releases.
+ +In order to allow PMD to move forward at a faster pace, this implicit contract will +be invalidated with PMD 7.0.0. We now introduce more fine-grained distinctions between +the type of compatibility support we guarantee for our libraries, and ways to make +them explicit to clients of PMD.
+ +.internal
packages and @InternalApi
annotationInternal API is meant for use only by the main PMD codebase. Internal types and methods +may be modified in any way, or even removed, at any time.
+ +Any API in a package that contains an .internal
segment is considered internal.
+The @InternalApi
annotation will be used for APIs that have to live outside of
+these packages, e.g. methods of a public type that shouldn’t be used outside of PMD (again,
+these can be removed anytime).
@ReservedSubclassing
Types marked with the @ReservedSubclassing
annotation are only meant to be subclassed
+by classes within PMD. As such, we may add new abstract methods, or remove protected methods,
+at any time. All published public members remain supported. The annotation is not inherited, which
+means a reserved interface doesn’t prevent its implementors to be subclassed.
@Experimental
APIs marked with the @Experimental
annotation at the class or method level are subject to change.
+They can be modified in any way, or even removed, at any time. You should not use or rely
+ on them in any production code. They are purely to allow broad testing and feedback.
@Deprecated
APIs marked with the @Deprecated
annotation at the class or method level will remain supported
+until the next major release but it is recommended to stop using them.
All currently supported APIs will remain so until 7.0.0. All APIs that are to be moved to
+.internal
packages or hidden will be tagged @InternalApi
before that major release, and
+the breaking API changes will be performed in 7.0.0.
@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.No changes.
+ +net.sourceforge.pmd.RuleViolationComparator
. Use RuleViolation#DEFAULT_COMPARATOR
instead.net.sourceforge.pmd.cpd.AbstractTokenizer
. Use net.sourceforge.pmd.cpd.AnyTokenizer
instead.net.sourceforge.pmd.cpd.FortranTokenizer
. Was replaced by an AnyTokenizer
. Use FortranLanguage#getTokenizer
anyway.net.sourceforge.pmd.cpd.PerlTokenizer
. Was replaced by an AnyTokenizer
. Use PerlLanguage#getTokenizer
anyway.net.sourceforge.pmd.cpd.RubyTokenizer
. Was replaced by an AnyTokenizer
. Use RubyLanguage#getTokenizer
anyway.RuleReference#getOverriddenLanguage
and
+RuleReference#setLanguage
net.sourceforge.pmd.lang.cs.antlr4.CSharpLexer
will be moved to package net.sourceforge.pmd.lang.cs.ast
with PMD 7.net.sourceforge.pmd.lang.dart.antlr4.Dart2Lexer
will be renamed to DartLexer
and moved to package
+net.sourceforge.pmd.lang.dart.ast
with PMD 7. All other classes in the old package will be removed.net.sourceforge.pmd.lang.go.antlr4.GolangLexer
will be moved to package
+net.sourceforge.pmd.lang.go.ast
with PMD 7. All other classes in the old package will be removed.net.sourceforge.pmd.lang.kotlin.antlr4.Kotlin
will be renamed to KotlinLexer
and moved to package
+net.sourceforge.pmd.lang.kotlin.ast
with PMD 7.net.sourceforge.pmd.lang.lua.antlr4.LuaLexer
will be moved to package
+net.sourceforge.pmd.lang.lua.ast
with PMD 7. All other classes in the old package will be removed.language
attribute will be required on all rule
+elements that declare a new rule. Some base rule classes set the language implicitly in their
+constructor, and so this is not required in all cases for the rule to work. But this
+behavior will be discontinued in PMD 7, so missing language
attributes are now
+reported as a forward compatibility warning.Rule#getParserOptions
Parser#getParserOptions
AbstractParser
RuleContext#removeAttribute
RuleContext#getAttribute
RuleContext#setAttribute
ApexParserOptions
ASTThrowStatement#getFirstClassOrInterfaceTypeImage
EcmascriptParserOptions
EcmascriptXPathRule
XmlParserOptions
XmlXPathRule
Properties of AbstractXmlRule
net.sourceforge.pmd.Report.ReadableDuration
Many methods of net.sourceforge.pmd.Report
. They are replaced by accessors
+ that produce a List. For example, iterator()
+ (and implementing Iterable) and isEmpty()
are both
+ replaced by getViolations()
.
ASTJspDeclarations
ASTJspDocument
ScalaParserVisitorAdapter#zero
ScalaParserVisitorAdapter#combine
ApexParserVisitorReducedAdapter
TypeHelper
is deprecated in
+ favor of TypeTestUtil
, which has the
+same functionality, but a slightly changed API.net.sourceforge.pmd.lang.java.symboltable
+are deprecated as internal API.RuleChainVisitor
and all implementations in language modulesAbstractRuleChainVisitor
Language#getRuleChainVisitorClass
BaseLanguageModule#<init>
ImportWrapper
The maven module net.sourceforge.pmd:pmd-scala
is deprecated. Use net.sourceforge.pmd:pmd-scala_2.13
+or net.sourceforge.pmd:pmd-scala_2.12
instead.
Rule implementation classes are internal API and should not be used by clients directly.
+The rules should only be referenced via their entry in the corresponding category ruleset
+(e.g. <rule ref="category/java/bestpractices.xml/AbstractClassWithoutAbstractMethod" />
).
While we definitely won’t move or rename the rule classes in PMD 6.x, we might consider changes +in PMD 7.0.0 and onwards.
+Those APIs are not intended to be used by clients, and will be hidden or removed with PMD 7.0.0.
+You can identify them with the @InternalApi
annotation. You’ll also get a deprecation warning.
AbstractIgnoredAnnotationRule
(Java)AbstractInefficientZeroCheck
(Java)AbstractJUnitRule
(Java)AbstractJavaMetricsRule
(Java)AbstractLombokAwareRule
(Java)AbstractPoorMethodCall
(Java)AbstractSunSecureRule
(Java)AbstractNcssCountRule
(Java)AbstractCommentRule
(Java)AbstractOptimizationRule
(Java)RegexHelper
(Java)AbstractApexUnitTestRule
(Apex)AbstractNcssCountRule
(Apex)AbstractNcssCountRule
(PLSQL)ApexParser
ApexHandler
RuleChain
RuleSets
RulesetsFactoryUtils#getRuleSets
TokenEntry#TokenEntry
AbstractTokenizerTest
. Use CpdTextComparisonTest in module pmd-lang-test instead.
+For details see
+Testing your implementation
+in the developer documentation.ASTAnnotation#suppresses
(Apex)ApexXPathRule
(Apex)SymbolTableTestRule
(Java)InefficientStringBufferingRule#isInStringBufferOperation
BaseLanguageModule#addVersion(String, LanguageVersionHandler, boolean)
TokenMgrError
, in particular, a new constructor is available
+that should be preferred to the old onesAntlrTokenManager.ANTLRSyntaxError
Note: Experimental APIs are identified with the annotation Experimental
,
+see its javadoc for details
BaseLanguageModule
have been replaced by a
+definitive API.Those APIs are not intended to be used by clients, and will be hidden or removed with PMD 7.0.0.
+You can identify them with the @InternalApi
annotation. You’ll also get a deprecation warning.
As part of the changes we’d like to do to AST classes for 7.0.0, we would like to +hide some methods and constructors that rule writers should not have access to. +The following usages are now deprecated in the Apex, Javascript, PL/SQL, Scala and Visualforce ASTs:
+ +InternalApi
. Nodes should only be obtained from the parser,
+which for rules, means that they never need to instantiate node themselves.
+Those constructors will be made package private with 7.0.0.Parser
(eg VfParser
) are deprecated and should not be used directly.
+Use LanguageVersionHandler#getParser
instead.TokenManager
(eg VfTokenManager
) are deprecated and should not be used outside of our implementation.
+This also affects CPD-only modules.These deprecations are added to the following language modules in this release. +Please look at the package documentation to find out the full list of deprecations.
+net.sourceforge.pmd.lang.apex.ast
net.sourceforge.pmd.lang.ecmascript.ast
net.sourceforge.pmd.lang.plsql.ast
net.sourceforge.pmd.lang.scala.ast
net.sourceforge.pmd.lang.vf.ast
These deprecations have already been rolled out in a previous version for the +following languages:
+net.sourceforge.pmd.lang.java.ast
net.sourceforge.pmd.lang.jsp.ast
net.sourceforge.pmd.lang.vm.ast
Outside of these packages, these changes also concern the following TokenManager +implementations, and their corresponding Parser if it exists (in the same package):
+ +CppTokenManager
JavaTokenManager
Ecmascript5TokenManager
JspTokenManager
MatlabTokenManager
ModelicaTokenManager
ObjectiveCTokenManager
PLSQLTokenManager
PythonTokenManager
VfTokenManager
VmTokenManager
In the Java AST the following attributes are deprecated and will issue a warning when used in XPath rules:
+ +ASTAdditiveExpression#getImage
- use getOperator()
insteadASTVariableDeclaratorId#getImage
- use getName()
insteadASTVariableDeclaratorId#getVariableName
- use getName()
insteadParser#getTokenManager
TokenManager#setFileName
AbstractTokenManager#setFileName
AbstractTokenManager#getFileName
AntlrToken#getType
- use getKind()
instead.ImmutableLanguage
MockRule
Node#getFirstParentOfAnyType
Node#getAsDocument
AbstractNode#hasDescendantOfAnyType
ASTRecordDeclaration#getComponentList
XPathRule
. See javadoc for details.Those APIs are not intended to be used by clients, and will be hidden or removed with PMD 7.0.0.
+You can identify them with the @InternalApi
annotation. You’ll also get a deprecation warning.
JavaLanguageHandler
JavaLanguageParser
JavaDataFlowHandler
RuleViolationFactory
in each
+language module, eg JavaRuleViolationFactory
.
+See javadoc of RuleViolationFactory
.Implementations of RuleViolation
in each language module,
+eg JavaRuleViolation
. See javadoc of
+RuleViolation
.
RuleFactory
RuleBuilder
RuleSetFactory
, use factory methods from RulesetsFactoryUtils
insteadAbstractApexNode
AbstractApexNodeBase
, and the related visit
+methods on ApexParserVisitor
and its implementations.
+ Use ApexNode
instead, now considers comments too.DFAGraphRule
and its implementationsDFAGraphMethod
Node
interface
+and AbstractNode
base class. See their javadoc for details.Node#isFindBoundary
is deprecated for XPath queries.net.sourceforge.pmd.lang.metrics
, though most of them were internal and
+probably not used directly outside of PMD. Use MetricsUtil
as
+a replacement for the language-specific façades too.QualifiableNode
, QualifiedName
AbstractJavaParser
AbstractJavaHandler
ASTAnyTypeDeclaration.TypeKind
ASTAnyTypeDeclaration#getKind
JavaQualifiedName
ASTCatchStatement#getBlock
ASTCompilationUnit#declarationsAreInDefaultPackage
JavaQualifiableNode
+
+ net.sourceforge.pmd.lang.java.qname
and its contentsMethodLikeNode
+ ASTMethodOrConstructorDeclaration
,
+ASTLambdaExpression
.ASTAnyTypeDeclaration#getImage
will be removed. Please use getSimpleName()
+instead. This affects ASTAnnotationTypeDeclaration#getImage
,
+ASTClassOrInterfaceDeclaration#getImage
, and
+ASTEnumDeclaration#getImage
.ASTTryStatement
, replacements with other names
+have been added. This includes the XPath attribute @Finally
, replace it with a test for child::FinallyStatement
.getGuardExpressionNode
are replaced with getCondition
. This affects the
+following nodes: WhileStatement, DoStatement, ForStatement, IfStatement, AssertStatement, ConditionalExpression.ASTYieldStatement
will not implement TypeNode
+anymore come 7.0.0. Test the type of the expression nested within it.JavaMetrics
, JavaMetricsComputer
ASTArguments#getArgumentCount
.
+Use size
instead.ASTFormalParameters#getParameterCount
.
+Use size
instead.As part of the changes we’d like to do to AST classes for 7.0.0, we would like to +hide some methods and constructors that rule writers should not have access to. +The following usages are now deprecated in the JSP AST (with other languages to come):
+ +InternalApi
. Nodes should only be obtained from the parser,
+which for rules, means that they never need to instantiate node themselves.
+Those constructors will be made package private with 7.0.0.JspParser
is deprecated and should not be used directly.
+Use LanguageVersionHandler#getParser
instead.Please look at net.sourceforge.pmd.lang.jsp.ast
to find out the full list of deprecations.
As part of the changes we’d like to do to AST classes for 7.0.0, we would like to +hide some methods and constructors that rule writers should not have access to. +The following usages are now deprecated in the VM AST (with other languages to come):
+ +InternalApi
. Nodes should only be obtained from the parser,
+which for rules, means that they never need to instantiate node themselves.
+Those constructors will be made package private with 7.0.0.net.sourceforge.pmd.lang.vm.directive
as well as the classes
+DirectiveMapper
and LogUtil
are deprecated
+for removal. They were only used internally during parsing.VmParser
is deprecated and should not be used directly.
+Use LanguageVersionHandler#getParser
instead.Please look at net.sourceforge.pmd.lang.vm.ast
to find out the full list of deprecations.
The production and node ASTCursorBody
was unnecessary, not used and has been removed. Cursors have been already
+parsed as ASTCursorSpecification
.
Those APIs are not intended to be used by clients, and will be hidden or removed with PMD 7.0.0.
+You can identify them with the @InternalApi
annotation. You’ll also get a deprecation warning.
JavaLanguageHandler
JavaLanguageParser
JavaDataFlowHandler
RuleViolationFactory
in each
+language module, eg JavaRuleViolationFactory
.
+See javadoc of RuleViolationFactory
.Implementations of RuleViolation
in each language module,
+eg JavaRuleViolation
. See javadoc of
+RuleViolation
.
RuleFactory
RuleBuilder
RuleSetFactory
, use factory methods from RulesetsFactoryUtils
insteadAbstractApexNode
AbstractApexNodeBase
, and the related visit
+methods on ApexParserVisitor
and its implementations.
+ Use ApexNode
instead, now considers comments too.
CharStream
, JavaCharStream
,
+SimpleCharStream
: these are APIs used by our JavaCC
+implementations and that will be moved/refactored for PMD 7.0.0. They should not
+be used, extended or implemented directly.JJTJavaParserState
.
+This includes token classes, which will be replaced with a single implementation, and
+subclasses of ParseException
, whose usages will be replaced
+by just that superclass.Node
interface
+and AbstractNode
base class. See their javadoc for details.Node#isFindBoundary
is deprecated for XPath queries.AbstractJavaParser
AbstractJavaHandler
ASTAnyTypeDeclaration.TypeKind
ASTAnyTypeDeclaration#getKind
JavaQualifiedName
ASTCatchStatement#getBlock
ASTCompilationUnit#declarationsAreInDefaultPackage
JavaQualifiableNode
+
+ net.sourceforge.pmd.lang.java.qname
and its contentsMethodLikeNode
+ ASTMethodOrConstructorDeclaration
,
+ASTLambdaExpression
.ASTAnyTypeDeclaration#getImage
will be removed. Please use getSimpleName()
+instead. This affects ASTAnnotationTypeDeclaration#getImage
,
+ASTClassOrInterfaceDeclaration#getImage
, and
+ASTEnumDeclaration#getImage
.ASTTryStatement
, replacements with other names
+have been added. This includes the XPath attribute @Finally
, replace it with a test for child::FinallyStatement
.getGuardExpressionNode
are replaced with getCondition
. This affects the
+following nodes: WhileStatement, DoStatement, ForStatement, IfStatement, AssertStatement, ConditionalExpression.ASTYieldStatement
will not implement TypeNode
+anymore come 7.0.0. Test the type of the expression nested within it.No changes.
+ +net.sourceforge.pmd.dcd
and its subpackages. See DCD
.LanguageRegistry
:
+
+ RuleSet#getExcludePatterns
. Use the new method getFileExclusions
instead.RuleSet#getIncludePatterns
. Use the new method getFileInclusions
instead.Parser#canParse
Parser#getSuppressMap
RuleBuilder#RuleBuilder
. Use the new constructor with the correct ResourceLoader instead.RuleFactory#RuleFactory
. Use the new constructor with the correct ResourceLoader instead.CanSuppressWarnings
and its implementationsisSuppressed
getDeclaringType
.isSupressed
ASTMethodDeclarator
getMethodName
getBlock
getParameterCount
CanSuppressWarnings
and its implementationsisSupressed
net.sourceforge.pmd.util
and its subpackages,
+except net.sourceforge.pmd.util.datasource
and net.sourceforge.pmd.util.database
.GridBagHelper
ColumnDescriptor
Each renderer has now a new method Renderer#setUseShortNames
which
+is used for implementing the “shortnames” CLI option. The method is automatically called by PMD, if this
+CLI option is in use. When rendering filenames to the report, the new helper method
+AbstractRenderer#determineFileName
should be used. This will change
+the filename to a short name, if the CLI option “shortnames” is used.
Not adjusting custom renderers will make them render always the full file names and not honoring the +CLI option “shortnames”.
+getImportedNameNode
and
+getPackage
have been deprecated and
+will be removed with PMD 7.0.0.RuleContext#setSourceCodeFilename
has been deprecated
+and will be removed. The already existing method RuleContext#setSourceCodeFile
+should be used instead. The method RuleContext#getSourceCodeFilename
still
+exists and returns just the filename without the full path.AbstractPMDProcessor#filenameFrom
has been
+deprecated. It was used to determine a “short name” of the file being analyzed, so that the report
+can use short names. However, this logic has been moved to the renderers.Report#metrics
and Report
have
+been deprecated. They were leftovers from a previous deprecation round targeting
+StatisticalRule
.Those APIs are not intended to be used by clients, and will be hidden or removed with PMD 7.0.0. You can identify them with the @InternalApi
annotation. You’ll also get a deprecation warning.
net.sourceforge.pmd.lang.java.typeresolution
: Everything, including
+subpackages, except TypeHelper
and
+JavaTypeDefinition
.ASTCompilationUnit#getClassTypeResolver
No changes.
+ +++ +Reminder: Please don’t use members marked with the annotation
+InternalApi
, as they will likely be removed, hidden, or otherwise intentionally broken with 7.0.0.
As part of the changes we’d like to do to AST classes for 7.0.0, we would like to +hide some methods and constructors that rule writers should not have access to. +The following usages are now deprecated in the Java AST (with other languages to come):
+ +InternalApi
. Nodes should only be obtained from the parser, which for rules, means that never need to instantiate node themselves. Those constructors will be made package private with 7.0.0.Please look at net.sourceforge.pmd.lang.java.ast
to find out the full list
+of deprecations.
DumpFacades
in all languages, that could be used to transform a AST into a textual representation,
+will be removed with PMD 7. The rule designer is a better way to inspect nodes.
+ net.sourceforge.pmd.lang.apex.ast.DumpFacade
net.sourceforge.pmd.lang.java.ast.DumpFacade
net.sourceforge.pmd.lang.ecmascript.ast.DumpFacade
net.sourceforge.pmd.lang.jsp.ast.DumpFacade
net.sourceforge.pmd.lang.plsql.ast.DumpFacade
net.sourceforge.pmd.lang.vf.ast.DumpFacade
net.sourceforge.pmd.lang.vm.ast.AbstractVmNode#dump
net.sourceforge.pmd.lang.xml.ast.DumpFacade
LanguageVersionHandler#getDumpFacade
will be
+removed as well. It is deprecated, along with all its implementations in the subclasses of LanguageVersionHandler
.No changes.
+ +The start scripts run.sh
, pmd.bat
and cpd.bat
support the new environment variable PMD_JAVA_OPTS
.
+This can be used to set arbitrary JVM options for running PMD, such as memory settings (e.g. PMD_JAVA_OPTS=-Xmx512m
)
+or enable preview language features (e.g. PMD_JAVA_OPTS=--enable-preview
).
The previously available variables such as OPTS
or HEAPSIZE
are deprecated and will be removed with PMD 7.0.0.
CodeClimateRule
is deprecated in 7.0.0 because it was unused for 2 years and
+created an unwanted dependency.
+Properties “cc_categories”, “cc_remediation_points_multiplier”, “cc_block_highlighting” will also be removed.
+See #1702 for more.
The Apex ruleset rulesets/apex/ruleset.xml
has been deprecated and will be removed in 7.0.0. Please use the new
+quickstart ruleset rulesets/apex/quickstart.xml
instead.
No changes.
+ +StatisticalRule
and the related helper classes and base rule classes
+are deprecated for removal in 7.0.0. This includes all of net.sourceforge.pmd.stat
and net.sourceforge.pmd.lang.rule.stat
,
+and also AbstractStatisticalJavaRule
, AbstractStatisticalApexRule
and the like.
+The methods Report#addMetric
and metricAdded
+will also be removed.setProperty
is deprecated,
+because MultiValuePropertyDescriptor
is deprecated as wellThe 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
+ +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
,
+is being replaced by the simpler PropertyBuilder
. Their APIs enjoy a high degree of source compatibility.
Concrete property classes like IntegerProperty
and StringMultiProperty
will gradually
+all be deprecated until 7.0.0. Their usages should be replaced by direct usage of the PropertyDescriptor
+interface, e.g. PropertyDescriptor<Integer>
or PropertyDescriptor<List<String>>
.
Instead of spreading properties across countless classes, the utility class PropertyFactory
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
is replaced by PropertyFactory#intProperty
+ IntegerMultiProperty
is replaced by PropertyFactory#intListProperty
FloatProperty
and DoubleProperty
are both replaced by PropertyFactory#doubleProperty
.
+Having a separate property for floats wasn’t that useful.
+ FloatMultiProperty
and DoubleMultiProperty
are replaced by PropertyFactory#doubleListProperty
.StringProperty
is replaced by PropertyFactory#stringProperty
+ StringMultiProperty
is replaced by PropertyFactory#stringListProperty
RegexProperty
is replaced by PropertyFactory#regexProperty
EnumeratedProperty
is replaced by PropertyFactory#enumProperty
+ EnumeratedProperty
is replaced by PropertyFactory#enumListProperty
BooleanProperty
is replaced by PropertyFactory#booleanProperty
+ BooleanMultiProperty
, is not replaced, because it doesn’t have a use case.CharacterProperty
is replaced by PropertyFactory#charProperty
+ CharacterMultiProperty
is replaced by PropertyFactory#charListProperty
LongProperty
is replaced by PropertyFactory#longIntProperty
+ LongMultiProperty
is replaced by PropertyFactory#longIntListProperty
MethodProperty
, FileProperty
, 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:
+// 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<Integer> 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.
+ +EnumeratedPropertyDescriptor
, NumericPropertyDescriptor
, PackagedPropertyDescriptor
,
+and the related builders (in net.sourceforge.pmd.properties.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 PropertyConstraint
s,
+which will allow virtually any constraint to be defined, and improve documentation and error reporting. The
+related methods PropertyTypeId#isPropertyNumeric
and
+PropertyTypeId#isPropertyPackaged
are also deprecated.
MultiValuePropertyDescriptor
and 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 PropertyDescriptor#isMultiValue
will be removed
+accordingly.
preferredRowCount
is deprecated with no intended replacement. It was never implemented, and does not belong
+in this interface. The methods 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<PropertyDescriptor>
anymore come 7.0.0.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<String>
with the shift to Java 8.The implementation of the adapters for the XPath engines Saxon and Jaxen (package net.sourceforge.pmd.lang.ast.xpath
)
+are now deprecated. They’ll be moved to an internal package come 7.0.0. Only Attribute
remains public API.
The classes PropertyDescriptorField
, PropertyDescriptorBuilderConversionWrapper
, and the methods
+PropertyDescriptor#attributeValuesById
, PropertyDescriptor#isDefinedExternally
and PropertyTypeId#getFactory
.
+These were used to read and write properties to and from XML, but were not intended as public API.
The class ValueParserConstants
and the interface ValueParser
.
All classes from net.sourceforge.pmd.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,
+JavaParserVisitorAdapter
should be directly subclassed.
LanguageVersionHandler#getDataFlowHandler()
, LanguageVersionHandler#getDFAGraphRule()
All classes from net.sourceforge.pmd.properties.modules
will be removed.
The interface 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).
Several methods from ASTLocalVariableDeclaration
and ASTFieldDeclaration
have
+also been deprecated:
ASTFieldDeclaration
won’t be a TypeNode
come 7.0.0, so
+getType
and
+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
>
+though, so you should iterate on each declared variable. See #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.
+ +net.sourceforge.pmd.lang.java.ast
: JavaParserDecoratedVisitor
, JavaParserControllessVisitor
,
+JavaParserControllessVisitorAdapter
, and 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:
+ +CppHandler
CppLanguageModule
CppParser
CsLanguageModule
FortranLanguageModule
GroovyLanguageModule
MatlabHandler
MatlabLanguageModule
MatlabParser
ObjectiveCHandler
ObjectiveCLanguageModule
ObjectiveCParser
PhpLanguageModule
PythonHandler
PythonLanguageModule
PythonParser
RubyLanguageModule
ScalaLanguageModule
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. Consequently, the following APIs are deprecated for +removal:
+Rule
: isDfa()
, isTypeResolution()
, isMultifile()
and their
+respective setters.RuleSet
: usesDFA(Language)
, usesTypeResolution(Language)
, usesMultifile(Language)
RuleSets
: usesDFA(Language)
, usesTypeResolution(Language)
, usesMultifile(Language)
LanguageVersionHandler
: getDataFlowFacade()
, getSymbolFacade()
, getSymbolFacade(ClassLoader)
,
+getTypeResolutionFacade(ClassLoader)
, getQualifiedNameResolutionFacade(ClassLoader)
No changes.
+ +A couple of methods and fields in net.sourceforge.pmd.properties.AbstractPropertySource
have been
+deprecated, as they are replaced by already existing functionality or expose internal implementation
+details: propertyDescriptors
, propertyValuesByDescriptor
,
+copyPropertyDescriptors()
, copyPropertyValues()
, ignoredProperties()
, usesDefaultValues()
,
+useDefaultValueFor()
.
Some methods in net.sourceforge.pmd.properties.PropertySource
have been deprecated as well:
+usesDefaultValues()
, useDefaultValueFor()
, ignoredProperties()
.
The class net.sourceforge.pmd.lang.rule.AbstractDelegateRule
has been deprecated and will
+be removed with PMD 7.0.0. It is internally only in use by RuleReference.
The default constructor of net.sourceforge.pmd.lang.rule.RuleReference
has been deprecated
+and will be removed with PMD 7.0.0. RuleReferences should only be created by providing a Rule and
+a RuleSetReference. Furthermore the following methods are deprecated: setRuleReference()
,
+hasOverriddenProperty()
, usesDefaultValues()
, useDefaultValueFor()
.
All classes in the package net.sourceforge.pmd.lang.dfa.report
have been deprecated and will be removed
+with PMD 7.0.0. This includes the class net.sourceforge.pmd.lang.dfa.report.ReportTree
. The reason is,
+that this class is very specific to Java and not suitable for other languages. It has only been used for
+YAHTMLRenderer
, which has been rewritten to work without these classes.
The nodes RUNSIGNEDSHIFT and RSIGNEDSHIFT are deprecated and will be removed from the AST with PMD 7.0.0. +These represented the operator of ShiftExpression in two cases out of three, but they’re not needed and +make ShiftExpression inconsistent. The operator of a ShiftExpression is now accessible through +ShiftExpression#getOperator.
+The utility class net.sourceforge.pmd.lang.java.ast.CommentUtil
has been deprecated and will be removed
+with PMD 7.0.0. Its methods have been intended to parse javadoc tags. A more useful solution will be added
+around the AST node FormalComment
, which contains as children JavadocElement
nodes, which in
+turn provide access to the JavadocTag
.
All comment AST nodes (FormalComment
, MultiLineComment
, SingleLineComment
) have a new method
+getFilteredComment()
which provide access to the comment text without the leading /*
markers.
The method AbstractCommentRule.tagsIndicesIn()
has been deprecated and will be removed with
+PMD 7.0.0. It is not very useful, since it doesn’t extract the information
+in a useful way. You would still need check, which tags have been found, and with which
+data they might be accompanied.
net.sourceforge.pmd.benchmark
have been deprecated: Benchmark
, Benchmarker
,
+BenchmarkReport
, BenchmarkResult
, RuleDuration
, StringBuilderCR
and TextReport
. Their API is not supported anymore
+and is disconnected from the internals of PMD. Use the newer API based around TimeTracker
instead, which can be found
+in the same package.net.sourceforge.pmd.lang.java.xpath.TypeOfFunction
has been deprecated. Use the newer TypeIsFunction
in the same package.typeof
methods in net.sourceforge.pmd.lang.java.xpath.JavaFunctions
have been deprecated.
+Use the newer typeIs
method in the same class instead..isA
, isEither
and isNeither
of net.sourceforge.pmd.lang.java.typeresolution.TypeHelper
.
+Use the new isExactlyAny
and isExactlyNone
methods in the same class instead.The static method PMDParameters.transformParametersIntoConfiguration(PMDParameters)
is now deprecated,
+for removal in 7.0.0. The new instance method PMDParameters.toConfiguration()
replaces it.
The method ASTConstructorDeclaration.getParameters()
has been deprecated in favor of the new method
+getFormalParameters()
. This method is available for both ASTConstructorDeclaration
and
+ASTMethodDeclaration
.
getXPathNodeName
is added to the Node
interface, which removes the
+use of the toString
of a node to get its XPath element name (see #569).
+ AbstractNode
, will
+be removed with 7.0.0Node.toString
method will not necessarily provide its XPath node
+name anymore.The interface net.sourceforge.pmd.cpd.Renderer
has been deprecated. A new interface
+net.sourceforge.pmd.cpd.renderer.CPDRenderer
has been introduced to replace it. The main
+difference is that the new interface is meant to render directly to a java.io.Writer
+rather than to a String. This allows to greatly reduce the memory footprint of CPD, as on
+large projects, with many duplications, it was causing OutOfMemoryError
s (see #795).
net.sourceforge.pmd.cpd.FileReporter
has also been deprecated as part of this change, as it’s no longer needed.
net.sourceforge.pmd.PMD.VERSION
has been deprecated and will be removed with PMD 7.0.0.
+Please use net.sourceforge.pmd.PMDVersion.VERSION
instead.The Java rules VariableNamingConventions
, MIsLeadingVariableName
,
+SuspiciousConstantFieldName
, and AvoidPrefixingMethodParameters
are
+now deprecated, and will be removed with version 7.0.0. They are replaced by the more general
+FieldNamingConventions
, FormalParameterNamingConventions
, and
+LocalVariableNamingConventions
.
The Java rule AbstractNaming
is deprecated
+in favour of ClassNamingConventions
.
The Java rules WhileLoopsMustUseBraces
, ForLoopsMustUseBraces
, IfStmtsMustUseBraces
, and IfElseStmtsMustUseBraces
+are deprecated. They will be replaced by the new rule ControlStatementBraces
.
The Java rules NcssConstructorCount
, NcssMethodCount
, and NcssTypeCount
have been
+deprecated. They will be replaced by the new rule NcssCount
in the category design
.
The Java rule LooseCoupling
in ruleset java-typeresolution
is deprecated. Use the rule with the same name from category bestpractices
instead.
The Java rule CloneMethodMustImplementCloneable
in ruleset java-typeresolution
is deprecated. Use the rule with the same name from category errorprone
instead.
The Java rule UnusedImports
in ruleset java-typeresolution
is deprecated. Use the rule with
+the same name from category bestpractices
instead.
The Java rule SignatureDeclareThrowsException
in ruleset java-typeresolution
is deprecated. Use the rule with the same name from category design
instead.
The Java rule EmptyStaticInitializer
in ruleset java-empty
is deprecated. Use the rule EmptyInitializer
, which covers both static and non-static empty initializers.`
The Java rules GuardDebugLogging
(ruleset java-logging-jakarta-commons
) and GuardLogStatementJavaUtil
+(ruleset java-logging-java
) have been deprecated. Use the rule GuardLogStatement
, which covers all cases regardless of the logging framework.
The Java rule UnsynchronizedStaticDateFormatter
has been deprecated and
+will be removed with PMD 7.0.0. The rule is replaced by the more general
+UnsynchronizedStaticFormatter
.
The two Java rules PositionLiteralsFirstInComparisons
+and PositionLiteralsFirstInCaseInsensitiveComparisons
(ruleset java-bestpractices
)
+have been deprecated in favor of the new rule LiteralsFirstInComparisons
.
The Java rule AvoidFinalLocalVariable
(java-codestyle
) has been deprecated
+and will be removed with PMD 7.0.0. The rule is controversial and also contradicts other existing
+rules such as LocalVariableCouldBeFinal
. If the goal is to avoid defining
+constants in a scope smaller than the class, then the rule AvoidDuplicateLiterals
+should be used instead.
The Apex rule VariableNamingConventions
(apex-codestyle
) has been deprecated and
+will be removed with PMD 7.0.0. The rule is replaced by the more general rules
+FieldNamingConventions
,
+FormalParameterNamingConventions
,
+LocalVariableNamingConventions
, and
+PropertyNamingConventions
.
The Java rule LoggerIsNotStaticFinal
(java-errorprone
) has been deprecated
+and will be removed with PMD 7.0.0. The rule is replaced by ProperLogger
.
The Java rule DataflowAnomalyAnalysis
(java-errorprone
)
+is deprecated in favour of UnusedAssignment
(java-bestpractices
),
+which was introduced in PMD 6.26.0.
The main homepage of PMD https://pmd.github.io is hosted by Github Pages.
+ +The repository is https://github.com/pmd/pmd.github.io.
+ +It uses Jekyll to generate the static html pages. Jekyll is +executed by github for every push to the repository. Please note, that it takes some time +until Jekyll has been executed and due to caching, the homepage is not updated immediately. +It usually takes 15 minutes.
+ +_config.yml
and the variables site.pmd.latestVersion
are used
+e.g. in _includes/home.html.pmd-<version>/
.Since the repository contains the documentation for many old PMD releases, it is quite big. When executing
+Jekyll to generate the site, it copies all the files to the folder _site/
- and this can take a while.
In order to speed things up locally, consider to add pmd-*
to the exclude patterns in _config.yml
. See
+also the comments in this file.
Then it is a matter of simply executing bundle exec jekyll serve
. This will generate the site and host
+it on localhost, so you can test the page at http://127.0.0.1:4000.
When creating a new PMD release, some content of the main page need to be updated as well. +This done as part of the Release process, but is +summarized here as well:
+ +pmd.latestVersion
) needs to be updated in _config.yml
+ /pmd-<version>/
/latest/
, actually replacing the old version./_posts/YYYY-mm-dd-PMD-<version>.md
sitemap.xml
is regeneratedSome of these steps are automated through do-release.sh
(like blog post), some are manual steps
+(updating the version in _config.yml) and other steps are done on the travis-ci-build (like
+copying the new documentation).
Adding a new blog post is as easy as:
+ +/_posts/YYYY-mm-dd-<title>.md
---
+layout: post
+title: Title
+---
+
+Here comes the text
+
Once you commit and push it, Github will run Jekyll and update the page. The Jekyll templates take care that +the new post is recognized and added to the news section and also on the news subpage.
+ + + + + + +Review the pull request
+ +The actual merge commands:
+ +We assume, that the PR has been created from the master branch. If this is not the case, +then we’ll either need to rebase or ask for rebasing before merging.
+ +git checkout master && git pull origin master # make sure, you have the latest code
+git fetch origin pull/123/head:pr-123 && git checkout pr-123 # creates a new temporary branch
+
Update the release notes:
+ +Commit these changes with the message:
+ +git add docs/pages/release_notes.md
+git commit -m "Update release notes, refs #123"
+
Update release notes, refs #123, fixes #issue-number
.
+This will automatically close the github issue.Now merge the pull request into the master branch:
+ +git checkout master
+git merge --no-ff pr-123
+
Run the complete build: ./mvnw clean verify
If the build was successful, you are ready to push:
+ +git push origin master
+
Since the temporary branch is now not needed anymore, you can delete it:
+git branch -d pr-123
.
We ask, to create every pull request against master, to make it easier to contribute. +But if a pull request is intended to fix a bug in an older version of PMD, then we need to backport this pull request.
+ +For older versions, we use maintenance branches, like pmd/5.8.x
. If there is no maintenance branch for
+the specific version, then we’ll have to create it first. Let’s say, we want a maintenance branch for
+PMD version 5.8.0, so that we can create a bugfix release 5.8.1.
We’ll simply create a new branch off of the release tag:
+ +git branch pmd/5.8.x pmd_releases/5.8.0 && git checkout pmd/5.8.x
+
Now we’ll need to adjust the version, since it’s currently the same as the release version. +We’ll change the version to the next patch version: “5.8.1-SNAPSHOT”.
+ +./mvnw versions:set -DnewVersion=5.8.1-SNAPSHOT
+git add pom.xml \*/pom.xml
+git commit -m "prepare next version 5.8.1-SNAPSHOT"
+
As above: Review the PR
+Fetch the PR and rebase it onto the maintenance branch:
+ +git fetch origin pull/124/head:pr-124 && git checkout pr-124 # creates a new temporary branch
+git rebase master --onto pmd/5.8.x
+./mvnw clean verify # make sure, everything works after the rebase
+
Update the release notes. See above for details.
+Now merge the pull request into the maintenance branch:
+ +git checkout pmd/5.8.x
+git merge --no-ff pr-124
+
Just to be sure, run the complete build again: ./mvnw clean verify
.
If the build was successful, you are ready to push:
+ +git push origin pmd/5.8.x
+
Since we have rebased the pull request, it won’t appear as merged on github. +You need to manually close the pull request. Leave a comment, that it has been +rebased onto the maintenance branch.
+Now the PR has been merged into the maintenance branch, but it is missing in any later version of PMD. +Therefore, we merge first into the next minor version maintenance branch (if existing):
+ +git checkout pmd/5.9.x
+git merge pmd/5.8.x
+
After that, we merge the changes into the master branch:
+ +git checkout master
+git merge pmd/5.9.x
+
pom.xml
files, since
+every branch changed the version number differently.We are not using cherry-picking, so that each fix is represented by a single commit. +Cherry-picking would duplicate the commit and you can’t see in the log, on which branches the fix has been +integrated (e.g. gitk and github show the branches, from which the specific commit is reachable).
+ +The downside is a more complex history - the maintenance branches and master branch are “connected” and not separate.
+ + + + + + +This page describes the current status of the release process.
+ +Since versions 5.4.5 / 5.5.4 there is an automated release process using travis-ci +in place. However, there are still a few steps, that need manual examination.
+ +Note: You can find a small shell script in the root of the repo: do-release.sh
. This script guides you
+through the release process.
Make sure code is up to date and everything is committed and pushed with git:
+ +$ ./mvnw clean
+$ git pull
+$ git status
+
You can find the release notes here: docs/pages/release_notes.md
.
The date (date +%d-%B-%Y
) and the version (remove the SNAPSHOT) must be updated in docs/_config.yml
, e.g.
pmd:
+ version: 6.22.0
+ previous_version: 6.21.0
+ date: 12-March-2020
+ release_type: minor
+
The release type could be one of “bugfix”, “minor”, or “major”.
+ +The release notes usual mention any new rules that have been added since the last release.
+Please double check the file pmd-core/src/main/resources/rulesets/releases/<version>.xml
, so
+that all new rules are listed.
Add the new rules as comments to the quickstart rulesets:
+pmd-apex/src/main/resources/rulesets/apex/quickstart.xml
pmd-java/src/main/resources/rulesets/java/quickstart.xml
We maintain a documentation for the next major release. Copy the API
+changes from the current release notes to this document: docs/pages/next_major_development.md
.
The designer lives at pmd/pmd-designer.
+Update property pmd-designer.version
in pom.xml to reference the latest pmd-designer release.
+See https://search.maven.org/search?q=g:net.sourceforge.pmd%20AND%20a:pmd-ui&core=gav for the available releases.
Starting with PMD 6.23.0 we’ll provide small statistics for every release. This needs to be added +to the release notes as the last section. To count the closed issues and pull requests, the milestone +on github with the title of the new release is searched. Make sure, there is a milestone +on https://github.com/pmd/pmd/milestones. The following snippet will +create the numbers, that can be attached to the release notes as a last section:
+ +LAST_VERSION=6.22.0
+NEW_VERSION=6.23.0
+NEW_VERSION_COMMITISH=HEAD
+
+echo "### Stats"
+echo "* $(git log pmd_releases/${LAST_VERSION}..${NEW_VERSION_COMMITISH} --oneline --no-merges |wc -l) commits"
+echo "* $(curl -s https://api.github.com/repos/pmd/pmd/milestones|jq ".[] | select(.title == \"$NEW_VERSION\") | .closed_issues") closed tickets & PRs"
+echo "* Days since last release: $(( ( $(date +%s) - $(git log --max-count=1 --format="%at" pmd_releases/${LAST_VERSION}) ) / 86400))"
+
Note: this part is also integrated into do-release.sh
.
Check in all (version) changes to branch master or any other branch, from which the release takes place:
+ +$ git commit -a -m "Prepare pmd release <version>"
+$ git push
+
The github repo pmd.github.io
hosts the homepage for https://pmd.github.io.
The new version needs to be entered into _config.yml
, e.g.:
pmd:
+ latestVersion: 6.22.0
+ latestVersionDate: 12-March-2020
+
Also move the previous version down into the “downloads” section.
+ +Then create a new page for the new release, e.g. _posts/2020-03-12-PMD-6.22.0.md
and copy
+the release notes into this page. This will appear under the news section.
Check in all (version) changes to branch master:
+ +$ git commit -a -m "Prepare pmd release <version>"
+$ git push
+
The release is created using the maven-release-plugin. This plugin changes the version by basically +removing the “-SNAPSHOT” suffix, builds the changed project locally, commits the version change, creates +a new tag from this commit, changes the version of the project to the next snapshot, commits this change +and pushes everything.
+ +RELEASE_VERSION
is the version of the release. It is reused for the tag. DEVELOPMENT_VERSION
is the
+next snapshot version after the release.
mvn -B release:clean release:prepare \
+ -Dtag=pmd_releases/${RELEASE_VERSION} \
+ -DreleaseVersion=${RELEASE_VERSION} \
+ -DdevelopmentVersion=${DEVELOPMENT_VERSION}
+
Once the maven plugin has pushed the tag, travis-ci will start and build a new version from this tag. Since +it is a tag build and a released version build, travis-ci will do a couple of additional stuff:
+ +latest
.The release on travis currently takes about 30 minutes. Once this is done, you can spread the news:
+ +Submit news to SF on the PMD Project News page. You can use +the following template:
+ +PMD <version> released
+
+* Downloads: https://github.com/pmd/pmd/releases/tag/pmd_releases%2F<version>
+* Documentation: https://pmd.github.io/pmd-<version>/
+
+And Copy-Paste the release notes
+
To: PMD Developers List <pmd-devel@lists.sourceforge.net>
+Subject: [ANNOUNCE] PMD <version> released
+
+
+* Downloads: https://github.com/pmd/pmd/releases/tag/pmd_releases%2F<version>
+* Documentation: https://pmd.github.io/pmd-<version>/
+
+And Copy-Paste the release notes
+
Update version in docs/_config.yml. Note - the next version needs to have a SNAPSHOT in it.
+ +pmd:
+ version: 6.23.0-SNAPSHOT
+ previous_version: 6.22.0
+ date: ??-??-2020
+ release_type: minor
+
---
+title: PMD Release Notes
+permalink: pmd_release_notes.html
+keywords: changelog, release notes
+---
+
+## {{ site.pmd.date }} - {{ site.pmd.version }}
+
+The PMD team is pleased to announce PMD {{ site.pmd.version }}.
+
+This is a {{ site.pmd.release_type }} release.
+
+{% tocmaker %}
+
+### New and noteworthy
+
+### Fixed Issues
+
+### API Changes
+
+### External Contributions
+
+{% endtocmaker %}
+
+
Commit and push
+ +$ git commit -m "Prepare next development version"
+$ git push origin master
+
Manage the milestones under https://github.com/pmd/pmd/milestones. +Maybe there are some milestones on sourceforge, too: https://sourceforge.net/p/pmd/bugs/milestones.
+ +If the release was done on a maintenance branch, such as pmd/5.4.x
, then this branch should be
+merged into the next “higher” branches, such as pmd/5.5.x
and master
.
This ensures, that all fixes done on the maintenance branch, finally end up in the other branches. +In theory, the fixes should already be there, but you never now.
+ +If releases from multiple branches are being done, the order matters. You should start from the “oldest” branch,
+e.g. pmd/5.4.x
, release from there. Then merge (see above) into the next branch, e.g. pmd/5.5.x
and release
+from there. Then merge into the master
branch and release from there. This way, the last release done, becomes
+automatically the latest release on https://pmd.github.io/latest/ and on sourceforge.
At some point, it might be time for a new maintenance branch. Such a branch is usually created from
+the master
branch. Here are the steps:
git branch pmd/5.6.x master
mvn versions:set -DnewVersion=5.6.1-SNAPSHOT
+and mvn versions:set -DnewVersion=5.7.0-SNAPSHOT
.+ MicroDoc for sponsoring PMD development. + MicroDoc is a software business serving an international customer base. Since 1991 MicroDoc + has grown into a technology oriented software engineering and professional services company. + Our focus on complex software technology and software infrastructure made us a well + respected partner for large corporations and even for other software businesses. + | +|
+ AE for the JSP integration and especially for writing the JSP grammar. + | +|
+ DARPA for funding + the Ultra*Log and Cougaar + effort which spawned PMD. + | +|
+ SourceForge for providing hosting services for PMD. + | +|
+ RefactorIT for letting + their software be used free-of-charge on PMD code + (OpenSource + Community License) + | +|
+ QA-Systems for sending in some + handy utilities for PMD and shipping PMD inside their QStudio product + | +|
+ | + Vanward Technologies for + using PMD inside their Convergence product + | +
+ Cenqua for + giving us a free Clover license and doing a nice FishEye run. + | +|
+ YourKit is kindly supporting open source projects with its full-featured Java Profiler. + YourKit, LLC is creator of innovative and intelligent tools for profiling + Java and .NET applications. Take a look at YourKit's leading software products: + YourKit Java Profiler and + YourKit .NET Profiler. + | +|
+ Bijzonder Bezig for giving the PMD logo a modern look. + | +
Have this clear: having a projects with no pmd violations does not mean at all, I repeat, +it does not mean at all, not at the minimum expected, that the project has any quality. +For illustrating this I’ll tell a little story taken from my work (a sadly real story). +Some classes had fields that were reported as unused, (unused code ruleset) as developers +saw this, they wanted to remove the violation, (not fix the code, fix the violation) so +the action took was to add useless log sentences with something like: +‘unused variable ‘+unusedVariable. Believe it or not, the code was worse than the original +and reported less pmd violations.
+ +In a more positive way: use the rules as you see them fix, don’t try to remove violations +per-se, try to review the code and see if the particular cases you are using are correct or not.
+ +The parser performs a depth-first traversal. +Consider the given source:
+ +public class Foo {
+ String name;
+ private class Bar {
+ String x;
+ }
+ int total;
+}
+
The visiting order here will be:
+ +Note that the total field of Foo will be visited after visiting the fields in Bar. +You must take this into account for certain rules.
+ +Yes, the symbol table can supply that information.
+ +FIXME: add code example
+ + + + + + +We’ve been trying to find the meaning of the letters PMD - because frankly, we don’t +really know. We just think the letters sound good together.
+ +However, in the spirit of the Computing Industry, we have come up with several “backronyms” to explain it.
+ +PMD…
+ +March 2020 - Helping Salesforce developers create readable and maintainable Apex code
+July 2019 - Apex PMD | Static code analysis - Apex Hours
+June 2019 - Pluralsight Course about leveraging PMD usage for Salesforce by Robert Sösemann (Apex Language Module Contributor) Play by Play: Automated Code Analysis in Salesforce - a Tools Deep-Dive
+June 2018 - Salesforce Way Podcast with Robert Sösemann Static Code Analysis with PMD for Apex
+January 2018 - Webinar: How to contribute Apex rules to PMD with Robert Sösemann
+August 2017 - Webinar about how to use PMD with The Welkin Suite Salesforce IDE - Author Robert Sösemann - Improving your Apex Code Quality with PMD in The Welkin Suite
+November 2016 - Recording of Robert Sösemann’s Session at Salesforce Dreamforce Conference about enforcing Clean Code in the Salesforce world using PMD and other tools Clean Apex Code with Automatic Code Metrics
+May 2019 - Code quality assurance with PMD – An extensible static code analyser for Java and other languages
+February 2012 - Romain Pelisse’s lightning talk at FOSDEM 2012 about “PMD5: What can it do for you?”. +Video recording is available.
+May 2008 - Romain Pelisse’s article in LinuxMagazin: An introduction + to PMD (in French)
+July 2007 - Ryan Slobojan’s article on InfoQ +discusses the PMD 4.0 release.
+July 2006 - Paul Duvall’s article “Automation for the people: Continuous Inspection” on +developerWorks discusses CPD.
+June 2006 - Andrew Glover’s article “In pursuit of code quality: Tame the chatterbox” on +developerWorks +discusses PMD and JavaNCSS.
+June 2006 - Tom Copeland’s article “Static Electricity: Better Living with Static Code Analysis” in +Better Software discusses +PMD/CPD analyses of Azureus and Columba.
+April 2006 - John Ferguson Smart’s article “PMD Squashes Code Bugs” on +DevX discusses PMD and the Eclipse plugin. Lots of screenshots!
+November 2005 - Mike Clark’s article “Staying Out of Code Debt” on +StickyMinds +mentions both PMD and CPD as useful code-checking tools.
+October 2005 - Levent Gurses’ article “Improving Code Quality with PMD and Eclipse” in +EclipseZone talks about the PMD Eclipse plugin and explains many +different facets of PMD - XPath, writing rules, the AST, all that. Good stuff!
+June 2005 - Amit Chaturvedi’s article “Java & Static Analysis” in +Doctor Dobb’s Journal talks about PMD and shows a +screenshot of the rule designer
+March 2005 - Kirk Knoernschild’s article “Benefits of the Build” in +Doctor Dobb’s Journal mentions PMD as a way +to automate code reviews
+February 2005 - Java Is Well-Suited for Open-Source Projects - +Peter Coffee’s eWeek article on open source, Java, and PMD
+January 2005 - Zap bugs with PMD - Elliotte Rusty +Harold’s article on installing, configuring, and running PMD
+November 2004 - PMD: A code analyzer for Java programmers - Daniel +Rubio’s article about PMD; includes some notes on XPath rules
+June 2004 - Code Improvement Through Cyclomatic Complexity - +Andrew Glover’s CCM article featuring PMD
+June 2004 - Open Source-Perlen - A German article on PMD in Java Magazin
+June 2004 - Improving Project Quality with PMD - Tom Wheeler’s +“Java News Brief”, June 2004 issue
+February 2004 - Software Development - Listed as one of +their ‘Open-Source Projects to Watch’
+November 2003 - JavaWorld: “Bug patrol” - +Various code inspection tools
+June 2003 - Software Development Times - PMD is embedded in QStudio.
+May 2003 - techrepublic.com - +PMD, Checkstyle, and Jalopy
+April 2003 - O’Reilly OnJava.com - PMD custom rules
+March 2003 - O’Reilly OnJava.com - overview of CPD
+February 2003 - O’Reilly OnJava.com - overview of PMD
+January 2003 - Sprout - +interview with Ole-Martin and Tom
+Glean - Aggregates PMD + numerous other source code feedback tools
+QALab - Aggregates PMD + Checkstyle + FindBugs and tracks problems over time
+XRadar - Using PMD, CPD, and lots of other projects to give measurements on +standard software metrics such as package metrics and dependencies, code size and complexity, code duplications, +coding violations and code-style violations.
+Vanward Technology’s Convergence [link broken] - +a quality management dashboard for the Java platform. Thanks to Vanward Technologies for their support of PMD +by buying copies of PMD Applied!
+Compuware’s OptimalAdvisor [link broken] +OptimalAdvisor from ComponentSource - +static code analysis and refactoring tool
+PMD Applied - the official manual by Tom Copeland.
+ +Note: This book is from November 2005 and quite outdated. It discusses PMD 3.
+Checking Java Programs - by Ian Darwin; +also discusses FindBugs.
+Sustainable Software Development: An Agile Perspective - +by Kevin Tate, discusses both PMD and CPD
+High-Assurance Design: Architecting Secure and Reliable Enterprise Applications - +by Cliff Berg, mentions PMD in a discussion of static analysis utilities
+Eclipse Distilled - by David Carlson, +discusses the PMD plugin
+Maven: A Developer’s Notebook, co-authored by +Vincent Massol, who’s done a bunch of work on PMD. Thanks Vincent!
+Network Security Tools, chapter 6 discusses using PMD +to catch web app security problems. Thanks to Joseph Hemler for the props!
+The PMD team is pleased to announce PMD 6.30.0-SNAPSHOT.
+ +This is a minor release.
+ +ASTPackageDeclaration#getPackageNameImage
,
+ASTTypeParameter#getParameterName
+and the corresponding XPath attributes. In both cases they’re replaced with a new method getName
,
+the attribute is @Name
.ASTClassOrInterfaceBody#isAnonymousInnerClass
,
+and ASTClassOrInterfaceBody#isEnumChild
,
+refs #905Those APIs are not intended to be used by clients, and will be hidden or removed with PMD 7.0.0.
+You can identify them with the @InternalApi
annotation. You’ll also get a deprecation warning.
net.sourceforge.pmd.lang.ecmascript.Ecmascript3Handler
net.sourceforge.pmd.lang.ecmascript.Ecmascript3Parser
EcmascriptParser#parserOptions
EcmascriptParser#getSuppressMap
net.sourceforge.pmd.lang.rule.ParametricRuleViolation
ParserOptions#suppressMarker
net.sourceforge.pmd.lang.modelica.rule.ModelicaRuleViolationFactory
Previous versions of PMD can be downloaded here: https://github.com/pmd/pmd/releases
+ +The PMD team is pleased to announce PMD 6.29.0.
+ +This is a minor release.
+ +OperationWithLimitsInLoop
(apex-performance
)
+finds operations in loops that may hit governor limits such as DML operations, SOQL
+queries and more. The rule replaces the three rules “AvoidDmlStatementsInLoops”, “AvoidSoqlInLoops”,
+and “AvoidSoslInLoops”.DoNotCallSystemExit
has been renamed to
+DoNotTerminateVM
, since it checks for all the following calls:
+System.exit(int)
, Runtime.exit(int)
, Runtime.halt(int)
. All these calls terminate
+the Java VM, which is bad, if the VM runs an application server which many independent applications.AvoidDmlStatementsInLoops
,
+AvoidSoqlInLoops
and AvoidSoslInLoops
+(apex-performance
) are deprecated in favour of the new rule
+OperationWithLimitsInLoop
. The deprecated rules will be removed
+with PMD 7.0.0.The PMD team is pleased to announce PMD 6.28.0.
+ +This is a minor release.
+ +The AnyTokenizer is used for languages, that don’t have an own lexer/grammar based tokenizer. +AnyTokenizer now handles string literals and end-of-line comments. Fortran, Perl and Ruby have +been updated to use AnyTokenizer instead of their old custom tokenizer based on AbstractTokenizer. +See #2758 for details.
+ +AbstractTokenizer and the custom tokenizers of Fortran, Perl and Ruby are deprecated now.
+ +net.sourceforge.pmd.RuleViolationComparator
. Use RuleViolation#DEFAULT_COMPARATOR
instead.net.sourceforge.pmd.cpd.AbstractTokenizer
. Use net.sourceforge.pmd.cpd.AnyTokenizer
instead.net.sourceforge.pmd.cpd.FortranTokenizer
. Was replaced by an AnyTokenizer
. Use FortranLanguage#getTokenizer
anyway.net.sourceforge.pmd.cpd.PerlTokenizer
. Was replaced by an AnyTokenizer
. Use PerlLanguage#getTokenizer
anyway.net.sourceforge.pmd.cpd.RubyTokenizer
. Was replaced by an AnyTokenizer
. Use RubyLanguage#getTokenizer
anyway.RuleReference#getOverriddenLanguage
and
+RuleReference#setLanguage
net.sourceforge.pmd.lang.cs.antlr4.CSharpLexer
will be moved to package net.sourceforge.pmd.lang.cs.ast
with PMD 7.net.sourceforge.pmd.lang.dart.antlr4.Dart2Lexer
will be renamed to DartLexer
and moved to package
+net.sourceforge.pmd.lang.dart.ast
with PMD 7. All other classes in the old package will be removed.net.sourceforge.pmd.lang.go.antlr4.GolangLexer
will be moved to package
+net.sourceforge.pmd.lang.go.ast
with PMD 7. All other classes in the old package will be removed.net.sourceforge.pmd.lang.kotlin.antlr4.Kotlin
will be renamed to KotlinLexer
and moved to package
+net.sourceforge.pmd.lang.kotlin.ast
with PMD 7.net.sourceforge.pmd.lang.lua.antlr4.LuaLexer
will be moved to package
+net.sourceforge.pmd.lang.lua.ast
with PMD 7. All other classes in the old package will be removed.The PMD team is pleased to announce PMD 6.27.0.
+ +This is a minor release.
+ +This release of PMD brings support for Java 15. PMD can parse Text Blocks +which have been promoted to be a standard language feature of Java.
+ +PMD also supports Pattern Matching for instanceof, +Records, and Sealed Classes.
+ +Note: The Pattern Matching for instanceof, Records, and Sealed Classes are all preview language features of OpenJDK 15
+and are not enabled by default. In order to
+analyze a project with PMD that uses these language features, you’ll need to enable it via the environment
+variable PMD_JAVA_OPTS
and select the new language version 15-preview
:
export PMD_JAVA_OPTS=--enable-preview
+./run.sh pmd -language java -version 15-preview ...
+
Note: Support for Java 13 preview language features have been removed. The version “13-preview” is no longer available.
+ +In the past, tab characters in source files has been handled differently in different languages by PMD. +For instance in Java, tab characters had a width of 8 columns, while C# used only 1 column. Visualforce instead +used 4 columns.
+ +This has been unified now so that tab characters are consistently now always 1 column wide.
+ +This however might be a incompatible change, if you’re using the properties “BeginColumn” or “EndColumn” +additionally to “BeginLine” and “EndLine” of a Token/AST node in order to highlight +where a rule violation occurred in the source file. If you have logic there that deals with tab characters, +you most likely can remove this logic now, since tab characters are now just “normal” characters +in terms of string processing.
+ +See also [all] Ensure PMD/CPD uses tab width of 1 for tabs consistently #2656.
+ +This PMD release ships a new version of the pmd-designer. +For the changes, see PMD Designer Changelog.
+ +AvoidReassigningCatchVariables
(java-bestpractices
) finds
+cases where the variable of the caught exception is reassigned. This practice is surprising and prevents
+further evolution of the code like multi-catch.The Java rule CloseResource
(java-errorprone
) has a new property
+closeNotInFinally
. With this property set to true
the rule will also find calls to close a
+resource, which are not in a finally-block of a try-statement. If a resource is not closed within a
+finally block, it might not be closed at all in case of exceptions.
As this new detection would yield many new violations, it is disabled by default. It might be +enabled in a later version of PMD.
+DataflowAnomalyAnalysis
(java-errorprone
)
+is deprecated in favour of UnusedAssignment
(java-bestpractices
),
+which was introduced in PMD 6.26.0.language
attribute will be required on all rule
+elements that declare a new rule. Some base rule classes set the language implicitly in their
+constructor, and so this is not required in all cases for the rule to work. But this
+behavior will be discontinued in PMD 7, so missing language
attributes are now
+reported as a forward compatibility warning.Rule#getParserOptions
Parser#getParserOptions
AbstractParser
RuleContext#removeAttribute
RuleContext#getAttribute
RuleContext#setAttribute
ApexParserOptions
ASTThrowStatement#getFirstClassOrInterfaceTypeImage
EcmascriptParserOptions
EcmascriptXPathRule
XmlParserOptions
XmlXPathRule
Properties of AbstractXmlRule
net.sourceforge.pmd.Report.ReadableDuration
Many methods of net.sourceforge.pmd.Report
. They are replaced by accessors
+ that produce a List. For example, iterator()
+ (and implementing Iterable) and isEmpty()
are both
+ replaced by getViolations()
.
ASTJspDeclarations
ASTJspDocument
ScalaParserVisitorAdapter#zero
ScalaParserVisitorAdapter#combine
ApexParserVisitorReducedAdapter
TypeHelper
is deprecated in
+ favor of TypeTestUtil
, which has the
+same functionality, but a slightly changed API.net.sourceforge.pmd.lang.java.symboltable
+are deprecated as internal API.char foo = '\0';
- Mykhailo PalahutaThe PMD team is pleased to announce PMD 6.26.0.
+ +This is a minor release.
+ +UnusedAssignment
(java-bestpractices
) finds assignments
+to variables, that are never used and are useless. The new rule is supposed to entirely replace
+DataflowAnomalyAnalysis
.ArrayIsStoredDirectly
(java-bestpractices
) now ignores
+by default private methods and constructors. You can restore the old behavior by setting the new property
+allowPrivate
to “false”.RuleChainVisitor
and all implementations in language modulesAbstractRuleChainVisitor
Language#getRuleChainVisitorClass
BaseLanguageModule#<init>
ImportWrapper
unsafe
- Artem KrosheninnikovThe PMD team is pleased to announce PMD 6.25.0.
+ +This is a minor release.
+ +Up until now the PMD Scala module has been compiled against scala 2.13 only by default. +However, this makes it impossible to use pmd as a library in scala projects, +that use scala 2.12, e.g. in sbt plugins. Therefore PMD now provides cross compiled pmd-scala +modules for both versions: scala 2.12 and scala 2.13.
+ +The new modules have new maven artifactIds. The old artifactId net.sourceforge.pmd:pmd-scala:6.25.0
+is still available, but is deprecated from now on. It has been demoted to be just a delegation to the new
+pmd-scala_2.13
module and will be removed eventually.
The coordinates for the new modules are:
+ +<dependency>
+ <groupId>net.sourceforge.pmd</groupId>
+ <artifactId>pmd-scala_2.12</artifactId>
+ <version>6.25.0</version>
+</dependency>
+
+<dependency>
+ <groupId>net.sourceforge.pmd</groupId>
+ <artifactId>pmd-scala_2.13</artifactId>
+ <version>6.25.0</version>
+</dependency>
+
The command line version of PMD continues to use scala 2.13.
+ +The new Java Rule UnnecessaryCast
(java-codestyle
)
+finds casts that are unnecessary while accessing collection elements.
The new Java Rule AvoidCalendarDateCreation
(java-performance
)
+finds usages of java.util.Calendar
whose purpose is just to get the current date. This
+can be done in a more lightweight way.
The new Java Rule UseIOStreamsWithApacheCommonsFileItem
(java-performance
)
+finds usage of FileItem.get()
and FileItem.getString()
. These two methods are problematic since
+they load the whole uploaded file into memory.
The Java rule UseDiamondOperator
(java-codestyle
) now by default
+finds unnecessary usages of type parameters, which are nested, involve wildcards and are used
+within a ternary operator. These usages are usually only unnecessary with Java8 and later, when
+the type inference in Java has been improved.
In order to avoid false positives when checking Java7 only code, the rule has the new property
+java7Compatibility
, which is disabled by default. Settings this to “true” retains
+the old rule behaviour.
The maven module net.sourceforge.pmd:pmd-scala
is deprecated. Use net.sourceforge.pmd:pmd-scala_2.13
+or net.sourceforge.pmd:pmd-scala_2.12
instead.
Rule implementation classes are internal API and should not be used by clients directly.
+The rules should only be referenced via their entry in the corresponding category ruleset
+(e.g. <rule ref="category/java/bestpractices.xml/AbstractClassWithoutAbstractMethod" />
).
While we definitely won’t move or rename the rule classes in PMD 6.x, we might consider changes +in PMD 7.0.0 and onwards.
+Those APIs are not intended to be used by clients, and will be hidden or removed with PMD 7.0.0.
+You can identify them with the @InternalApi
annotation. You’ll also get a deprecation warning.
AbstractIgnoredAnnotationRule
(Java)AbstractInefficientZeroCheck
(Java)AbstractJUnitRule
(Java)AbstractJavaMetricsRule
(Java)AbstractLombokAwareRule
(Java)AbstractPoorMethodCall
(Java)AbstractSunSecureRule
(Java)AbstractNcssCountRule
(Java)AbstractCommentRule
(Java)AbstractOptimizationRule
(Java)RegexHelper
(Java)AbstractApexUnitTestRule
(Apex)AbstractNcssCountRule
(Apex)AbstractNcssCountRule
(PLSQL)ApexParser
ApexHandler
RuleChain
RuleSets
RulesetsFactoryUtils#getRuleSets
TokenEntry#TokenEntry
AbstractTokenizerTest
. Use CpdTextComparisonTest in module pmd-lang-test instead.
+For details see
+Testing your implementation
+in the developer documentation.ASTAnnotation#suppresses
(Apex)ApexXPathRule
(Apex)SymbolTableTestRule
(Java)InefficientStringBufferingRule#isInStringBufferOperation
The PMD team is pleased to announce PMD 6.24.0.
+ +This is a minor release.
+ +Thanks to Fernando Cosso CPD can now find duplicates in XML files as well. +This is useful to find duplicated sections in XML files.
+ +This PMD release ships a new version of the pmd-designer. +For the changes, see PMD Designer Changelog.
+ +The new Java Rule LiteralsFirstInComparisons
(java-bestpractices
)
+find String literals, that are used in comparisons and are not positioned first. Using the String literal
+as the receiver of e.g. equals
helps to avoid NullPointerExceptions.
This rule is replacing the two old rules PositionLiteralsFirstInComparisons
+and PositionLiteralsFirstInCaseInsensitiveComparisons
and extends the check
+for the methods compareTo
, compareToIgnoreCase
and contentEquals
in addition to equals
and
+equalsIgnoreCase
.
Note: This rule also replaces the two mentioned rules in Java’s quickstart ruleset.
+PositionLiteralsFirstInComparisons
+and PositionLiteralsFirstInCaseInsensitiveComparisons
have been deprecated
+in favor of the new rule LiteralsFirstInComparisons
.BaseLanguageModule#addVersion(String, LanguageVersionHandler, boolean)
TokenMgrError
, in particular, a new constructor is available
+that should be preferred to the old onesAntlrTokenManager.ANTLRSyntaxError
Note: Experimental APIs are identified with the annotation Experimental
,
+see its javadoc for details
BaseLanguageModule
have been replaced by a
+definitive API.The PMD team is pleased to announce PMD 6.23.0.
+ +This is a minor release.
+ +To facilitate healthy and constructive community behavior PMD adopts +Contributor Convenant as its code of +conduct.
+ +Please note that this project is released with a Contributor Code of Conduct. +By participating in this project you agree to abide by its terms.
+ +You can find the code of conduct in the file code_of_conduct.md +in our repository.
+ +XPath rules written with XPath 2.0 now support conversion to a rulechain rule, which
+improves their performance. The rulechain is a mechanism that allows several rules
+to be executed in a single tree traversal. Conversion to the rulechain is possible if
+your XPath expression looks like //someNode/... | //someOtherNode/... | ...
, that
+is, a union of one or more path expressions that start with //
. Instead of traversing
+the whole tree once per path expression (and per rule), a single traversal executes all
+rules in your ruleset as needed.
This conversion is performed automatically and cannot be disabled. The conversion should +not change the result of your rules, if it does, please report a bug at https://github.com/pmd/pmd/issues
+ +Note that XPath 1.0 support, the default XPath version, is deprecated since PMD 6.22.0. +We highly recommend that you upgrade your rules to XPath 2.0. Please refer to the migration guide.
+ +PMD uses the Rhino library to parse Javascript.
+The default version has been set to ES6
, so that some ECMAScript 2015 features are
+supported. E.g. let
statements and for-of
loops are now parsed. However Rhino does
+not support all features.
PMD now supports a JSON renderer (use it with -f json
on the CLI).
+See the documentation and example
The new Apex rule FieldDeclarationsShouldBeAtStart
(apex-codestyle
)
+helps to ensure that field declarations are always at the beginning of a class.
The new Apex rule UnusedLocalVariable
(apex-bestpractices
) detects unused
+local variables.
Those APIs are not intended to be used by clients, and will be hidden or removed with PMD 7.0.0.
+You can identify them with the @InternalApi
annotation. You’ll also get a deprecation warning.
As part of the changes we’d like to do to AST classes for 7.0.0, we would like to +hide some methods and constructors that rule writers should not have access to. +The following usages are now deprecated in the Apex, Javascript, PL/SQL, Scala and Visualforce ASTs:
+ +InternalApi
. Nodes should only be obtained from the parser,
+which for rules, means that they never need to instantiate node themselves.
+Those constructors will be made package private with 7.0.0.Parser
(eg VfParser
) are deprecated and should not be used directly.
+Use LanguageVersionHandler#getParser
instead.TokenManager
(eg VfTokenManager
) are deprecated and should not be used outside of our implementation.
+This also affects CPD-only modules.These deprecations are added to the following language modules in this release. +Please look at the package documentation to find out the full list of deprecations.
+net.sourceforge.pmd.lang.apex.ast
net.sourceforge.pmd.lang.ecmascript.ast
net.sourceforge.pmd.lang.plsql.ast
net.sourceforge.pmd.lang.scala.ast
net.sourceforge.pmd.lang.vf.ast
These deprecations have already been rolled out in a previous version for the +following languages:
+net.sourceforge.pmd.lang.java.ast
net.sourceforge.pmd.lang.jsp.ast
net.sourceforge.pmd.lang.vm.ast
Outside of these packages, these changes also concern the following TokenManager +implementations, and their corresponding Parser if it exists (in the same package):
+ +CppTokenManager
JavaTokenManager
Ecmascript5TokenManager
JspTokenManager
MatlabTokenManager
ModelicaTokenManager
ObjectiveCTokenManager
PLSQLTokenManager
PythonTokenManager
VfTokenManager
VmTokenManager
In the Java AST the following attributes are deprecated and will issue a warning when used in XPath rules:
+ +ASTAdditiveExpression#getImage
- use getOperator()
insteadASTVariableDeclaratorId#getImage
- use getName()
insteadASTVariableDeclaratorId#getVariableName
- use getName()
insteadParser#getTokenManager
TokenManager#setFileName
AbstractTokenManager#setFileName
AbstractTokenManager#getFileName
AntlrToken#getType
- use getKind()
instead.ImmutableLanguage
MockRule
Node#getFirstParentOfAnyType
Node#getAsDocument
AbstractNode#hasDescendantOfAnyType
ASTRecordDeclaration#getComponentList
XPathRule
. See javadoc for details.The PMD team is pleased to announce PMD 6.22.0.
+ +This is a minor release.
+ +This release of PMD brings support for Java 14. PMD can parse Switch Expressions, +which have been promoted to be a standard language feature of Java.
+ +PMD also parses Text Blocks as String literals, which is still a preview +language feature in Java 14.
+ +The new Pattern Matching for instanceof can be used as well as +Records.
+ +Note: The Text Blocks, Pattern Matching for instanceof and Records are all preview language features of OpenJDK 14
+and are not enabled by default. In order to
+analyze a project with PMD that uses these language features, you’ll need to enable it via the environment
+variable PMD_JAVA_OPTS
and select the new language version 14-preview
:
export PMD_JAVA_OPTS=--enable-preview
+./run.sh pmd -language java -version 14-preview ...
+
Note: Support for the extended break statement introduced in Java 12 as a preview language feature +has been removed from PMD with this version. The version “12-preview” is no longer available.
+ +This PMD release ships a new version of the pmd-designer. +For the changes, see PMD Designer Changelog.
+ +In addition to suppressing violation with the @SuppressWarnings
annotation, Apex now also supports
+the suppressions with a NOPMD
comment. See Suppressing warnings.
The C# tokenizer is now based on an antlr grammar instead of a manual written tokenizer. This +should give more accurate results and especially fixes the problems with the using statement syntax +(see #2139).
+ +See the new documentation about Writing XPath Rules.
+ +Note: As of PMD version 6.22.0, XPath versions 1.0 and the 1.0 compatibility mode are deprecated. +XPath 2.0 is superior in many ways, for example for its support for type checking, sequence values, +or quantified expressions. For a detailed but approachable review of the features of XPath 2.0 and above, +see the Saxon documentation.
+ +The Rule CognitiveComplexity
(apex-design
) finds methods and classes
+that are highly complex and therefore difficult to read and more costly to maintain. In contrast
+to cyclomatic complexity, this rule uses “Cognitive Complexity”, which is a measure of how
+difficult it is for humans to read and understand a method.
The Rule TestMethodsMustBeInTestClasses
(apex-errorprone
) finds test methods
+that are not residing in a test class. The test methods should be moved to a proper test class.
+Support for tests inside functional classes was removed in Spring-13 (API Version 27.0), making classes
+that violate this rule fail compile-time. This rule is however useful when dealing with legacy code.
Those APIs are not intended to be used by clients, and will be hidden or removed with PMD 7.0.0.
+You can identify them with the @InternalApi
annotation. You’ll also get a deprecation warning.
JavaLanguageHandler
JavaLanguageParser
JavaDataFlowHandler
RuleViolationFactory
in each
+language module, eg JavaRuleViolationFactory
.
+See javadoc of RuleViolationFactory
.Implementations of RuleViolation
in each language module,
+eg JavaRuleViolation
. See javadoc of
+RuleViolation
.
RuleFactory
RuleBuilder
RuleSetFactory
, use factory methods from RulesetsFactoryUtils
insteadAbstractApexNode
AbstractApexNodeBase
, and the related visit
+methods on ApexParserVisitor
and its implementations.
+ Use ApexNode
instead, now considers comments too.DFAGraphRule
and its implementationsDFAGraphMethod
Node
interface
+and AbstractNode
base class. See their javadoc for details.Node#isFindBoundary
is deprecated for XPath queries.net.sourceforge.pmd.lang.metrics
, though most of them were internal and
+probably not used directly outside of PMD. Use MetricsUtil
as
+a replacement for the language-specific façades too.QualifiableNode
, QualifiedName
AbstractJavaParser
AbstractJavaHandler
ASTAnyTypeDeclaration.TypeKind
ASTAnyTypeDeclaration#getKind
JavaQualifiedName
ASTCatchStatement#getBlock
ASTCompilationUnit#declarationsAreInDefaultPackage
JavaQualifiableNode
+
+ net.sourceforge.pmd.lang.java.qname
and its contentsMethodLikeNode
+ ASTMethodOrConstructorDeclaration
,
+ASTLambdaExpression
.ASTAnyTypeDeclaration#getImage
will be removed. Please use getSimpleName()
+instead. This affects ASTAnnotationTypeDeclaration#getImage
,
+ASTClassOrInterfaceDeclaration#getImage
, and
+ASTEnumDeclaration#getImage
.ASTTryStatement
, replacements with other names
+have been added. This includes the XPath attribute @Finally
, replace it with a test for child::FinallyStatement
.getGuardExpressionNode
are replaced with getCondition
. This affects the
+following nodes: WhileStatement, DoStatement, ForStatement, IfStatement, AssertStatement, ConditionalExpression.ASTYieldStatement
will not implement TypeNode
+anymore come 7.0.0. Test the type of the expression nested within it.JavaMetrics
, JavaMetricsComputer
ASTArguments#getArgumentCount
.
+Use size
instead.ASTFormalParameters#getParameterCount
.
+Use size
instead.As part of the changes we’d like to do to AST classes for 7.0.0, we would like to +hide some methods and constructors that rule writers should not have access to. +The following usages are now deprecated in the JSP AST (with other languages to come):
+ +InternalApi
. Nodes should only be obtained from the parser,
+which for rules, means that they never need to instantiate node themselves.
+Those constructors will be made package private with 7.0.0.JspParser
is deprecated and should not be used directly.
+Use LanguageVersionHandler#getParser
instead.Please look at net.sourceforge.pmd.lang.jsp.ast
to find out the full list of deprecations.
As part of the changes we’d like to do to AST classes for 7.0.0, we would like to +hide some methods and constructors that rule writers should not have access to. +The following usages are now deprecated in the VM AST (with other languages to come):
+ +InternalApi
. Nodes should only be obtained from the parser,
+which for rules, means that they never need to instantiate node themselves.
+Those constructors will be made package private with 7.0.0.net.sourceforge.pmd.lang.vm.directive
as well as the classes
+DirectiveMapper
and LogUtil
are deprecated
+for removal. They were only used internally during parsing.VmParser
is deprecated and should not be used directly.
+Use LanguageVersionHandler#getParser
instead.Please look at net.sourceforge.pmd.lang.vm.ast
to find out the full list of deprecations.
The production and node ASTCursorBody
was unnecessary, not used and has been removed. Cursors have been already
+parsed as ASTCursorSpecification
.
The PMD team is pleased to announce PMD 6.21.0.
+ +This is a minor release.
+ +Thanks to Anatoly Trosinenko PMD supports now a new language: +Modelica is a language to model complex physical systems. +Both PMD and CPD are supported and there are already 3 rules available. +The PMD Designer supports syntax highlighting for Modelica.
+ +While the language implementation is quite complete, Modelica support is considered experimental +for now. This is to allow us to change the rule API (e.g. the AST classes) slightly and improve +the implementation based on your feedback.
+ +We added a experimental feature to dump the AST of a source file into XML. The XML format +is of course PMD specific and language dependent. That XML file can be used to execute +(XPath) queries against without PMD. It can also be used as a textual visualization of the AST +if you don’t want to use the Designer.
+ +This feature is experimental and might change or even be removed in the future, if it is not +useful. A short description how to use it is available under Creating XML dump of the AST.
+ +Any feedback about it, especially about your use cases, is highly appreciated.
+ +The CPD XML output format has been enhanced to also report column information for found duplications +in addition to the line information. This allows to display the exact tokens, that are considered +duplicate.
+ +If a CPD language doesn’t provide these exact information, then these additional attributes are omitted.
+ +Each <file>
element in the XML format now has 3 new attributes:
endline
column
(if there is column information available)endcolumn
(if there is column information available)The Java rule AvoidLiteralsInIfCondition
(java-errorprone
) has a new property
+ignoreExpressions
. This property is set by default to true
in order to maintain compatibility. If this
+property is set to false, then literals in more complex expressions are considered as well.
The Apex rule ApexCSRF
(apex-errorprone
) has been moved from category
+“Security” to “Error Prone”. The Apex runtime already prevents DML statements from being executed, but only
+at runtime. So, if you try to do this, you’ll get an error at runtime, hence this is error prone. See also
+the discussion on #2064.
The Java rule CommentRequired
(java-documentation
) has a new property
+classCommentRequirement
. This replaces the now deprecated property headerCommentRequirement
, since
+the name was misleading. (File) header comments are not checked, but class comments are.
Those APIs are not intended to be used by clients, and will be hidden or removed with PMD 7.0.0.
+You can identify them with the @InternalApi
annotation. You’ll also get a deprecation warning.
JavaLanguageHandler
JavaLanguageParser
JavaDataFlowHandler
RuleViolationFactory
in each
+language module, eg JavaRuleViolationFactory
.
+See javadoc of RuleViolationFactory
.Implementations of RuleViolation
in each language module,
+eg JavaRuleViolation
. See javadoc of
+RuleViolation
.
RuleFactory
RuleBuilder
RuleSetFactory
, use factory methods from RulesetsFactoryUtils
insteadAbstractApexNode
AbstractApexNodeBase
, and the related visit
+methods on ApexParserVisitor
and its implementations.
+ Use ApexNode
instead, now considers comments too.
CharStream
, JavaCharStream
,
+SimpleCharStream
: these are APIs used by our JavaCC
+implementations and that will be moved/refactored for PMD 7.0.0. They should not
+be used, extended or implemented directly.JJTJavaParserState
.
+This includes token classes, which will be replaced with a single implementation, and
+subclasses of ParseException
, whose usages will be replaced
+by just that superclass.Node
interface
+and AbstractNode
base class. See their javadoc for details.Node#isFindBoundary
is deprecated for XPath queries.AbstractJavaParser
AbstractJavaHandler
ASTAnyTypeDeclaration.TypeKind
ASTAnyTypeDeclaration#getKind
JavaQualifiedName
ASTCatchStatement#getBlock
ASTCompilationUnit#declarationsAreInDefaultPackage
JavaQualifiableNode
+
+ net.sourceforge.pmd.lang.java.qname
and its contentsMethodLikeNode
+ ASTMethodOrConstructorDeclaration
,
+ASTLambdaExpression
.ASTAnyTypeDeclaration#getImage
will be removed. Please use getSimpleName()
+instead. This affects ASTAnnotationTypeDeclaration#getImage
,
+ASTClassOrInterfaceDeclaration#getImage
, and
+ASTEnumDeclaration#getImage
.ASTTryStatement
, replacements with other names
+have been added. This includes the XPath attribute @Finally
, replace it with a test for child::FinallyStatement
.getGuardExpressionNode
are replaced with getCondition
. This affects the
+following nodes: WhileStatement, DoStatement, ForStatement, IfStatement, AssertStatement, ConditionalExpression.ASTYieldStatement
will not implement TypeNode
+anymore come 7.0.0. Test the type of the expression nested within it.The PMD team is pleased to announce PMD 6.20.0.
+ +This is a minor release.
+ +The PMD team is pleased to announce PMD 6.19.0.
+ +This is a minor release.
+ +This PMD release ships a new version of the pmd-designer. +For the changes, see PMD Designer Changelog.
+ +The Java rules InvalidLogMessageFormat
and MoreThanOneLogger
+(java-errorprone
) now both support Log4j2. Note that the
+rule “InvalidSlf4jMessageFormat” has been renamed to “InvalidLogMessageFormat” to reflect the fact, that it now
+supports more than slf4j.
The Java rule LawOfDemeter
(java-design
) ignores now also Builders, that are
+not assigned to a local variable, but just directly used within a method call chain. The method, that creates
+the builder needs to end with “Builder”, e.g. newBuilder()
or initBuilder()
works. This change
+fixes a couple of false positives.
The Java rule DataflowAnomalyAnalysis
(java-errorprone
) doesn’t check for
+UR anomalies (undefined and then referenced) anymore. These checks were all false-positives, since actual
+UR occurrences would lead to compile errors.
The java rule DoNotUseThreads
(java-multithreading
) has been changed
+to not report usages of java.lang.Runnable
anymore. Just using Runnable
does not automatically create
+a new thread. While the check for Runnable
has been removed, the rule now additionally checks for
+usages of Executors
and ExecutorService
. Both create new threads, which are not managed by a J2EE
+server.
InvalidSlf4jMessageFormat
has been renamed to
+InvalidLogMessageFormat
since it supports now both slf4j and log4j2
+message formats.-norulesetcompatibility
shows a boolean default valuenet.sourceforge.pmd.dcd
and its subpackages. See DCD
.LanguageRegistry
:
+
+ RuleSet#getExcludePatterns
. Use the new method getFileExclusions
instead.RuleSet#getIncludePatterns
. Use the new method getFileInclusions
instead.Parser#canParse
Parser#getSuppressMap
RuleBuilder#RuleBuilder
. Use the new constructor with the correct ResourceLoader instead.RuleFactory#RuleFactory
. Use the new constructor with the correct ResourceLoader instead.CanSuppressWarnings
and its implementationsisSuppressed
getDeclaringType
.isSupressed
ASTMethodDeclarator
getMethodName
getBlock
getParameterCount
CanSuppressWarnings
and its implementationsisSupressed
net.sourceforge.pmd.util
and its subpackages,
+except net.sourceforge.pmd.util.datasource
and net.sourceforge.pmd.util.database
.GridBagHelper
ColumnDescriptor
The PMD team is pleased to announce PMD 6.18.0.
+ +This is a minor release.
+ +This release of PMD brings support for Java 13. PMD can parse Switch Expressions
+with the new yield
statement and resolve the type of such an expression.
PMD also parses Text Blocks as String literals.
+ +Note: The Switch Expressions and Text Blocks are a preview language feature of OpenJDK 13
+and are not enabled by default. In order to
+analyze a project with PMD that uses these language features, you’ll need to enable it via the environment
+variable PMD_JAVA_OPTS
and select the new language version 13-preview
:
export PMD_JAVA_OPTS=--enable-preview
+./run.sh pmd -language java -version 13-preview ...
+
Note: Support for the extended break statement introduced in Java 12 as a preview language feature +will be removed with the next PMD version 6.19.0.
+ +Thanks to Chris Smith PMD now fully supports Scala. Now rules for analyzing Scala +code can be developed in addition to the Copy-Paste-Detection (CPD) functionality. There are no rules yet, so +contributions are welcome.
+ +Additionally Scala support has been upgraded from 2.12.4 to 2.13.
+ +The documentation for the rule designer is now available on the main PMD documentation page: +Rule Designer Reference. Check it out to learn +about the usage and features of the rule designer.
+ +The Java rule AvoidMessageDigestField
(java-bestpractices
) detects fields
+of the type java.security.MessageDigest
. Using a message digest instance as a field would need to be
+synchronized, as it can easily be used by multiple threads. Without synchronization the calculated hash could
+be entirely wrong. Instead of declaring this as a field and synchronize access to use it from multiple threads,
+a new instance should be created when needed. This rule is also active when using java’s quickstart ruleset.
The Apex rule DebugsShouldUseLoggingLevel
(apex-bestpractices
) detects
+usages of System.debug()
method calls that are used without specifying the log level. Having the log
+level specified provides a cleaner log, and improves readability of it.
CloseResource
(java-errorprone
) now ignores by default instances
+of java.util.stream.Stream
. These streams are AutoCloseable
, but most streams are backed by collections,
+arrays, or generating functions, which require no special resource management. However, there are some exceptions:
+The stream returned by Files::lines(Path)
is backed by a actual file and needs to be closed. These instances
+won’t be found by default by the rule anymore.Each renderer has now a new method Renderer#setUseShortNames
which
+is used for implementing the “shortnames” CLI option. The method is automatically called by PMD, if this
+CLI option is in use. When rendering filenames to the report, the new helper method
+AbstractRenderer#determineFileName
should be used. This will change
+the filename to a short name, if the CLI option “shortnames” is used.
Not adjusting custom renderers will make them render always the full file names and not honoring the +CLI option “shortnames”.
+getImportedNameNode
and
+getPackage
have been deprecated and
+will be removed with PMD 7.0.0.RuleContext#setSourceCodeFilename
has been deprecated
+and will be removed. The already existing method RuleContext#setSourceCodeFile
+should be used instead. The method RuleContext#getSourceCodeFilename
still
+exists and returns just the filename without the full path.AbstractPMDProcessor#filenameFrom
has been
+deprecated. It was used to determine a “short name” of the file being analyzed, so that the report
+can use short names. However, this logic has been moved to the renderers.Report#metrics
and Report
have
+been deprecated. They were leftovers from a previous deprecation round targeting
+StatisticalRule
.Those APIs are not intended to be used by clients, and will be hidden or removed with PMD 7.0.0. You can identify them with the @InternalApi
annotation. You’ll also get a deprecation warning.
net.sourceforge.pmd.lang.java.typeresolution
: Everything, including
+subpackages, except TypeHelper
and
+JavaTypeDefinition
.ASTCompilationUnit#getClassTypeResolver
The PMD team is pleased to announce PMD 6.17.0.
+ +This is a minor release.
+ +This PMD release ships a new version of the pmd-designer. +For the changes, see PMD Designer Changelog. +It contains a new feature to edit test cases directly within the designer. Any feedback is highly appreciated.
+ +Thanks to the contribution from Maikel Steneker, and built on top of the ongoing efforts to fully support Antlr-based languages, +PMD now has CPD support for Lua.
+ +Being based on a proper Antlr grammar, CPD can:
+The Java rule CloseResource
(java-errorprone
) ignores now by default
+java.io.ByteArrayInputStream
and java.io.CharArrayWriter
. Such streams/writers do not need to be closed.
The Java rule MissingStaticMethodInNonInstantiatableClass
(java-errorprone
) has now
+the new property annotations
.
+When one of the private constructors is annotated with one of the annotations, then the class is not considered
+non-instantiatable anymore and no violation will be reported. By default, Spring’s @Autowired
and
+Java EE’s @Inject
annotations are recognized.
The PMD team is pleased to announce PMD 6.16.0.
+ +This is a minor release.
+ +This PMD release ships a new version of the pmd-designer. +For the changes, see PMD Designer Changelog.
+ +The grammar has been updated to support inline constraints in CREATE TABLE statements. Additionally, the +CREATE TABLE statement may now be followed by physical properties and table properties. However, these +properties are skipped over during parsing.
+ +The CREATE VIEW statement now supports subquery views.
+ +The EXTRACT function can now be parsed correctly. It is used to extract values from a specified +datetime field. Also date time literals are parsed now correctly.
+ +The CASE expression can now be properly used within SELECT statements.
+ +Table aliases are now supported when specifying columns in INSERT INTO clauses.
+ +The Java rule DoubleBraceInitialization
(java-bestpractices
)
+detects non static initializers in anonymous classes also known as “double brace initialization”.
+This can be problematic, since a new class file is generated and object holds a strong reference
+to the surrounding class.
Note: This rule is also part of the Java quickstart ruleset (rulesets/java/quickstart.xml
).
The Java rule UnusedPrivateField
(java-bestpractices
) now ignores by
+default fields, that are annotated with the Lombok experimental annotation @Delegate
. This can be
+customized with the property ignoredAnnotations
.
The Java rule SingularField
(java-design
) now ignores by
+default fields, that are annotated with the Lombok experimental annotation @Delegate
. This can be
+customized with the property ignoredAnnotations
.
The Java rules UnsynchronizedStaticFormatter
and
+UnsynchronizedStaticDateFormatter
(java-multithreading
)
+now prefer synchronized blocks by default. They will raise a violation, if the synchronization is implemented
+on the method level. To allow the old behavior, the new property allowMethodLevelSynchronization
can
+be enabled.
The Java rule UseUtilityClass
(java-design
) has a new property ignoredAnnotations
.
+By default, classes that are annotated with Lombok’s @UtilityClass
are ignored now.
The Java rule NonStaticInitializer
(java-errorprone
) does not report
+non static initializers in anonymous classes anymore. For this use case, there is a new rule now:
+DoubleBraceInitialization
(java-bestpractices
).
The Java rule CommentDefaultAccessModifier
(java-codestyle
) was enhanced
+in the last version 6.15.0 to check also top-level types by default. This created many new violations.
+Missing the access modifier for top-level types is not so critical, since it only decreases the visibility
+of the type.
The default behaviour has been restored. If you want to enable the check for top-level types, you can
+use the new property checkTopLevelTypes
.
The Java rule CloseResource
(java-errorprone
) now by default searches
+for any unclosed java.lang.AutoCloseable
resource. This includes now the standard java.io.*Stream
classes.
+Previously only SQL-related resources were considered by this rule. The types can still be configured
+via the types
property. Some resources do not need to be closed (e.g. ByteArrayOutputStream
). These
+exceptions can be configured via the new property allowedResourceTypes
.
+In order to restore the old behaviour, just remove the type java.lang.AutoCloseable
from the types
+property and keep the remaining SQL-related classes.
AvoidFinalLocalVariable
(java-codestyle
) has been deprecated
+and will be removed with PMD 7.0.0. The rule is controversial and also contradicts other existing
+rules such as LocalVariableCouldBeFinal
. If the goal is to avoid defining
+constants in a scope smaller than the class, then the rule AvoidDuplicateLiterals
+should be used instead.++ +Reminder: Please don’t use members marked with the annotation
+InternalApi
, as they will likely be removed, hidden, or otherwise intentionally broken with 7.0.0.
As part of the changes we’d like to do to AST classes for 7.0.0, we would like to +hide some methods and constructors that rule writers should not have access to. +The following usages are now deprecated in the Java AST (with other languages to come):
+ +InternalApi
. Nodes should only be obtained from the parser, which for rules, means that never need to instantiate node themselves. Those constructors will be made package private with 7.0.0.Please look at net.sourceforge.pmd.lang.java.ast
to find out the full list
+of deprecations.
The PMD team is pleased to announce PMD 6.15.0.
+ +This is a minor release.
+ +Thanks to the contributions from Maikel Steneker CPD for Matlab can +now parse Matlab programs which use the question mark operator to specify access to +class members:
+ +classdef Class1
+properties (SetAccess = ?Class2)
+
CPD also understands now double quoted strings, which are supported since version R2017a of Matlab:
+ +str = "This is a string"
+
CPD now supports digit separators in C++ (language module “cpp”). This is a C++14 feature.
+ +Example: auto integer_literal = 1'000'000;
The single quotes can be used to add some structure to large numbers.
+ +CPD also parses raw string literals now correctly (see #1784).
+ +The new Apex rule FieldNamingConventions
(apex-codestyle
) checks the naming
+conventions for field declarations. By default this rule uses the standard Apex naming convention (Camel case),
+but it can be configured through properties.
The new Apex rule FormalParameterNamingConventions
(apex-codestyle
) checks the
+naming conventions for formal parameters of methods. By default this rule uses the standard Apex naming
+convention (Camel case), but it can be configured through properties.
The new Apex rule LocalVariableNamingConventions
(apex-codestyle
) checks the
+naming conventions for local variable declarations. By default this rule uses the standard Apex naming
+convention (Camel case), but it can be configured through properties.
The new Apex rule PropertyNamingConventions
(apex-codestyle
) checks the naming
+conventions for property declarations. By default this rule uses the standard Apex naming convention (Camel case),
+but it can be configured through properties.
The new Java rule UseShortArrayInitializer
(java-codestyle
) searches for
+array initialization expressions, which can be written shorter.
The Apex rule ClassNamingConventions
(apex-codestyle
) can now be configured
+using various properties for the specific kind of type declarations (e.g. class, interface, enum).
+As before, this rule uses by default the standard Apex naming convention (Pascal case).
The Apex rule MethodNamingConventions
(apex-codestyle
) can now be configured
+using various properties to differenciate e.g. static methods and test methods.
+As before, this rule uses by default the standard Apex naming convention (Camel case).
The Java rule FieldNamingConventions
(java-codestyle
) now by default ignores
+the field serialPersistentFields
. Since this is a field which needs to have this special name, no
+field naming conventions can be applied here. It is excluded the same way like serialVersionUID
via the
+property exclusions
.
The Java rule CommentRequired
(java-documentation
) has a new property
+serialPersistentFieldsCommentRequired
with the default value “Ignored”. This means that from now
+on comments for the field serialPersistentFields
are not required anymore. You can change the property
+to restore the old behavior.
The Java rule ProperLogger
(java-errorprone
) has two new properties
+to configure the logger class (e.g. “org.slf4j.Logger”) and the logger name of the special case,
+when the logger is not static. The name of the static logger variable was already configurable.
+The new property “loggerClass” allows to use this rule for different logging frameworks.
+This rule covers all the cases of the now deprecated rule LoggerIsNotStaticFinal
.
The Java rule CommentDefaultAccessModifier
(java-codestyle
) now reports also
+missing comments for top-level classes and annotations, that are package-private.
The Apex rule VariableNamingConventions
(apex-codestyle
) has been deprecated and
+will be removed with PMD 7.0.0. The rule is replaced by the more general rules
+FieldNamingConventions
,
+FormalParameterNamingConventions
,
+LocalVariableNamingConventions
, and
+PropertyNamingConventions
.
The Java rule LoggerIsNotStaticFinal
(java-errorprone
) has been deprecated
+and will be removed with PMD 7.0.0. The rule is replaced by ProperLogger
.
DumpFacades
in all languages, that could be used to transform a AST into a textual representation,
+will be removed with PMD 7. The rule designer is a better way to inspect nodes.
+ net.sourceforge.pmd.lang.apex.ast.DumpFacade
net.sourceforge.pmd.lang.java.ast.DumpFacade
net.sourceforge.pmd.lang.ecmascript.ast.DumpFacade
net.sourceforge.pmd.lang.jsp.ast.DumpFacade
net.sourceforge.pmd.lang.plsql.ast.DumpFacade
net.sourceforge.pmd.lang.vf.ast.DumpFacade
net.sourceforge.pmd.lang.vm.ast.AbstractVmNode#dump
net.sourceforge.pmd.lang.xml.ast.DumpFacade
LanguageVersionHandler#getDumpFacade
will be
+removed as well. It is deprecated, along with all its implementations in the subclasses of LanguageVersionHandler
.The PMD team is pleased to announce PMD 6.14.0.
+ +This is a minor release.
+ +Thanks to the contribution from Maikel Steneker, and built on top of the ongoing efforts to fully support Antlr-based languages, +PMD now has CPD support for Dart.
+ +Being based on a proper Antlr grammar, CPD can:
+This PMD release ships a new version of the pmd-designer. +For the changes, see PMD Designer Changelog.
+ +The Java rule AssignmentToNonFinalStatic
(java-errorprone
) will now report on each
+assignment made within a constructor rather than on the field declaration. This makes it easier for developers to
+find the offending statements.
The Java rule NoPackage
(java-codestyle
) will now report additionally enums
+and annotations that do not have a package declaration.
No changes.
+ +The PMD team is pleased to announce PMD 6.13.0.
+ +This is a minor release.
+ +We are still searching for a new logo for PMD for the next major release.
+ +Learn more about how to participate on github issue 1663.
+ +This release of PMD brings support for Java 12. PMD can parse the new Switch Expressions +and resolve the type of such an expression.
+ +Note: The Switch Expressions are a preview language feature of OpenJDK 12 and are not enabled by default. In order to
+analyze a project with PMD that uses these language features, you’ll need to enable it via the new environment
+variable PMD_JAVA_OPTS
:
export PMD_JAVA_OPTS=--enable-preview
+./run.sh pmd ...
+
PMD provides now a quickstart ruleset for Salesforce.com Apex, which you can use as a base ruleset to
+get your custom ruleset started. You can reference it with rulesets/apex/quickstart.xml
.
+You are strongly encouraged to create your own ruleset
+though.
The quickstart ruleset has the intention, to be useful out-of-the-box for many projects. Therefore it +references only rules, that are most likely to apply everywhere.
+ +Any feedback would be greatly appreciated.
+ +The rule designer’s codebase has been moved out of the main repository and +will be developed at pmd/pmd-designer +from now on. The maven coordinates will stay the same for the time being. +The designer will still be shipped with PMD’s binaries.
+ +Annotation[@Resolved = false()]
finds unsupported annotations.AnnotationParameter[@Name='RestResource'][@Value='/myurl']
gives access to
+annotation parameters.CatchBlockStatement[@ExceptionType='Exception'][@VariableName='e']
finds catch
+block for specific exception types.Field[@Type='String']
find all String fields, Field[string-length(@Name) < 5]
+finds all fields with short names and Field[@Value='a']
find alls fields, that are
+initialized with a specific value.LiteralExpression[@String = true()]
finds all String literals. There are attributes
+for each type: @Boolean
, @Integer
, @Double
, @Long
, @Decimal
, @Null
.Method[@Constructor = true()]
selects all constructors. Method[@ReturnType = 'String']
+selects all methods that return a String.ModifierNode
node has a couple of attributes to check for the existence of specific
+modifiers: @Test
, @TestOrTestSetup
, @WithSharing
, @WithoutSharing
, @InheritedSharing
,
+@WebService
, @Global
, @Override
.Parameter[@Type='Integer']
you can find all
+method parameters of type Integer. The same attribute Type
exists as well for:
+NewObjectExpression
, Property
, VariableDeclaration
.VariableExpression[@Image='i']
finds all variable usages of the variable “i”.The new Java rule AvoidUncheckedExceptionsInSignatures
(java-design
) finds methods or constructors
+that declare unchecked exceptions in their throws
clause. This forces the caller to handle the exception,
+even though it is a runtime exception.
The new Java rule DetachedTestCase
(java-errorprone
) searches for public
+methods in test classes, which are not annotated with @Test
. These methods might be test cases where
+the annotation has been forgotten. Because of that those test cases are never executed.
The new Java rule WhileLoopWithLiteralBoolean
(java-bestpractices
) finds
+Do-While-Loops and While-Loops that can be simplified since they use simply true
or false
as their
+loop condition.
The new Apex rule ApexAssertionsShouldIncludeMessage
(apex-bestpractices
)
+searches for assertions in unit tests and checks, whether they use a message argument.
The new Apex rule ApexUnitTestMethodShouldHaveIsTestAnnotation
(apex-bestpractices
)
+searches for methods in test classes, which are missing the @IsTest
annotation.
The new PLSQL rule AvoidTabCharacter
(plsql-codestyle
) checks, that there are
+no tab characters (“\t”) in the source file.
The new PLSQL rule LineLength
(plsql-codestyle
) helps to enforce a maximum
+line length.
The start scripts run.sh
, pmd.bat
and cpd.bat
support the new environment variable PMD_JAVA_OPTS
.
+This can be used to set arbitrary JVM options for running PMD, such as memory settings (e.g. PMD_JAVA_OPTS=-Xmx512m
)
+or enable preview language features (e.g. PMD_JAVA_OPTS=--enable-preview
).
The previously available variables such as OPTS
or HEAPSIZE
are deprecated and will be removed with PMD 7.0.0.
CodeClimateRule
is deprecated in 7.0.0 because it was unused for 2 years and
+created an unwanted dependency.
+Properties “cc_categories”, “cc_remediation_points_multiplier”, “cc_block_highlighting” will also be removed.
+See #1702 for more.
The Apex ruleset rulesets/apex/ruleset.xml
has been deprecated and will be removed in 7.0.0. Please use the new
+quickstart ruleset rulesets/apex/quickstart.xml
instead.
The PMD team is pleased to announce PMD 6.12.0.
+ +This is a minor release.
+ +PMD’s logo was great for a long time. But now we want to take the opportunity with the next major release to change +our logo in order to use a more “politically correct” one.
+ +Learn more about how to participate on github issue 1663.
+ +ITBA students Matías Fraga,
+Tomi De Lucca and Lucas Soncini
+keep working on bringing full Antlr support to PMD. For this release, they have implemented
+token filtering in an equivalent way as we did for JavaCC languages, adding support for CPD
+suppressions through CPD-OFF
and CPD-ON
comments for all Antlr-based languages.
This means, you can now ignore arbitrary blocks of code on:
+Simply start the suppression with any comment (single or multiline) containing CPD-OFF
,
+and resume again with a comment containing CPD-ON
.
More information is available in the user documentation.
+ +UseTryWithResources
(java-bestpractices
) searches
+for try-blocks, that could be changed to a try-with-resources statement. This statement ensures that
+each resource is closed at the end of the statement and is available since Java 7.MethodNamingConventions
(apex-codestyle
) has a new
+property skipTestMethodUnderscores
, which is by default disabled. The new property allows for ignoring
+all test methods, either using the testMethod
modifier or simply annotating them @isTest
.No changes.
+ +The PMD team is pleased to announce PMD 6.11.0.
+ +This is a minor release.
+ +//BooleanExpression[@Operator='&&']
.SELECT * FROM TABLE(expr)
).The new Java rule UnsynchronizedStaticFormatter
(java-multithreading
) detects
+unsynchronized usages of static java.text.Format
instances. This rule is a more generic replacement of the
+rule UnsynchronizedStaticDateFormatter
which focused just on DateFormat
.
The new Java rule ForLoopVariableCount
(java-bestpractices
) checks for
+the number of control variables in a for-loop. Having a lot of control variables makes it harder to understand
+what the loop does. The maximum allowed number of variables is by default 1 and can be configured by a
+property.
The new Java rule AvoidReassigningLoopVariables
(java-bestpractices
) searches
+for loop variables that are reassigned. Changing the loop variables additionally to the loop itself can lead to
+hard-to-find bugs.
The new Java rule UseDiamondOperator
(java-codestyle
) looks for constructor
+calls with explicit type parameters. Since Java 1.7, these type parameters are not necessary anymore, as they
+can be inferred now.
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.UnsynchronizedStaticDateFormatter
has been deprecated and
+will be removed with PMD 7.0.0. The rule is replaced by the more general
+UnsynchronizedStaticFormatter
.#1507: [plsql] Parse Exception when using ‘ | ++ | ’ operator in where clause | +
StatisticalRule
and the related helper classes and base rule classes
+are deprecated for removal in 7.0.0. This includes all of net.sourceforge.pmd.stat
and net.sourceforge.pmd.lang.rule.stat
,
+and also AbstractStatisticalJavaRule
, AbstractStatisticalApexRule
and the like.
+The methods Report#addMetric
and metricAdded
+will also be removed.setProperty
is deprecated,
+because MultiValuePropertyDescriptor
is deprecated as wellThe PMD team is pleased to announce PMD 6.10.0.
+ +This is a minor release.
+ +Thanks to Maikel Steneker, CPD now supports Kotlin. +This means, you can use CPD to find duplicated code in your Kotlin projects.
+ +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.The Java rule JUnitTestsShouldIncludeAssert
(java-bestpractices
)
+now also detects Soft Assertions.
The property exceptionfile
of the rule AvoidDuplicateLiterals
(java-errorprone
)
+has been deprecated and will be removed with 7.0.0. Please use exceptionList
instead.
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
+ +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
,
+is being replaced by the simpler PropertyBuilder
. Their APIs enjoy a high degree of source compatibility.
Concrete property classes like IntegerProperty
and StringMultiProperty
will gradually
+all be deprecated until 7.0.0. Their usages should be replaced by direct usage of the PropertyDescriptor
+interface, e.g. PropertyDescriptor<Integer>
or PropertyDescriptor<List<String>>
.
Instead of spreading properties across countless classes, the utility class PropertyFactory
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
is replaced by PropertyFactory#intProperty
+ IntegerMultiProperty
is replaced by PropertyFactory#intListProperty
FloatProperty
and DoubleProperty
are both replaced by PropertyFactory#doubleProperty
.
+Having a separate property for floats wasn’t that useful.
+ FloatMultiProperty
and DoubleMultiProperty
are replaced by PropertyFactory#doubleListProperty
.StringProperty
is replaced by PropertyFactory#stringProperty
+ StringMultiProperty
is replaced by PropertyFactory#stringListProperty
RegexProperty
is replaced by PropertyFactory#regexProperty
EnumeratedProperty
is replaced by PropertyFactory#enumProperty
+ EnumeratedProperty
is replaced by PropertyFactory#enumListProperty
BooleanProperty
is replaced by PropertyFactory#booleanProperty
+ BooleanMultiProperty
, is not replaced, because it doesn’t have a use case.CharacterProperty
is replaced by PropertyFactory#charProperty
+ CharacterMultiProperty
is replaced by PropertyFactory#charListProperty
LongProperty
is replaced by PropertyFactory#longIntProperty
+ LongMultiProperty
is replaced by PropertyFactory#longIntListProperty
MethodProperty
, FileProperty
, 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:
+// 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<Integer> 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.
+ +EnumeratedPropertyDescriptor
, NumericPropertyDescriptor
, PackagedPropertyDescriptor
,
+and the related builders (in net.sourceforge.pmd.properties.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 PropertyConstraint
s,
+which will allow virtually any constraint to be defined, and improve documentation and error reporting. The
+related methods PropertyTypeId#isPropertyNumeric
and
+PropertyTypeId#isPropertyPackaged
are also deprecated.
MultiValuePropertyDescriptor
and 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 PropertyDescriptor#isMultiValue
will be removed
+accordingly.
preferredRowCount
is deprecated with no intended replacement. It was never implemented, and does not belong
+in this interface. The methods 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<PropertyDescriptor>
anymore come 7.0.0.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<String>
with the shift to Java 8.The implementation of the adapters for the XPath engines Saxon and Jaxen (package net.sourceforge.pmd.lang.ast.xpath
)
+are now deprecated. They’ll be moved to an internal package come 7.0.0. Only Attribute
remains public API.
The classes PropertyDescriptorField
, PropertyDescriptorBuilderConversionWrapper
, and the methods
+PropertyDescriptor#attributeValuesById
, PropertyDescriptor#isDefinedExternally
and PropertyTypeId#getFactory
.
+These were used to read and write properties to and from XML, but were not intended as public API.
The class ValueParserConstants
and the interface ValueParser
.
All classes from net.sourceforge.pmd.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,
+JavaParserVisitorAdapter
should be directly subclassed.
LanguageVersionHandler#getDataFlowHandler()
, LanguageVersionHandler#getDFAGraphRule()
All classes from net.sourceforge.pmd.properties.modules
will be removed.
The interface 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).
Several methods from ASTLocalVariableDeclaration
and ASTFieldDeclaration
have
+also been deprecated:
ASTFieldDeclaration
won’t be a TypeNode
come 7.0.0, so
+getType
and
+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
>
+though, so you should iterate on each declared variable. See #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.
+ +net.sourceforge.pmd.lang.java.ast
: JavaParserDecoratedVisitor
, JavaParserControllessVisitor
,
+JavaParserControllessVisitorAdapter
, and 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:
+ +CppHandler
CppLanguageModule
CppParser
CsLanguageModule
FortranLanguageModule
GroovyLanguageModule
MatlabHandler
MatlabLanguageModule
MatlabParser
ObjectiveCHandler
ObjectiveCLanguageModule
ObjectiveCParser
PhpLanguageModule
PythonHandler
PythonLanguageModule
PythonParser
RubyLanguageModule
ScalaLanguageModule
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. Consequently, the following APIs are deprecated for +removal:
+Rule
: isDfa()
, isTypeResolution()
, isMultifile()
and their
+respective setters.RuleSet
: usesDFA(Language)
, usesTypeResolution(Language)
, usesMultifile(Language)
RuleSets
: usesDFA(Language)
, usesTypeResolution(Language)
, usesMultifile(Language)
LanguageVersionHandler
: getDataFlowFacade()
, getSymbolFacade()
, getSymbolFacade(ClassLoader)
,
+getTypeResolutionFacade(ClassLoader)
, getQualifiedNameResolutionFacade(ClassLoader)
The PMD team is pleased to announce PMD 6.9.0.
+ +This is a minor release.
+ +Thanks to the work of ITBA students Matías Fraga, +Tomi De Lucca and Lucas Soncini, +Golang is now backed by a proper Antlr Grammar. This means CPD is now better at detecting duplicates, +as comments are recognized as such and ignored.
+ +CodeFormat
(plsql-codestyle
) verifies that
+PLSQL code is properly formatted. It checks e.g. for correct indentation in select statements and verifies
+that each parameter is defined on a separate line.-ignorelist
. With that, you can provide a file containing a comma-delimit list of files,
+that should be excluded during analysis. The ignorelist is applied after the files have been selected
+via -dir
or -filelist
, which means, if the file is in both lists, then it will be ignored.
+Note: there is no corresponding option for the Ant task, since the feature is already available via
+Ant’s FileSet include/exclude filters.The PMD team is pleased to announce PMD 6.8.0.
+ +This is a minor release.
+ +Until now, all released public members and types were implicitly considered part +of PMD’s public API, including inheritance-specific members (protected members, abstract methods). +We have maintained those APIs with the goal to preserve full binary compatibility between minor releases, +only breaking those APIs infrequently, for major releases.
+ +In order to allow PMD to move forward at a faster pace, this implicit contract will +be invalidated with PMD 7.0.0. We now introduce more fine-grained distinctions between +the type of compatibility support we guarantee for our libraries, and ways to make +them explicit to clients of PMD.
+ +.internal
packages and @InternalApi
annotationInternal API is meant for use only by the main PMD codebase. Internal types and methods +may be modified in any way, or even removed, at any time.
+ +Any API in a package that contains an .internal
segment is considered internal.
+The @InternalApi
annotation will be used for APIs that have to live outside of
+these packages, e.g. methods of a public type that shouldn’t be used outside of PMD (again,
+these can be removed anytime).
@ReservedSubclassing
Types marked with the @ReservedSubclassing
annotation are only meant to be subclassed
+by classes within PMD. As such, we may add new abstract methods, or remove protected methods,
+at any time. All published public members remain supported. The annotation is not inherited, which
+means a reserved interface doesn’t prevent its implementors to be subclassed.
@Experimental
APIs marked with the @Experimental
annotation at the class or method level are subject to change.
+They can be modified in any way, or even removed, at any time. You should not use or rely
+ on them in any production code. They are purely to allow broad testing and feedback.
@Deprecated
APIs marked with the @Deprecated
annotation at the class or method level will remain supported
+until the next major release but it is recommended to stop using them.
All currently supported APIs will remain so until 7.0.0. All APIs that are to be moved to
+.internal
packages or hidden will be tagged @InternalApi
before that major release, and
+the breaking API changes will be performed in 7.0.0.
PMD 6.8.0 provides a first quickstart ruleset for Java, which you can use as a base ruleset to get your
+custom ruleset started. You can reference it with rulesets/java/quickstart.xml
.
+You are strongly encouraged to create your own ruleset
+though.
The quickstart ruleset has the intention, to be useful out-of-the-box for many projects. Therefore it +references only rules, that are most likely to apply everywhere.
+ +Any feedback would be greatly appreciated.
+ +ApexDoc
(apex-documentation
)
+enforces the inclusion of ApexDoc on classes, interfaces, properties and methods; as well as some
+sanity rules for such docs (no missing parameters, parameters’ order, and return value). By default,
+method overrides and test classes are allowed to not include ApexDoc.MissingSerialVersionUID
(java-errorprone
) has been modified
+in order to recognize also missing serialVersionUID
fields in abstract classes, if they are serializable.
+Each individual class in the inheritance chain needs an own serialVersionUID field. See also Should an abstract class have a serialVersionUID.
+This change might lead to additional violations in existing code bases.The grammar for PLSQL has been revamped in order to fully parse SELECT INTO
, UPDATE
, and DELETE
+statements. Previously such statements have been simply skipped ahead, now PMD is parsing them, giving access
+to the individual parts of a SELECT-statement, such as the Where-Clause. This might produce new parsing errors
+where PMD previously could successfully parse PLSQL code. If this happens, please report a new issue to get this problem fixed.
A couple of methods and fields in net.sourceforge.pmd.properties.AbstractPropertySource
have been
+deprecated, as they are replaced by already existing functionality or expose internal implementation
+details: propertyDescriptors
, propertyValuesByDescriptor
,
+copyPropertyDescriptors()
, copyPropertyValues()
, ignoredProperties()
, usesDefaultValues()
,
+useDefaultValueFor()
.
Some methods in net.sourceforge.pmd.properties.PropertySource
have been deprecated as well:
+usesDefaultValues()
, useDefaultValueFor()
, ignoredProperties()
.
The class net.sourceforge.pmd.lang.rule.AbstractDelegateRule
has been deprecated and will
+be removed with PMD 7.0.0. It is internally only in use by RuleReference.
The default constructor of net.sourceforge.pmd.lang.rule.RuleReference
has been deprecated
+and will be removed with PMD 7.0.0. RuleReferences should only be created by providing a Rule and
+a RuleSetReference. Furthermore the following methods are deprecated: setRuleReference()
,
+hasOverriddenProperty()
, usesDefaultValues()
, useDefaultValueFor()
.
The PMD team is pleased to announce PMD 6.7.0.
+ +This is a minor release.
+ +OneDeclarationPerLine
(java-bestpractices
) has been revamped to
+consider not only local variable declarations, but field declarations too.The new Java rule LinguisticNaming
(java-codestyle
)
+detects cases, when a method name indicates it returns a boolean (such as isSmall()
) but it doesn’t.
+Besides method names, the rule also checks field and variable names. It also checks, that getters return
+something but setters won’t. The rule has several properties with which it can be customized.
The new PL/SQL rule ForLoopNaming
(plsql-codestyle
)
+enforces a naming convention for “for loops”. Both “cursor for loops” and “index for loops” are covered.
+The rule can be customized via patterns. By default, short variable names are reported.
The new Java rule FieldNamingConventions
(java-codestyle
)
+detects field names that don’t comply to a given convention. It defaults to standard Java convention of using camelCase,
+but can be configured with ease for e.g. constants or static fields.
The new Apex rule OneDeclarationPerLine
(apex-codestyle
) enforces declaring a
+single field / variable per line; or per statement if the strictMode
property is set.
+It’s an Apex equivalent of the already existing Java rule of the same name.
VariableNamingConventions
, MIsLeadingVariableName
,
+SuspiciousConstantFieldName
, and AvoidPrefixingMethodParameters
are
+now deprecated, and will be removed with version 7.0.0. They are replaced by the more general
+FieldNamingConventions
, FormalParameterNamingConventions
, and
+LocalVariableNamingConventions
.All classes in the package net.sourceforge.pmd.lang.dfa.report
have been deprecated and will be removed
+with PMD 7.0.0. This includes the class net.sourceforge.pmd.lang.dfa.report.ReportTree
. The reason is,
+that this class is very specific to Java and not suitable for other languages. It has only been used for
+YAHTMLRenderer
, which has been rewritten to work without these classes.
The nodes RUNSIGNEDSHIFT and RSIGNEDSHIFT are deprecated and will be removed from the AST with PMD 7.0.0. +These represented the operator of ShiftExpression in two cases out of three, but they’re not needed and +make ShiftExpression inconsistent. The operator of a ShiftExpression is now accessible through +ShiftExpression#getOperator.
+The PMD team is pleased to announce PMD 6.6.0.
+ +This is a minor release.
+ +PMD is now able to parse the local-variable declaration syntax var xxx
, that has been
+extended for lambda parameters with Java 11 via
+JEP 323: Local-Variable Syntax for Lambda Parameters.
The new Java rule LocalVariableNamingConventions
+(java-codestyle
) detects local variable names that don’t comply to a given convention. It defaults to standard
+Java convention of using camelCase, but can be configured. Special cases can be configured for final variables
+and caught exceptions’ names.
The new Java rule FormalParameterNamingConventions
+(java-codestyle
) detects formal parameter names that don’t comply to a given convention. It defaults to
+standard Java convention of using camelCase, but can be configured. Special cases can be configured for final
+parameters and lambda parameters (considering whether they are explicitly typed or not).
AccessorClassGeneration
and
+AccessorMethodGeneration
(both in category
+java-bestpractices
) have been modified to be only valid up until Java 10. Java 11 adds support for
+JEP 181: Nest-Based Access Control which avoids the generation of
+accessor classes / methods altogether.findDescendantsOfType
methods in net.sourceforge.pmd.lang.ast.AbstractNode
no longer search for
+exact type matches, but will match subclasses, too. That means, it’s now possible to look for abstract node
+types such as AbstractJavaTypeNode
and not only for it’s concrete subtypes.The PMD team is pleased to announce PMD 6.5.0.
+ +This is a minor release.
+ +AvoidNonExistentAnnotations
(apex-errorprone
)
+detects usages non-officially supported annotations. Apex supported non existent annotations for legacy reasons.
+In the future, use of such non-existent annotations could result in broken Apex code that will not compile.
+A full list of supported annotations can be found herejava-codestyle
)
+now detects enum constrcutors with explicit private
modifier. The rule now produces better error messages
+letting you know exactly which modifiers are redundant at each declaration.The utility class net.sourceforge.pmd.lang.java.ast.CommentUtil
has been deprecated and will be removed
+with PMD 7.0.0. Its methods have been intended to parse javadoc tags. A more useful solution will be added
+around the AST node FormalComment
, which contains as children JavadocElement
nodes, which in
+turn provide access to the JavadocTag
.
All comment AST nodes (FormalComment
, MultiLineComment
, SingleLineComment
) have a new method
+getFilteredComment()
which provide access to the comment text without the leading /*
markers.
The method AbstractCommentRule.tagsIndicesIn()
has been deprecated and will be removed with
+PMD 7.0.0. It is not very useful, since it doesn’t extract the information
+in a useful way. You would still need check, which tags have been found, and with which
+data they might be accompanied.
The PMD team is pleased to announce PMD 6.4.0.
+ +This is a minor release.
+ +PMD is now able to understand local-variable type inference as introduced by Java 10.
+Simple type resolution features are available, e.g. the type of the variable s
is inferred
+correctly as String
:
var s = "Java 10";
+
For some time now PMD has supported Type Resolution, and exposed this functionality to XPath rules for the Java language
+with the typeof
function. This function however had a number of shortcomings:
@Image
+but was still required.In this release we are deprecating typeof
in favor of a simpler typeIs
function, which behaves exactly as the
+old typeof
when given all 3 arguments.
typeIs
receives a single parameter, which is the fully qualified name of the class to test against.
So, calls such as:
+ +//ClassOrInterfaceType[typeof(@Image, 'junit.framework.TestCase', 'TestCase')]
+
can now we expressed much more concisely as:
+ +//ClassOrInterfaceType[typeIs('junit.framework.TestCase')]
+
With this change, we also allow to check against array types by just appending []
to the fully qualified class name.
+These can be repeated for arrays of arrays (e.g. byte[][]
or java.lang.String[]
).
Additionally, we introduce the companion function typeIsExactly
, that receives the same parameters as typeIs
,
+but checks for exact type matches, without considering the type hierarchy. That is, the test
+typeIsExactly('junit.framework.TestCase')
will match only if the context node is an instance of TestCase
, but
+not if it’s an instance of a subclass of TestCase
. Be aware then, that using that method with abstract types will
+never match.
The new Java rule HardCodedCryptoKey
(java-security
)
+detects hard coded keys used for encryption. It is recommended to store keys outside of the source code.
The new Java rule IdenticalCatchBranches
(java-codestyle
)
+finds catch blocks,
+that catch different exception but perform the same exception handling and thus can be collapsed into a
+multi-catch try statement.
The Java rule JUnit4TestShouldUseTestAnnotation (java-bestpractices
)
+has a new parameter “testClassPattern”. It is used to distinguish test classes from other classes and
+avoid false positives. By default, any class, that has “Test” in its name, is considered a test class.
The Java rule CommentDefaultAccessModifier (java-codestyle
)
+allows now by default the comment “/* package */
in addition to “/* default */
. This behavior can
+still be adjusted by setting the property regex
.
net.sourceforge.pmd.benchmark
have been deprecated: Benchmark
, Benchmarker
,
+BenchmarkReport
, BenchmarkResult
, RuleDuration
, StringBuilderCR
and TextReport
. Their API is not supported anymore
+and is disconnected from the internals of PMD. Use the newer API based around TimeTracker
instead, which can be found
+in the same package.net.sourceforge.pmd.lang.java.xpath.TypeOfFunction
has been deprecated. Use the newer TypeIsFunction
in the same package.typeof
methdos in net.sourceforge.pmd.lang.java.xpath.JavaFunctions
have been deprecated.
+Use the newer typeIs
method in the same class instead..isA
, isEither
and isNeither
of net.sourceforge.pmd.lang.java.typeresolution.TypeHelper
.
+Use the new isExactlyAny
and isExactlyNone
methods in the same class instead.DoNotExtendJavaLangError
- Akshat BahetyThe PMD team is pleased to announce PMD 6.3.0.
+ +This is a minor release.
+ +As described in #904, when searching for child nodes of the AST methods
+such as hasDescendantOfType
, getFirstDescendantOfType
and findDescendantsOfType
were found to behave inconsistently,
+not all of them honoring find boundaries; that is, nodes that define a self-contained entity which should be considered separately
+(think of lambdas, nested classes, anonymous classes, etc.). We have modified these methods to ensure all of them honor
+find boundaries.
This change implies several false positives / unexpected results
+(ie: ASTBlockStatement
falsely returning true
to isAllocation()
)
+have been fixed; and lots of searches are now restricted to smaller search areas, which improves performance
+(depending on the project, we have measured up to 10% improvements during Type Resolution, Symbol Table analysis,
+and some rules’ application).
ClassNamingConventions (java-codestyle
)
+has been enhanced to allow granular configuration of naming
+conventions for different kinds of type declarations (eg enum or abstract
+class). Each kind of declaration can use its own naming convention
+using a regex property. See the rule’s documentation for more info about
+configuration and default conventions.
MethodNamingConventions (java-codestyle
)
+has been enhanced in the same way.
Back in PMD 5.6.0 we introduced the ability to suppress CPD warnings in Java using comments, by
+including CPD-OFF
(to start ignoring code), or CPD-ON
(to resume analysis) during CPD execution.
+This has proved to be much more flexible and versatile than the old annotation-based approach,
+and has since been the preferred way to suppress CPD warnings.
On this occasion, we are extending support for comment-based suppressions to many other languages:
+ +So for instance, in Python we could now do:
+ +class BaseHandler(object):
+ def __init__(self):
+ # some unignored code
+
+ # tell cpd to start ignoring code - CPD-OFF
+
+ # mission critical code, manually loop unroll
+ GoDoSomethingAwesome(x + x / 2);
+ GoDoSomethingAwesome(x + x / 2);
+ GoDoSomethingAwesome(x + x / 2);
+ GoDoSomethingAwesome(x + x / 2);
+ GoDoSomethingAwesome(x + x / 2);
+ GoDoSomethingAwesome(x + x / 2);
+
+ # resume CPD analysis - CPD-ON
+
+ # further code will *not* be ignored
+
Other languages are equivalent.
+ +Thanks to major contributions from kenji21 the Swift grammar has been updated to +support Swift 4.1. This is a major update, since the old grammar was quite dated, and we are sure all iOS +developers will enjoy it.
+ +Unfortunately, this change is not compatible. The grammar elements that have been removed (ie: the keywords __FILE__
,
+__LINE__
, __COLUMN__
and __FUNCTION__
) are no longer supported. We don’t usually introduce such
+drastic / breaking changes in minor releases, however, given that the whole Swift ecosystem pushes hard towards
+always using the latest versions, and that Swift needs all code and libraries to be currently compiling against
+the same Swift version, we felt strongly this change was both safe and necessary to be shipped as soon as possible.
+We had great feedback from the community during the process but if you have a legitimate use case for older Swift
+versions, please let us know on our Issue Tracker.
java-security
)
+detects hard coded initialization vectors used in cryptographic operations. It is recommended to use
+a randomly generated IV.The Java rule UnnecessaryConstructor (java-codestyle
)
+has been rewritten as a Java rule (previously it was a XPath-based rule). It supports a new property
+ignoredAnnotations
and ignores by default empty constructors,
+that are annotated with javax.inject.Inject
. Additionally, it detects now also unnecessary private constructors
+in enums.
The property checkNativeMethods
of the Java rule MethodNamingConventions (java-codestyle
)
+is now deprecated, as it is now superseded by nativePattern
. Support for that property will be maintained until
+7.0.0.
The Java rule ControlStatementBraces (java-codestyle
)
+supports a new boolean property checkSingleIfStmt
. When unset, the rule won’t report if
statements which lack
+braces, if the statement is not part of an if ... else if
chain. This property defaults to true.
java-codestyle
) is deprecated
+in favour of ClassNamingConventions.
+See Naming rules enhancements.The PMD team is pleased to announce PMD 6.2.0.
+ +This is a minor release.
+ +The Rhino Library has been upgraded from version 1.7.7 to version 1.7.7.2.
+ +Detailed changes for changed in Rhino can be found:
+Both are bugfixing releases.
+ +Some time ago, we added support for Incremental Analysis. On PMD 6.0.0, we +started to add warns when not using it, as we strongly believe it’s a great improvement to our user’s experience as +analysis time is greatly reduced; and in the future we plan to have it enabled by default. However, we realize some +scenarios don’t benefit from it (ie: CI jobs), and having the warning logged can be noisy and cause confusion.
+ +To this end, we have added a new flag to allow you to explicitly disable incremental analysis. On CLI, this is
+the new -no-cache
flag. On Ant, there is a noCache
attribute for the <pmd>
task.
On both scenarios, disabling the cache takes precedence over setting a cache location.
+ +The new Java rule MissingOverride
+(category bestpractices
) detects overridden and implemented methods, which are not marked with the
+@Override
annotation. Annotating overridden methods with @Override
ensures at compile time that
+the method really overrides one, which helps refactoring and clarifies intent.
The new Java rule UnnecessaryAnnotationValueElement
+(category codestyle
) detects annotations with a single element (value
) that explicitely names it.
+That is, doing @SuppressWarnings(value = "unchecked")
would be flagged in favor of
+@SuppressWarnings("unchecked")
.
The new Java rule ControlStatementBraces
+(category codestyle
) enforces the presence of braces on control statements where they are optional.
+Properties allow to customize which statements are required to have braces. This rule replaces the now
+deprecated rules WhileLoopMustUseBraces
, ForLoopMustUseBraces
, IfStmtMustUseBraces
, and
+IfElseStmtMustUseBraces
. More than covering the use cases of those rules, this rule also supports
+do ... while
statements and case
labels of switch
statements (disabled by default).
The Java rule CommentContentRule
(java-documentation
) previously had the property wordsAreRegex
. But this
+property never had been implemented and is removed now.
The Java rule UnusedPrivateField
(java-bestpractices
) now has a new ignoredAnnotations
property
+that allows to configure annotations that imply the field should be ignored. By default @java.lang.Deprecated
+and @javafx.fxml.FXML
are ignored.
The Java rule UnusedPrivateMethod
(java-bestpractices
) now has a new ignoredAnnotations
property
+that allows to configure annotations that imply the method should be ignored. By default @java.lang.Deprecated
+is ignored.
The Java rule ImmutableField
(java-design
) now has a new ignoredAnnotations
property
+that allows to configure annotations that imply the method should be ignored. By default several lombok
+annotations are ignored
The Java rule SingularField
(java-design
) now has a new ignoredAnnotations
property
+that allows to configure annotations that imply the method should be ignored. By default several lombok
+annotations are ignored
WhileLoopMustUseBraces
, ForLoopMustUseBraces
, IfStmtMustUseBraces
, and IfElseStmtMustUseBraces
+are deprecated. They will be replaced by the new rule ControlStatementBraces
, in the category codestyle
.A new CLI switch, -no-cache
, disables incremental analysis and the related suggestion. This overrides the
+ -cache
option. The corresponding Ant task parameter is noCache
.
The static method PMDParameters.transformParametersIntoConfiguration(PMDParameters)
is now deprecated,
+for removal in 7.0.0. The new instance method PMDParameters.toConfiguration()
replaces it.
The method ASTConstructorDeclaration.getParameters()
has been deprecated in favor of the new method
+getFormalParameters()
. This method is available for both ASTConstructorDeclaration
and
+ASTMethodDeclaration
.
The PMD team is pleased to announce PMD 6.1.0.
+ +This is a minor release.
+ +The Designer now supports configuring properties for XPath based rule development. +The Designer is still under development and any feedback is welcome.
+ +You can start the designer via run.sh designer
or designer.bat
.
The method getXPathNodeName
is added to the Node
interface, which removes the
+use of the toString
of a node to get its XPath element name (see #569).
+A default implementation is provided in AbstractNode
, to stay compatible
+with existing implementors.
The toString
method of a Node is not changed for the time being, and still produces
+the name of the XPath node. That behaviour may however change in future major releases,
+e.g. to produce a more useful message for debugging.
The interface net.sourceforge.pmd.cpd.Renderer
has been deprecated. A new interface net.sourceforge.pmd.cpd.renderer.CPDRenderer
+has been introduced to replace it. The main difference is that the new interface is meant to render directly to a java.io.Writer
+rather than to a String. This allows to greatly reduce the memory footprint of CPD, as on large projects, with many duplications,
+it was causing OutOfMemoryError
s (see #795).
net.sourceforge.pmd.cpd.FileReporter
has also been deprecated as part of this change, as it’s no longer needed.
The PMD team is pleased to announce PMD 6.0.1.
+ +This is a bug fixing release.
+ +With the release of PMD 6.0.0, all rules have been sorted into one of the following eight categories:
+ +Please note, that not every category in every language may have a rule. There might be categories with no
+rules at all, such as category/java/security.xml
, which has currently no rules.
+There are even languages, which only have rules of one category (e.g. category/xml/errorprone.xml
).
You can find the information about available rules in the generated rule documentation, available +at https://pmd.github.io/6.0.1/.
+ +In order to help migrate to the new category scheme, the new name for the old, deprecated rule names will +be logged as a warning. See PR #865. Please note, that the deprecated +rule names will keep working throughout PMD 6. You can upgrade to PMD 6 without the immediate need +to migrate your current ruleset. That backwards compatibility will be maintained until PMD 7.0.0 is released.
+ +net.sourceforge.pmd.PMD.VERSION
has been deprecated and will be removed with PMD 7.0.0.
+Please use net.sourceforge.pmd.PMDVersion.VERSION
instead.The PMD team is pleased to announce PMD 6.0.0.
+ +This is a major release.
+ +Thanks to Clément Fournier, we now have a new rule designer GUI, which +is based on JavaFX. It replaces the old designer and can be started via
+ +bin/run.sh designer
(on Unix-like platform such as Linux and Mac OS X)bin\designer.bat
(on Windows)Note: At least Java8 is required for the designer. The old designer is still available
+as designerold
but will be removed with the next major release.
The Java grammar has been updated to support analyzing Java 9 projects:
+ +module-info.java
can be parsedJava 9 support is enabled by default. You can switch back to an older java version
+via the command line, e.g. -language java -version 1.8
.
We are now using the Apex Jorje Lexer to tokenize Apex code for CPD. This change means:
+ +CPD will therefore have less false positives and false negatives.
+ +As part of Google Summer of Code 2017, Bendegúz Nagy worked on type resolution +for Java. For this release he has extended support for method calls for both instance and static methods.
+ +Method shadowing and overloading are supported, as are varargs. However, the selection of the target method upon +the presence of generics and type inference is still work in progress. Expect it in forecoming releases.
+ +As for fields, the basic support was in place for release 5.8.0, but has now been expanded to support static fields.
+ +As part of Google Summer of Code 2017, Clément Fournier is worked +on the new metrics framework for object-oriented metrics.
+ +There are already a couple of metrics (e.g. ATFD, WMC, Cyclo, LoC) implemented. More metrics are planned. +Based on those metrics, rules like “GodClass” detection could be implemented more easily. +The following rules benefit from the metrics framework: NcssCount (java), NPathComplexity (java), +CyclomaticComplexity (both java and apex).
+ +The Metrics framework has been abstracted and is available in pmd-core
for other languages. With this
+PMD release, the metrics framework is supported for both Java and Apex.
A number of improvements on error reporting have taken place, meaning changes to some of the report formats.
+ +Also of note, the xml report now provides a XML Schema definition, allowing easier parsing and validation.
+ +Processing errors can now provide not only the message previously included on some reports, but also a full stacktrace. +This will allow better error reports when providing feedback to the PMD team and help in debugging issues.
+ +The report formats providing full stacktrace of errors are:
+ +For a long time reports have been notified of configuration errors on rules, but they have remained hidden. +On a push to make these more evident to users, and help them get the best results out of PMD, we have started +to include them on the reports.
+ +So far, only reports that include processing errors are showing configuration errors. In other words, the report formats +providing configuration error reporting are:
+ +As we move forward we will be able to detect and report more configuration errors (ie: incomplete auxclasspath
)
+and include them to such reports.
Apex violations can now be suppressed very similarly to how it’s done in Java, by making use of a
+@SuppressWarnings
annotation.
Supported syntax includes:
+ +@SupressWarnings('PMD') // to supress all Apex rules
+@SupressWarnings('all') // to supress all Apex rules
+@SupressWarnings('PMD.ARuleName') // to supress only the rule named ARuleName
+@SupressWarnings('PMD.ARuleName, PMD.AnotherRuleName') // to supress only the rule named ARuleName or AnotherRuleName
+
Notice this last scenario is slightly different to the Java syntax. This is due to differences in the Apex grammar for annotations.
+ +All built-in rules have been sorted into one of eight categories:
+ +These categories help you to find rules and figure out the relevance and impact for your project.
+ +All rules have been moved accordingly, e.g. the rule “JumbledIncrementer”, which was previously defined in the
+ruleset “java-basic” has now been moved to the “Error Prone” category. The new rule reference to be used is
+<rule ref="category/java/errorprone.xml/JumbledIncrementer"/>
.
The old rulesets like “java-basic” are still kept for backwards-compatibility but will be removed eventually. +The rule reference documentation has been updated to reflect these changes.
+ +The new Java rule NcssCount
(category design
) replaces the three rules “NcssConstructorCount”, “NcssMethodCount”,
+and “NcssTypeCount”. The new rule uses the metrics framework to achieve the same. It has two properties, to
+define the report level for method and class sizes separately. Constructors and methods are considered the same.
The new Java rule DoNotExtendJavaLangThrowable
(category errorprone
) is a companion for the
+java-strictexception.xml/DoNotExtendJavaLangError
, detecting direct extensions of java.lang.Throwable
.
The new Java rule ForLoopCanBeForeach
(category errorprone
) helps to identify those for-loops that can
+be safely refactored into for-each-loops available since java 1.5.
The new Java rule AvoidFileStream
(category performance
) helps to identify code relying on FileInputStream
/ FileOutputStream
+which, by using a finalizer, produces extra / unnecessary overhead to garbage collection, and should be replaced with
+Files.newInputStream
/ Files.newOutputStream
available since java 1.7.
The new Java rule DataClass
(category design
) detects simple data-holders without behaviour. This might indicate
+that the behaviour is scattered elsewhere and the data class exposes the internal data structure,
+which breaks encapsulation.
The new Apex rule AvoidDirectAccessTriggerMap
(category errorprone
) helps to identify direct array access to triggers,
+which can produce bugs by either accessing non-existing indexes, or leaving them out. You should use for-each-loops
+instead.
The new Apex rule AvoidHardcodingId
(category errorprone
) detects hardcoded strings that look like identifiers
+and flags them. Record IDs change between environments, meaning hardcoded ids are bound to fail under a different
+setup.
The new Apex rule CyclomaticComplexity
(category design
) detects overly complex classes and methods. The
+report threshold can be configured separately for classes and methods.
errorprone
.
+The 5 rules are migrated for Apex from the equivalent Java rules and include:
+ EmptyCatchBlock
to detect catch blocks completely ignoring exceptions.EmptyIfStmt
for if blocks with no content, that can be safely removed.EmptyTryOrFinallyBlock
for empty try / finally blocks that can be safely removed.EmptyWhileStmt
for empty while loops that can be safely removed.EmptyStatementBlock
for empty code blocks that can be safely removed.AvoidSoslInLoops
(category performance
) is the companion of the old
+AvoidSoqlInLoops
rule, flagging SOSL (Salesforce Object Search Language) queries when within
+loops, to avoid governor issues, and hitting the database too often.The Java rule UnnecessaryFinalModifier
(category codestyle
, former ruleset java-unnecessarycode
)
+has been merged into the rule UnnecessaryModifier
. As part of this, the rule has been revamped to detect more cases.
+It will now flag anonymous class’ methods marked as final (can’t be overridden, so it’s pointless), along with
+final methods overridden / defined within enum instances. It will also flag final
modifiers on try-with-resources.
The Java rule UnnecessaryParentheses
(category codestyle
, former ruleset java-controversial
)
+has been merged into UselessParentheses
(category codestyle
, former ruleset java-unnecessary
).
+The rule covers all scenarios previously covered by either rule.
The Java rule UncommentedEmptyConstructor
(category documentation
, former ruleset java-design
)
+ will now ignore empty constructors annotated with javax.inject.Inject
.
The Java rule AbstractClassWithoutAnyMethod
(category bestpractices
, former ruleset java-design
)
+will now ignore classes annotated with com.google.auto.value.AutoValue
.
The Java rule GodClass
(category design', former ruleset
java-design`) has been revamped to use
+the new metrics framework.
The Java rule LooseCoupling
(category bestpractices
, former ruleset java-coupling
) has been
+replaced by the typeresolution-based implementation.
The Java rule CloneMethodMustImplementCloneable
(category errorprone
, former ruleset java-clone
)
+has been replaced by the typeresolution-based
+implementation and is now able to detect cases if a class implements or extends a Cloneable class/interface.
The Java rule UnusedImports
(category bestpractices
, former ruleset java-imports
) has been
+replaced by the typeresolution-based
+implementation and is now able to detect unused on-demand imports.
The Java rule SignatureDeclareThrowsException
(category design
, former ruleset ‘java-strictexception’)
+has been replaced by the
+typeresolution-based implementation. It has a new property IgnoreJUnitCompletely
, which allows all
+methods in a JUnit testcase to throw exceptions.
The Java rule NPathComplexity
(category design
, former ruleset java-codesize
) has been revamped
+to use the new metrics framework.
+Its report threshold can be configured via the property reportLevel
, which replaces the now
+deprecated property minimum
.
The Java rule CyclomaticComplexity
(category design
, former ruleset java-codesize
) has been
+revamped to use the new metrics framework.
+Its report threshold can be configured via the properties classReportLevel
and methodReportLevel
separately.
+The old property reportLevel
, which configured the level for both total class and method complexity,
+is deprecated.
CommentRequired
(category documentation
, former ruleset java-comments
)
+has been revamped to include 2 new properties:
+ accessorCommentRequirement
to specify documentation requirements for getters and setters (default to ignored
)methodWithOverrideCommentRequirement
to specify documentation requirements for methods annotated with @Override
(default to ignored
)The Java rule EmptyCatchBlock
(category errorprone
, former ruleset java-empty
) has been changed to ignore
+exceptions named ignore
or expected
by default. You can still override this behaviour by setting the allowExceptionNameRegex
property.
OptimizableToArrayCall
(category performance
, former ruleset design
) has been
+modified to fit for the current JVM implementations: It basically detects now the opposite and suggests to
+use Collection.toArray(new E[0])
with a zero-sized array.
+See Arrays of Wisdom of the Ancients.The Java rules NcssConstructorCount
, NcssMethodCount
, and NcssTypeCount
(ruleset java-codesize
) have been
+deprecated. They will be replaced by the new rule NcssCount
in the category design
.
The Java rule LooseCoupling
in ruleset java-typeresolution
is deprecated. Use the rule with the same name
+from category bestpractices
instead.
The Java rule CloneMethodMustImplementCloneable
in ruleset java-typeresolution
is deprecated. Use the rule with
+the same name from category errorprone
instead.
The Java rule UnusedImports
in ruleset java-typeresolution
is deprecated. Use the rule with
+the same name from category bestpractices
instead.
The Java rule SignatureDeclareThrowsException
in ruleset java-typeresolution
is deprecated. Use the rule
+with the same name from category design
instead.
The Java rule EmptyStaticInitializer
in ruleset java-empty
is deprecated. Use the rule EmptyInitializer
+from the category errorprone
, which covers both static and non-static empty initializers.`
The Java rules GuardDebugLogging
(ruleset java-logging-jakarta-commons
) and GuardLogStatementJavaUtil
+(ruleset java-logging-java
) have been deprecated. Use the rule GuardLogStatement
from the
+category bestpractices
, which covers all cases regardless of the logging framework.
UseSingleton
has been removed from the ruleset java-design
. The rule has been renamed
+long time ago to UseUtilityClass
(category design
).A bug in symbol table prevented
+the symbol table analysis to properly match primitive arrays types. The issue affected the java-unsedcode/UnusedPrivateMethod
+rule, but other rules may now produce improved results as consequence of this fix.
The Apex parser version was bumped, from 1.0-sfdc-187
to 210-SNAPSHOT
. This update let us take full advantage
+of the latest improvements from Salesforce, but introduces some breaking changes:
BlockStatements
are now created for all control structures, even if no brace is used. We have therefore added
+a hasCurlyBrace
method to differentiate between both scenarios.CastExpression
, ConstructorPreamble
, IllegalStoreExpression
,
+MethodBlockStatement
, Modifier
, MultiStatement
, NestedExpression
, NestedStoreExpression
,
+NewKeyValueObjectExpression
and StatementExecuted
TestNode
, DottedExpression
and NewNameValueObjectExpression
+(replaced by NewKeyValueObjectExpression
)All existing rules have been updated to reflect these changes. If you have custom rules, be sure to update them.
+ +For more info about the included Apex parser, see the new pmd module “pmd-apex-jorje”, which packages and provides +the parser as a binary.
+ +The incremental analysis feature first introduced in PMD 5.6.0 has been enhanced. A few minor issues have been fixed, +and several improvements have been performed to make it more accurate.
+ +The cache will now detect changes to the JARs referenced in the auxclasspath
instead of simply looking at their paths
+and order. This means that if you are referencing a JAR you are overwriting in some way, the incremental analysis can
+now detect it and invalidate it’s cache to avoid false reports.
Similarly, any changes to the execution classpath of PMD will invalidate the cache. This means that if you have custom +rules packaged in a jar, any changes to it will invalidate the cache automatically.
+ +We have also improved logging on the analysis code, allowing better insight into how the cache is performing, +under debug / verbose builds you can even see individual hits / misses to the cache (and the reason for any miss!)
+ +Finally, as this feature keeps maturing, we are gently pushing this forward. If not using incremental analysis, +a warning will now be produced suggesting users to adopt it for better performance.
+ +The implementation around the properties support for rule properties and report properties has been revamped
+to be fully typesafe. Along with that change, the support classes have been moved into an own
+package net.sourceforge.pmd.properties
. While there is no change necessary in the ruleset XML files,
+when using/setting values for rules, there are adjustments necessary when declaring properties in Java-implemented
+rules.
Rule properties can be declared both for Java based rules and XPath rules. +This is now very well documented in Working with properties.
+ +With PMD 6.0.0, multivalued properties are now also possible with XPath rules.
+ +The class net.sourceforge.pmd.lang.dfa.NodeType
has been converted to an enum.
+All node types are enum members now instead of int constants. The names for node types are retained.
The Properties API (rule and report properties) has been revamped to be fully typesafe. This is everything
+around net.sourceforge.pmd.properties.PropertyDescriptor
.
Note: All classes related to properties have been moved into the package net.sourceforge.pmd.properties
.
The rule classes net.sourceforge.pmd.lang.apex.rule.apexunit.ApexUnitTestClassShouldHaveAsserts
+and net.sourceforge.pmd.lang.apex.rule.apexunit.ApexUnitTestShouldNotUseSeeAllDataTrue
have been
+renamed to ApexUnitTestClassShouldHaveAssertsRule
and ApexUnitTestShouldNotUseSeeAllDataTrueRule
,
+respectively. This is to comply with the naming convention, that each rule class should be suffixed with “Rule”.
This change has no impact on custom rulesets, since the rule names themselves didn’t change.
+The never implemented method PMD.processFiles(PMDConfiguration, RuleSetFactory, Collection<File>, RuleContext, ProgressMonitor)
along with the interface ProgressMonitor
has been removed.
The method PMD.setupReport(RuleSets, RuleContext, String)
is gone. It was used to report dysfunctional
+rules. But PMD does this now automatically before processing the files, so there is no need for this
+method anymore.
Renderer.getPropertyDefinitions
AbstractRenderer.defineProperty(String, String)
AbstractRenderer.propertyDefinitions
ReportListener
Report.addListener(ReportListener)
SynchronizedReportListener
CPDConfiguration.CPDConfiguration(int, Language, String)
CPDConfiguration.getRendererFromString(String)
StreamUtil
StringUtil.appendXmlEscaped(StringBuilder, String)
StringUtil.htmlEncode(String)
net.sourceforge.pmd.util.CollectionUtil
have been deprecated and will be removed in PMD 7.0.0. In particular:
+ CollectionUtil.addWithoutDuplicates(T[], T)
CollectionUtil.addWithoutDuplicates(T[], T[])
CollectionUtil.areSemanticEquals(T[], T[])
CollectionUtil.areEqual(Object, Object)
CollectionUtil.arraysAreEqual(Object, Object)
CollectionUtil.valuesAreTransitivelyEqual(Object[], Object[])
net.sourceforge.pmd.util.StringUtil
have been deprecated and will be removed in PMD 7.0.0. In particular:
+ StringUtil.startsWithAny(String, String[])
StringUtil.isNotEmpty(String)
StringUtil.isEmpty(String)
StringUtil.isMissing(String)
StringUtil.areSemanticEquals(String, String)
StringUtil.replaceString(String, String, String)
StringUtil.replaceString(String, char, String)
StringUtil.substringsOf(String, char)
StringUtil.substringsOf(String, String)
StringUtil.asStringOn(StringBuffer, Iterator, String)
StringUtil.asStringOn(StringBuilder, Object[], String)
StringUtil.lpad(String, int)
The class net.sourceforge.pmd.lang.java.typeresolution.typedefinition.JavaTypeDefinition
is now abstract, and has been enhanced
+to provide several new methods.
The constructor of net.sourceforge.pmd.RuleSetFactory
, which took a ClassLoader
is deprecated.
+Please use the alternative constructor with the net.sourceforge.pmd.util.ResourceLoader
instead.
bgastviewer.bat
or run.sh bgastviewer
is
+deprecated, too, and will be removed in PMD 7.0.0.
+Both the “old designer” and “bgastviewer” are replaced by the New Rule Designer.
+ net.sourceforge.pmd.util.designer.CodeEditorTextPane
net.sourceforge.pmd.util.designer.CreateXMLRulePanel
net.sourceforge.pmd.util.designer.Designer
net.sourceforge.pmd.util.designer.DFAPanel
net.sourceforge.pmd.util.designer.LineGetter
net.sourceforge.pmd.util.viewer.Viewer
net.sourceforge.pmd.util.viewer.gui.ActionCommands
net.sourceforge.pmd.util.viewer.gui.ASTPanel
net.sourceforge.pmd.util.viewer.gui.EvaluationResultsPanel
net.sourceforge.pmd.util.viewer.gui.MainFrame
net.sourceforge.pmd.util.viewer.gui.ParseExceptionHandler
net.sourceforge.pmd.util.viewer.gui.SourceCodePanel
net.sourceforge.pmd.util.viewer.gui.XPathPanel
net.sourceforge.pmd.util.viewer.gui.menu.ASTNodePopupMenu
net.sourceforge.pmd.util.viewer.gui.menu.AttributesSubMenu
net.sourceforge.pmd.util.viewer.gui.menu.SimpleNodeSubMenu
net.sourceforge.pmd.util.viewer.gui.menu.XPathFragmentAddingItem
net.sourceforge.pmd.util.viewer.model.ASTModel
net.sourceforge.pmd.util.viewer.model.AttributeToolkit
net.sourceforge.pmd.util.viewer.model.SimpleNodeTreeNodeAdapter
net.sourceforge.pmd.util.viewer.model.ViewerModel
net.sourceforge.pmd.util.viewer.model.ViewerModelEvent
net.sourceforge.pmd.util.viewer.model.ViewerModelListener
net.sourceforge.pmd.util.viewer.util.NLS
net.sourceforge.pmd.Rule
have been deprecated and will be removed in PMD 7.0.0.
+All methods are replaced by their bean-like counterparts
+ void setUsesDFA()
. Use void setDfa(boolean)
instead.boolean usesDFA()
. Use boolean isDfa()
instead.void setUsesTypeResolution()
. Use void setTypeResolution(boolean)
instead.boolean usesTypeResolution()
. Use boolean isTypeResolution()
instead.void setUsesMultifile()
. Use void setMultifile(boolean)
instead.boolean usesMultifile()
. Use boolean isMultifile()
instead.boolean usesRuleChain()
. Use boolean isRuleChain()
instead.The PMD team is pleased to announce PMD 5.8.1.
+ +This is a bug fixing release.
+ +getGenericArgs()
method introduced to TypeNode
in 5.8.0 was removed. You can access to generics’ info through the JavaTypeDefinition
object.JavaTypeDefinitionBuilder
class introduced in 5.8.0 is not more. You can use factory methods available on JavaTypeDefinition
The PMD team is pleased to announce PMD 5.8.0.
+ +This is a minor release.
+ +As part of Google Summer of Code 2017, Bendegúz Nagy has been working on completing type resolution for Java. +His progress so far has allowed to properly resolve, in addition to previously supported statements:
+ +this
and super
, even when qualifiedthis.myObject.aField
), and properly handling inheritance / shadowingLambda parameter types where these are infered rather than explicit are still not supported. Expect future releases to do so.
+ +As part of Google Summer of Code 2017, Clément Fournier has been working on +a new metrics framework for object-oriented metrics.
+ +The basic groundwork has been done already and with this release, including a first rule based on the +metrics framework as a proof-of-concept: The rule CyclomaticComplexity, currently in the temporary +ruleset java-metrics, uses the Cyclomatic Complexity metric to find overly complex code. +This rule will eventually replace the existing three CyclomaticComplexity rules that are currently +defined in the java-codesize ruleset (see also issue #445).
+ +Since this work is still in progress, the metrics API (package net.sourceforge.pmd.lang.java.oom
)
+is not finalized yet and is expected to change.
The Java rule UnnecessaryFinalModifier
(ruleset java-unnecessary) now also reports on private methods marked as final
.
+Being private, such methods can’t be overriden, and therefore, the final keyword is redundant.
The Java rule PreserveStackTrace
(ruleset java-design) has been relaxed to support the builder pattern on thrown exception.
+This change may introduce some false positives if using the exception in non-orthodox ways for things other than setting the
+root cause of the exception. Contact us if you find any such scenarios.
The ruleset java-junit now properly detects JUnit5, and rules are being adapted to the changes on it’s API. +This support is, however, still incomplete. Let us know of any uses we are still missing on the issue tracker
+The Java rule EmptyTryBlock
(ruleset java-empty) now allows empty blocks when using try-with-resources.
The Java rule EmptyCatchBlock
(ruleset java-empty) now exposes a new property called allowExceptionNameRegex
.
+This allow to setup a regular expression for names of exceptions you wish to ignore for this rule. For instance,
+setting it to ^(ignored|expected)$
would ignore all empty catch blocks where the catched exception is named
+either ignored
or expected
. The default ignores no exceptions, being backwards compatible.
CyclomaticComplexity
, StdCyclomaticComplexity
, ModifiedCyclomaticComplexity
(ruleset java-codesize) have been deprecated. They will be eventually replaced
+by a new CyclomaticComplexity rule based on the metrics framework. See also issue #445.The PMD team is pleased to announce PMD 5.7.0.
+ +This is a minor release.
+ +The rule “FieldDeclarationsShouldBeAtStartOfClass” of the java-design ruleset has a new property ignoreInterfaceDeclarations
.
+Setting this property to true
ignores interface declarations, that precede fields.
+Example usage:
net.sourceforge.pmd.util.StringUtil#htmlEncode(String)
is deprecated.
+org.apache.commons.lang3.StringEscapeUtils#escapeHtml4(String)
should be used instead.The PMD team is pleased to announce PMD 5.6.1.
+ +This is a bug fixing release.
+ +The PMD team is pleased to announce PMD 5.6.0.
+ +The most significant changes are on analysis performance, support for Salesforce’s Visualforce language +a whole new Apex Security Rule Set and the new Braces Rule Set for Apex.
+ +We have added initial support for incremental analysis. The experimental feature allows +PMD to cache analysis results between executions to speed up the analysis for all +languages. New CLI flags and Ant options are available to configure it. Currently +the feature is disabled by default, but this may change as it matures.
+ +Multithread performance has been enhanced by reducing thread-contention on a +bunch of areas. This is still an area of work, as the speedup of running +multithreaded analysis is still relatively small (4 threads produce less +than a 50% speedup). Future releases will keep improving on this area.
+ +Once again, Symbol Table has been an area of great performance improvements. +This time we were able to further improve it’s performance by roughly 10% on all +supported languages. In Java in particular, several more improvements were possible, +improving Symbol Table performance by a whooping 80%, that’s over 15X faster +than PMD 5.5.1, when we first started working on it.
+ +Java developers will also appreciate the revamp of CloneMethodMustImplementCloneable
,
+making it over 500X faster, and PreserveStackTrace
which is now 7X faster.
PMD now supports incremental analysis. Analysis results can be cached and reused between runs. +This allows PMD to skip files without violations that have remained unchanged. In future releases, +we plan to extend this behavior to unchanged files with violations too.
+ +The cache is automatically invalidated if:
+auxclasspath
changed and any rules require type resolutionThis feature is incubating and is disabled by default. It’s only enabled if you +specifically configure a cache file.
+ +To configure the cache file from CLI, a new -cache <path/to/file>
flag has been added.
For Ant, a new cacheLocation
attribute has been added. For instance:
<target name="pmd">
+ <taskdef name="pmd" classname="net.sourceforge.pmd.ant.PMDTask"/>
+ <pmd cacheLocation="build/pmd/pmd.cache">
+ <ruleset>rulesets/java/design.xml</ruleset>
+ <ruleset>java-basic</ruleset>
+ <formatter type="xml" toFile="c:\pmd_report.xml"/>
+ <fileset dir="/usr/local/j2sdk1.4.1_01/src/">
+ <include name="java/lang/*.java"/>
+ </fileset>
+ </pmd>
+ </target>
+
Salesforce developers rejoice. To out growing Apex support we have added full Visualforce support.
+Both CPD and PD are available. So far only a security ruleset is available (vf-security
).
The rule looks for Expression Language occurances printing unescaped values from the backend. These +could lead to XSS attacks.
+ +The rule looks for <apex:page>
tags performing an action on page load, definish such action
+through Expression Language, as doing so is vulnerable to CSRF attacks.
A new ruleset focused on security has been added, consisting of a wide range of rules +to detect most common security problems.
+ +The rule makes sure you are using randomly generated IVs and keys for Crypto
calls.
+Hard-wiring these values greatly compromises the security of encrypted data.
For instance, it would report violations on code such as:
+ +public class without sharing Foo {
+ Blob hardCodedIV = Blob.valueOf('Hardcoded IV 123');
+ Blob hardCodedKey = Blob.valueOf('0000000000000000');
+ Blob data = Blob.valueOf('Data to be encrypted');
+ Blob encrypted = Crypto.encrypt('AES128', hardCodedKey, hardCodedIV, data);
+}
+
+
The rule validates you are checking for access permissions before a SOQL/SOSL/DML operation. +Since Apex runs in system mode not having proper permissions checks results in escalation of +privilege and may produce runtime errors. This check forces you to handle such scenarios.
+ +For example, the following code is considered valid:
+ +public class Foo {
+ public Contact foo(String status, String ID) {
+ Contact c = [SELECT Status__c FROM Contact WHERE Id=:ID];
+
+ // Make sure we can update the database before even trying
+ if (!Schema.sObjectType.Contact.fields.Name.isUpdateable()) {
+ return null;
+ }
+
+ c.Status__c = status;
+ update c;
+ return c;
+ }
+}
+
Check to avoid making DML operations in Apex class constructor/init method. This prevents +modification of the database just by accessing a page.
+ +For instance, the following code would be invalid:
+ +public class Foo {
+ public init() {
+ insert data;
+ }
+
+ public Foo() {
+ insert data;
+ }
+}
+
Checks against calling dangerous methods.
+ +For the time being, it reports:
+ +FinancialForce
’s Configuration.disableTriggerCRUDSecurity()
. Disabling CRUD security
+opens the door to several attacks and requires manual validation, which is unreliable.System.debug
passing sensitive data as parameter, which could lead to exposure
+of private data.Checks against accessing endpoints under plain http. You should always use +https for security.
+ +Checks against redirects to user-controlled locations. This prevents attackers from +redirecting users to phishing sites.
+ +For instance, the following code would be reported:
+ +public class without sharing Foo {
+ String unsafeLocation = ApexPage.getCurrentPage().getParameters.get('url_param');
+ PageReference page() {
+ return new PageReference(unsafeLocation);
+ }
+}
+
Detect classes declared without explicit sharing mode if DML methods are used. This +forces the developer to take access restrictions into account before modifying objects.
+ +Detects the usage of untrusted / unescaped variables in DML queries.
+ +For instance, it would report on:
+ +public class Foo {
+ public void test1(String t1) {
+ Database.query('SELECT Id FROM Account' + t1);
+ }
+}
+
Detects hardcoded credentials used in requests to an endpoint.
+ +You should refrain from hardcoding credentials:
+Instead, you should use Named Credentials and a callout endpoint.
+ +For more information, you can check this
+ +Reports on calls to addError
with disabled escaping. The message passed to addError
+will be displayed directly to the user in the UI, making it prime ground for XSS
+attacks if unescaped.
Makes sure that all values obtained from URL parameters are properly escaped / sanitized +to avoid XSS attacks.
+ +The Braces Rule Set has been added and serves the same purpose as the Braces Rule Set from Java: +It checks the use and placement of braces around if-statements, for-loops and so on.
+ +Avoid using if statements without using braces to surround the code block. If the code +formatting or indentation is lost then it becomes difficult to separate the code being +controlled from the rest.
+ +For instance, the following code shows the different. PMD would report on the not recommended approach:
+ +if (foo) // not recommended
+ x++;
+
+if (foo) { // preferred approach
+ x++;
+}
+
Avoid using ‘while’ statements without using braces to surround the code block. If the code +formatting or indentation is lost then it becomes difficult to separate the code being +controlled from the rest.
+ +For instance, the following code shows the different. PMD would report on the not recommended approach:
+ +while (true) // not recommended
+ x++;
+
+while (true) { // preferred approach
+ x++;
+}
+
Avoid using if..else statements without using surrounding braces. If the code formatting +or indentation is lost then it becomes difficult to separate the code being controlled +from the rest.
+ +For instance, the following code shows the different. PMD would report on the not recommended approach:
+ +// this is not recommended
+if (foo)
+ x = x+1;
+ else
+ x = x-1;
+
+// preferred approach
+if (foo) {
+ x = x+1;
+} else {
+ x = x-1;
+}
+
Avoid using ‘for’ statements without using surrounding braces. If the code formatting or +indentation is lost then it becomes difficult to separate the code being controlled +from the rest.
+ +For instance, the following code shows the different. PMD would report on the not recommended approach:
+ +for (int i = 0; i < 42; i++) // not recommended
+ foo();
+
+for (int i = 0; i < 42; i++) { // preferred approach
+ foo();
+}
+
When accessing a private field / method from another class, the Java compiler will generate an accessor method +with package-private visibility. This adds overhead, and to the dex method count on Android. This situation can +be avoided by changing the visibility of the field / method from private to package-private.
+ +For instance, it would report violations on code such as:
+ +public class OuterClass {
+ private int counter;
+ /* package */ int id;
+
+ public class InnerClass {
+ InnerClass() {
+ OuterClass.this.counter++; // wrong, accessor method will be generated
+ }
+
+ public int getOuterClassId() {
+ return OuterClass.this.id; // id is package-private, no accessor method needed
+ }
+ }
+}
+
This new rule is part of the java-design
ruleset.
The Java rule UnnecessaryLocalBeforeReturn
(ruleset java-design) now has a new property statementOrderMatters
.
+It is enabled by default to stay backwards compatible. But if this property is 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.
The Java rule UseLocaleWithCaseConversions
(ruleset java-design) has been modified, to detect calls
+to toLowerCase
and to toUpperCase
also within method call chains. This leads to more detected cases
+and potentially new false positives.
+See also bugfix #1556.
The Java rule AvoidConstantsInterface
(ruleset java-design) has been removed. It is completely replaced by
+the rule ConstantsInInterface
.
UnusedModifier
(ruleset java-unusedcode) has been moved to the ruleset java-unnecessary
+and has been renamed to UnnecessaryModifier
.
+Additionally, it has been expanded to consider more redundant modifiers:
+ abstract
.static
.public
.public
or static
.static
.JUnitTestsShouldIncludeAssert
(ruleset java-junit) now accepts usage of @Rule
ExpectedException
+to set expectations on exceptions, and are considered as valid assertions.It is now possible to allow CPD suppression through comments in Java. You tell CPD to ignore
+the following code with a comment containin CPD-OFF
and with CPD-ON
you tell CPD to resume
+analysis. The old approach via @SuppressWarnings
annotation is still supported, but is considered
+deprecated, since it is limited to locations where the SuppressWarnings
annotation is allowed.
+See PR #250.
For example:
+ + public Object someMethod(int x) throws Exception {
+ // some unignored code
+
+ // tell cpd to start ignoring code - CPD-OFF
+
+ // mission critical code, manually loop unroll
+ goDoSomethingAwesome(x + x / 2);
+ goDoSomethingAwesome(x + x / 2);
+ goDoSomethingAwesome(x + x / 2);
+ goDoSomethingAwesome(x + x / 2);
+ goDoSomethingAwesome(x + x / 2);
+ goDoSomethingAwesome(x + x / 2);
+
+ // resume CPD analysis - CPD-ON
+
+ // further code will *not* be ignored
+ }
+
CPD now supports the command line option --filelist
. With that, you can specify a file, which
+contains the names and paths of the files, that should be analyzed. This is similar to PMD’s filelist option.
+You need to use this, if you have a large project with many files, and you hit the command line length limit.
ResultSet
(false negative)net.sourceforge.pmd.RuleSetFactory
is now immutable and its behavior cannot be changed anymore.
+It provides constructors to create new adjusted instances. This allows to avoid synchronization in RuleSetFactory.
+See PR #131.net.sourceforge.pmd.RuleSet
is now immutable, too, and can only be created via RuleSetFactory
.
+See PR #145.net.sourceforge.pmd.cli.XPathCLI
has been removed. It’s functionality is fully covered by the Designer.net.sourceforge.pmd.Report
now works with ThreadSafeReportListener
s. Both ReportListener
and
+SynchronizedReportListener
are deprecated in favor of net.sourceforge.pmd.ThreadSafeReportListener
.
+Therefore, the methods getSynchronizedListeners()
and addSynchronizedListeners(...)
have been
+replaced by getListeners()
and addListeners(...)
. See PR #193.The PMD team is pleased to announce PMD 5.5.7.
+ +This is a bug fixing release.
+ +The PMD team is pleased to announce PMD 5.5.6.
+ +This is a bug fixing release.
+ +The PMD team is pleased to announce PMD 5.5.5.
+ +The PMD team is pleased to announce PMD 5.5.4
+ +When accessing a private field / method from another class, the Java compiler will generate a accessor methods +with package-private visibility. This adds overhead, and to the dex method count on Android. This situation can +be avoided by changing the visibility of the field / method from private to package-private.
+ +For instance, it would report violations on code such as:
+ +public class OuterClass {
+ private int counter;
+ /* package */ int id;
+
+ public class InnerClass {
+ InnerClass() {
+ OuterClass.this.counter++; // wrong, accessor method will be generated
+ }
+
+ public int getOuterClassId() {
+ return OuterClass.this.id; // id is package-private, no accessor method needed
+ }
+ }
+}
+
This new rule is part of the java-design
ruleset.
UnusedModifier
(ruleset java-unusedcode) has been expanded to consider more redundant modifiers.
+ abstract
.static
.public
.public
or static
.static
.UnnecessaryLocalBeforeReturn
(ruleset java-design) 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.The PMD team is pleased to announce PMD 5.5.3
+ +The most significant changes are on analysis performance and a whole new Apex Security Rule Set.
+ +Multithread performance has been enhanced by reducing thread-contention on a +bunch of areas. This is still an area of work, as the speedup of running +multithreaded analysis is still relatively small (4 threads produce less +than a 50% speedup). Future releases will keep improving on this area.
+ +Once again, Symbol Table has been an area of great performance improvements. +This time we were able to further improve it’s performance by roughly 10% on all +supported languages. In Java in particular, several more improvements were possible, +improving Symbol Table performance by a whooping 30%, that’s over 5X faster +than PMD 5.5.1, when we first started working on it.
+ +Java developers will also appreciate the revamp of CloneMethodMustImplementCloneable
,
+making it over 500X faster, and PreserveStackTrace
which is now 7X faster.
A new ruleset focused on security has been added, consisting of a wide range of rules +to detect most common security problems.
+ +The rule makes sure you are using randomly generated IVs and keys for Crypto
calls.
+Hard-wiring these values greatly compromises the security of encrypted data.
For instance, it would report violations on code such as:
+ +public class without sharing Foo {
+ Blob hardCodedIV = Blob.valueOf('Hardcoded IV 123');
+ Blob hardCodedKey = Blob.valueOf('0000000000000000');
+ Blob data = Blob.valueOf('Data to be encrypted');
+ Blob encrypted = Crypto.encrypt('AES128', hardCodedKey, hardCodedIV, data);
+}
+
+
The rule validates you are checking for access permissions before a SOQL/SOSL/DML operation. +Since Apex runs in system mode not having proper permissions checks results in escalation of +privilege and may produce runtime errors. This check forces you to handle such scenarios.
+ +For example, the following code is considered valid:
+ +public class Foo {
+ public Contact foo(String status, String ID) {
+ Contact c = [SELECT Status__c FROM Contact WHERE Id=:ID];
+
+ // Make sure we can update the database before even trying
+ if (!Schema.sObjectType.Contact.fields.Name.isUpdateable()) {
+ return null;
+ }
+
+ c.Status__c = status;
+ update c;
+ return c;
+ }
+}
+
Check to avoid making DML operations in Apex class constructor/init method. This prevents +modification of the database just by accessing a page.
+ +For instance, the following code would be invalid:
+ +public class Foo {
+ public init() {
+ insert data;
+ }
+
+ public Foo() {
+ insert data;
+ }
+}
+
Checks against calling dangerous methods.
+ +For the time being, it reports:
+ +FinancialForce
’s Configuration.disableTriggerCRUDSecurity()
. Disabling CRUD security
+opens the door to several attacks and requires manual validation, which is unreliable.System.debug
passing sensitive data as parameter, which could lead to exposure
+of private data.Checks against accessing endpoints under plain http. You should always use +https for security.
+ +Checks against redirects to user-controlled locations. This prevents attackers from +redirecting users to phishing sites.
+ +For instance, the following code would be reported:
+ +public class without sharing Foo {
+ String unsafeLocation = ApexPage.getCurrentPage().getParameters.get('url_param');
+ PageReference page() {
+ return new PageReference(unsafeLocation);
+ }
+}
+
Detect classes declared without explicit sharing mode if DML methods are used. This +forces the developer to take access restrictions into account before modifying objects.
+ +Detects the usage of untrusted / unescaped variables in DML queries.
+ +For instance, it would report on:
+ +public class Foo {
+ public void test1(String t1) {
+ Database.query('SELECT Id FROM Account' + t1);
+ }
+}
+
Detects hardcoded credentials used in requests to an endpoint.
+ +You should refrain from hardcoding credentials:
+Instead, you should use Named Credentials and a callout endpoint.
+ +For more information, you can check this
+ +Reports on calls to addError
with disabled escaping. The message passed to addError
+will be displayed directly to the user in the UI, making it prime ground for XSS
+attacks if unescaped.
Makes sure that all values obtained from URL parameters are properly escaped / sanitized +to avoid XSS attacks.
+ +The Java rule “UseLocaleWithCaseConversions” (ruleset java-design) has been modified, to detect calls
+to toLowerCase
and to toUpperCase
also within method call chains. This leads to more detected cases
+and potentially new false positives.
+See also bugfix #1556.
ResultSet
(false negative)net.sourceforge.pmd.RuleSetFactory
is now immutable and its behavior cannot be changed anymore.
+It provides constructors to create new adjusted instances. This allows to avoid synchronization in RuleSetFactory.
+See PR #131.Summary:
+ +New Supported Languages:
+ +Feature Requests and Improvements:
+ +New Rules:
+ +Pull Requests:
+ +Bugfixes:
+ +New Rules:
+ +Pull Requests:
+ +Bugfixes:
+ +System requirements:
+ +PMD and CPD need at least a java7 runtime environment. For analyzing Salesforce.com Apex source code, +you’ll need a java8 runtime environment.
+ +New Supported Languages:
+ +New and modified Rules:
+ +serialVersionUIDCommentRequired
which controls the comment requirements
+for serialVersionUID fields. By default, no comment is required for this field.if
block contains a return. Then the content of the else block can be
+put outside. See #1486.Improvements and CLI changes:
+ +--ignore-usings
: Ignore using directives in C# when comparing text.-norulesetcompatibility
- this disables the ruleset factory
+compatibility filter and fails, if e.g. an old rule name is used in the ruleset.
+See also #1360.
+This option is also available for the ant task: <noRuleSetCompatibility>true</noRuleSetCompatibility>
.-filelist
- this provides an alternative way to define, which
+files should be process by PMD. With this option, you can provide the path to a single file containing a comma
+delimited list of files to analyze. If this is given, then you don’t need to provide -dir
.
+See PR#98.Pull Requests:
+ +Bugfixes:
+ +The PMD team is pleased to announce PMD 5.4.6.
+ +This is a bug fixing release.
+ +The PMD team is pleased to announce PMD 5.4.5
+ +This is a bug fixing release.
+ +UnusedModifier
(ruleset java-unusedcode) has been expanded to consider more redundant modifiers.
+ abstract
.static
.public
.public
or static
.static
.The PMD team is pleased to announce PMD 5.4.4
+ +This is a bug fixing release. The most significant changes are on analysis performance.
+ +Multithread performance has been enhanced by reducing thread-contention on a +bunch of areas. This is still an area of work, as the speedup of running +multithreaded analysis is still relatively small (4 threads produce less +than a 50% speedup). Future releases will keep improving on this area.
+ +Once again, Symbol Table has been an area of great performance improvements. +This time we were able to further improve it’s performance by roughly 10% on all +supported languages. In Java in particular, several more improvements were possible, +improving Symbol Table performance by a whooping 30%, that’s over 5X faster +than PMD 5.4.2, when we first started working on it.
+ +Java developers will also appreciate the revamp of CloneMethodMustImplementCloneable
,
+making it over 500X faster, and PreserveStackTrace
which is now 7X faster.
This is a bug fixing release, no major changes were introduced.
+ +The Java rule “UseLocaleWithCaseConversions” (ruleset java-design) has been modified, to detect calls
+to toLowerCase
and to toUpperCase
also within method call chains. This leads to more detected cases
+and potentially new false positives.
+See also bugfix #1556.
ResultSet
(false negative)Summary:
+ +Pull Requests:
+ +Bugfixes:
+ +New Supported Languages:
+ +Feature Request and Improvements:
+ +Modified Rules:
+ +Pull Requests:
+ +Bugfixes:
+ +CLI Changes:
+ +-norulesetcompatibility
- this disables the ruleset factory
+compatibility filter and fails, if e.g. an old rule name is used in the ruleset.
+See also #1360.
+This option is also available for the ant task: <noRuleSetCompatibility>true</noRuleSetCompatibility>
.Feature Request and Improvements:
+ +--ignore-usings
: Ignore using directives in C# when comparing text.Modified Rules:
+ +serialVersionUIDCommentRequired
which controls the comment requirements
+for serialVersionUID fields. By default, no comment is required for this field.Pull Requests:
+ +Bugfixes:
+ +Summary:
+ +Feature Request and Improvements:
+ +failOnViolation
. Executing PMD with the option
+-failOnViolation false
will perform the PMD checks but won’t fail the build and still exit with status 0.
+This is useful if you only want to generate the report with violations but don’t want to fail your build.New Rules:
+ +Java:
+ +Basic: SimplifiedTernary (rulesets/java/basic.xml/SimplifiedTernary)
+Ternary operator with a boolean literal can be simplified with a boolean
+expression.
Clone: CloneMethodMustBePublic (rulesets/java/clone.xml/CloneMethodMustBePublic)
+The java manual says “By convention,
+classes that implement the Cloneable
interface should override Object.clone
(which is protected)
+with a public method.”
Clone: CloneMethodReturnTypeMustMatchClassName (rulesets/java/clone.xml/CloneMethodReturnTypeMustMatchClassName)
+If a class implements Cloneable
+the return type of the method clone()
must be the class name.
Comments: CommentDefaultAccessModifier (rulesets/java/comments.xml/CommentDefaultAccessModifier)
+In order to avoid mistakes with
+forgotten access modifiers for methods, this rule ensures, that you explicitly mark the usage of the
+default access modifier by placing a comment.
Design: SingletonClassReturningNewInstance (rulesets/java/design.xml/SingletonClassReturningNewInstance)
+Verifies that the method called getInstance
returns a cached instance and not always a fresh, new instance.
Design: SingleMethodRule (rulesets/java/design.xml/SingleMethodSingletonRule)
+Verifies that there is only one method called
+getInstance
. If there are more methods that return the singleton, then it can easily happen, that these
+are not the same instances - and thus no singleton.
Unnecessary: UselessQualifiedThis (rulesets/java/unnecessary.xml/UselessQualifiedThis)
+Flags unnecessary qualified usages
+of this, when this
alone would be unique. E.g. use just this
instead of Foo.this
.
Maven POM: (The rules can be found in the pmd-xml module)
+ +Basic: ProjectVersionAsDependencyVersion (rulesets/pom/basic.xml/ProjectVersionAsDependencyVersion)
+Checks the usage of ${project.version}
in Maven POM files.
Basic: InvalidDependencyTypes (rulesets/pom/basic.xml/InvalidDependencyTypes)
+Verifies that only the default types (jar, war, …) for dependencies are used.
Ruleset snippet to activate the new rules:
+ +<rule ref="rulesets/java/basic.xml/SimplifiedTernary"/>
+<rule ref="rulesets/java/clone.xml/CloneMethodReturnTypeMustMatchClassName"/>
+<rule ref="rulesets/java/clone.xml/CloneMethodMustBePublic"/>
+<rule ref="rulesets/java/comments.xml/CommentDefaultAccessModifier"/>
+<rule ref="rulesets/java/design.xml/SingleMethodSingleton"/>
+<rule ref="rulesets/java/design.xml/SingletonClassReturningNewInstance"/>
+<rule ref="rulesets/java/unnecessary.xml/UselessQualifiedThis"/>
+
+<rule ref="rulesets/pom/basic.xml/ProjectVersionAsDependencyVersion"/>
+<rule ref="rulesets/pom/basic.xml/InvalidDependencyTypes"/>
+
Modified Rules:
+ +Java
+ +Basic: CheckResultSet (rulesets/java/basic.xml/CheckResultSet)
+Do not require to check the result of a navigation method, if it is returned.
JUnit: UseAssertTrueInsteadOfAssertEquals (rulesets/java/junit.xml/UseAssertTrueInsteadOfAssertEquals)
+This rule also flags assertEquals, that use Boolean.TRUE/FALSE constants.
Naming: AbstractNaming (rulesets/java/naming.xml/AbstractNaming)
+By default, this rule flags now classes,
+that are named “Abstract” but are not abstract. This behavior can be disabled by setting
+the new property strict
to false.
Naming: ShortMethodName (rulesets/java/naming.xml/ShortMethodName)
+Additional property minimum
to configure the minimum required length of a method name.
Naming: ShortVariable (rulesets/java/naming.xml/ShortVariable)
+Additional property minimum
to configure the minimum required length of a variable name.
UnusedCode: UnusedPrivateField (rulesets/java/unusedcode.xml/UnusedPrivateField)
+This rule won’t trigger anymore if Lombok is in use.
+See #1420.
Renamed Rules:
+ +Removed Rules:
+ +Basic: The following rules of ruleset “Basic” were marked as deprecated and are removed with this release now:
+
+EmptyCatchBlock, EmptyIfStatement, EmptyWhileStmt, EmptyTryBlock, EmptyFinallyBlock, EmptySwitchStatements, EmptySynchronizedBlock, EmptyStatementNotInLoop, EmptyInitializer, EmptyStatementBlock, EmptyStaticInitializer
+
+UnnecessaryConversionTemporary, UnnecessaryReturn, UnnecessaryFinalModifier, UselessOverridingMethod, UselessOperationOnImmutable, UnusedNullCheckInEquals, UselessParentheses
+
+These rules are still available in the rulesets “Empty” (rulesets/java/empty.xml) and
+“Unnecessary” (rulesets/java/unnecessary.xml) respectively.
Design: The rule “UncommentedEmptyMethod” has been renamed last release to “UncommentedEmptyMethodBody”. The +old rule name reference has been removed with this release now.
+Controversial: The rule “BooleanInversion” has been deprecated last release +and has been removed with this release completely.
+Pull Requests:
+ +Bugfixes:
+ +API Changes:
+ +pmd requires now JDK 1.7 or above.
+pmd-core: net.sourceforge.pmd.lang.symboltable.Scope
:
The method addNameOccurrence
returns now a Set of
+NameDeclarations to which the given occurrence has been added. This is useful in case there are ambiguous declarations
+of methods.
pmd-core: net.sourceforge.pmd.lang.symboltable.AbstractScope
:
The method findVariableHere
returns now
+a Set of NameDeclarations which match the given occurrence. This is useful in case there are ambiguous declarations
+of methods.
Summary
+ +Feature Requests and Improvements:
+ +Pull Requests:
+ +Bugfixes:
+ +API Changes:
+ +-norulesetcompatibility
- this disables the ruleset factory
+compatibility filter and fails, if e.g. an old rule name is used in the ruleset.
+See also #1360.
+This option is also available for the ant task: <noRuleSetCompatibility>true</noRuleSetCompatibility>
.New Supported Languages:
+ +Feature Request and Improvements:
+ +Modified Rules:
+ +Pull Requests:
+ +Bugfixes:
+ +CLI Changes:
+ +Feature Request and Improvements:
+ +--ignore-usings
: Ignore using directives in C# when comparing text.Modified Rules:
+ +serialVersionUIDCommentRequired
which controls the comment requirements
+for serialVersionUID fields. By default, no comment is required for this field.Pull Requests:
+ +Bugfixes:
+ +Modified Rules:
+ +close
itself is
+always considered as a closeTarget - no matter whether it is configured with the closeTargets property
+or not.Pull Requests:
+ +Bugfixes:
+ +Bugfixes:
+ +Pull Requests:
+ +Bugfixes:
+ +Bugfixes:
+ +New/Modified/Deprecated Rules:
+ +Pull Requests:
+ +Bugfixes:
+ +New Supported Languages:
+ +Feature Requests and Improvements:
+ +4
if any violations have been found. This behavior has been introduced to ease PMD
+integration into scripts or hooks, such as SVN hooks.New/Modified/Deprecated Rules:
+ +The following rules have been +enhanced +:
+ +The following rules are marked as +deprecated +and will be removed with the next release of PMD.
+ +Language Java, ruleset basic.xml: The following rules have been moved into the empty.xml
ruleset. You’ll need
+to enable the “empty” ruleset explicitly from now on, if you want to have these rules executed:
EmptyCatchBlock, EmptyIfStatement, EmptyWhileStmt, EmptyTryBlock, EmptyFinallyBlock, EmptySwitchStatements, +EmptySynchronizedBlock, EmptyStatementNotInLoop, EmptyInitializer, EmptyStatementBlock, EmptyStaticInitializer.
+Language Java, ruleset basic.xml: The following rules have been moved into the unnecessary.xml
ruleset. You’ll need
+to enable the “unnecessary” ruleset explicitly from now on, if you want to have these rules executed:
UnnecessaryConversionTemporary, UnnecessaryReturn, UnnecessaryFinalModifier, UselessOverridingMethod, +UselessOperationOnImmutable, UnusedNullCheckInEquals, UselessParentheses.
+Language Java, ruleset design.xml: The rule “UncommentedEmptyMethod” has been renamed to “UncommentedEmptyMethodBody”. +See also bug #1283.
+Language Java, ruleset controversial.xml: The rule “BooleanInversion” is deprecated and will be removed with +the next release. See #1277 for more details.
+Pull Requests:
+ +csv_with_linecount_per_file
which outputs the correct line count per file.Bugfixes:
+ +API Changes:
+ +net.sourceforge.pmd.cpd.Match.iterator()
now returns an iterator of the new type net.sourceforge.pmd.cpd.Mark
instead
+of TokenEntry. A Mark
contains all the informations about each single duplication, including the TokenEntry via Mark.getToken()
.
+This Mark is useful for reporting the correct line count for each duplication. Previously only one line count was available.
+As for some languages CPD can be instructed to ignore comments, the line count could be different in the different files
+for the same duplication.
pmd-test: The utility class StreamUtil
is deprecated. Just use Apache Commons IO Utils instead.
Feature Requests and Improvements:
+ +Modified Rules:
+ +byte[]
is used as the last argument, it is ignored and no violation will be reported.checkNativeMethods
checkNativeMethodParameters
Pull requests:
+ +Bugfixes:
+ +New Parameters for CPD:
+ +For the language cpp, the following new parameters are supported:
+ +--no-skip-blocks
: Disables skipping of code blocks like a pre-processor. This is by default enabled.--skip-blocks-pattern
: Pattern to find the blocks to skip. Start and End pattern separated by “|
”. Default value is “#if 0|#endif
”.Bugfixes:
+ +Bugfixes:
+ +Modularization of the source code:
+ +The source code of pmd was undergoing a major restructuring. Each language is separated +out into its own module. This reduces the size of the artifacts significantly, if only +one language is needed. It also makes it easier, to add new languages as extensions.
+ +Therefore, the maven coordinates needed to change. In order to just use pmd with java support, you’ll need +the following two dependencies:
+ +<dependency>
+ <groupId>net.sourceforge.pmd</groupId>
+ <artifactId>pmd-core</artifactId>
+ <version>5.2.0</version>
+</dependency>
+<dependency>
+ <groupId>net.sourceforge.pmd</groupId>
+ <artifactId>pmd-java</artifactId>
+ <version>5.2.0</version>
+</dependency>
+
The binary package still contains all languages and can be used as usual. Have a look at +the central repository for available modules.
+ +New Languages
+ +Pull requests:
+ + + +New/Modified Rules:
+ +Bugfixes:
+ +Feature Requests and Improvements:
+ +New/Modified Rules:
+ +ignoreAnonymousClassDeclarations
:
+Ignore Field Declarations, that are initialized with anonymous class declarations. This property is enabled by default.
+See feature #1244.minimum
: Number of characters that are required
+as a minimum for a class name. By default, 5 characters are required - if the class name is shorter, a violation
+will be reported. See feature #1232.Bugfixes:
+ +Feature Requests and Improvements:
+ +Pull requests:
+ +New Rules:
+ +Bugfixes:
+ +CPD Changes:
+ +New/Updated Languages:
+ +New/Updated Rulesets and Rules:
+ +Bugfixes:
+ +http://sourceforge.net/p/pmd/bugs/milestone/PMD-5.1.0/
+ +CPD Changes:
+Miscellaneous:
+ +API Changes
+ +Fixed bug 991: AvoidSynchronizedAtMethodLevel for static methods
+Fixed bug 1084: NPE at UselessStringValueOfRule.java:36
+Fixed bug 1091: file extension for fortran seems to be wrong in cpdgui tools
+Fixed bug 1092: Wrong Attribute "excludemarker" in Ant Task Documentation
+Fixed bug 1095: AvoidFinalLocalVariable false positive
+Fixed bug 1099: UseArraysAsList false positives
+Fixed bug 1102: False positive: shift operator parenthesis
+Fixed bug 1104: IdempotentOperation false positive
+Fixed bug 1107: PMD 5.0.4 couldn't parse call of parent outer java class method from inner class
+Fixed bug 1069: Eclipse plugin does not accept project-local config
+Fixed bug 1111: False positive: Useless parentheses
+Fixed bug 1114: CPD - Tokenizer not initialized with requested properties
+Fixed bug 1118: ClassCastException in pmd.lang.ecmascript.ast.ASTElementGet
+
Fixed bug 254: False+ : UnusedImport with Javadoc @throws
+Fixed bug 794: False positive on PreserveStackTrace with anonymous inner
+Fixed bug 1063: False+: ArrayIsStoredDirectly
+Fixed bug 1080: net.sourceforge.pmd.cpd.CPDTest test failing
+Fixed bug 1081: Regression: CPD skipping all files when using relative paths
+Fixed bug 1082: CPD performance issue on larger projects
+Fixed bug 1085: NullPointerException by at net.sourceforge.pmd.lang.java.rule.design.GodClassRule.visit(GodClassRule.java:313)
+Fixed bug 1086: Unsupported Element and Attribute in Ant Task Example
+Fixed bug 1087: PreserveStackTrace (still) ignores initCause()
+Fixed bug 1089: When changing priority in a custom ruleset, violations reported twice
+
Fixed bug 938: False positive on LooseCoupling for overriding methods
+Fixed bug 940: False positive on UnsynchronizedStaticDateFormatter
+Fixed bug 942: CheckResultSet False Positive and Negative
+Fixed bug 943: PreserveStackTrace false positive if a StringBuffer exists
+Fixed bug 945: PMD generates RuleSets it cannot read.
+Fixed bug 958: Intermittent NullPointerException while loading XPath node attributes
+Fixed bug 968: Issues with JUnit4 @Test annotation with expected exception (Thanks to Yiannis Paschalidis)
+Fixed bug 975: false positive in ClassCastExceptionWithToArray
+Fixed bug 976: UselessStringValueOf wrong when appending character arrays
+Fixed bug 977: MisplacedNullCheck makes false positives
+Fixed bug 984: Cyclomatic complexity should treat constructors like methods
+Fixed bug 985: Suppressed methods shouldn't affect avg CyclomaticComplexity
+Fixed bug 992: Class java.beans.Statement triggered in CloseResource rule
+Fixed bug 997: Rule NonThreadSafeSingleton gives analysis problem
+Fixed bug 999: Law of Demeter: False positives and negatives
+Fixed bug 1002: False +: FinalFieldCouldBeStatic on inner class
+Fixed bug 1005: False + for ConstructorCallsOverridableMethod - overloaded methods
+Fixed bug 1027: PMD Ant: java.lang.ClassCastException
+Fixed bug 1032: ImmutableField Rule: Private field in inner class gives false positive
+Fixed bug 1064: Exception running PrematureDeclaration
+Fixed bug 1068: CPD fails on broken symbolic links
+Fixed bug 1073: Hard coded violation messages CommentSize
+Fixed bug 1074: rule priority doesn't work on group definitions
+Fixed bug 1076: Report.treeIterator() does not return all violations
+Fixed bug 1077: Missing JavaDocs for Xref-Test Files
+Fixed bug 1078: Package statement introduces false positive UnnecessaryFullyQualifiedName violation
+Merged pull request #14: fix Nullpointer Exception when using -l jsp
+
Fixed bug 878: False positive: UnusedFormalParameter for abstract methods
+Fixed bug 913: SignatureDeclareThrowsException is raised twice
+Fixed bug 947: CloseResource rule fails if field is marked with annotation
+Fixed bug 1004: targetjdk isn't attribute of PMD task
+Fixed bug 1007: Parse Exception with annotation
+Fixed bug 1011: CloseResource Rule ignores Constructors
+Fixed bug 1012: False positive: Useless parentheses.
+Fixed bug 1020: Parsing Error
+Fixed bug 1026: PMD doesn't handle 'value =' in SuppressWarnings annotation
+Fixed bug 1028: False-positive: Compare objects with equals for Enums
+Fixed bug 1030: CPD Java.lang.IndexOutOfBoundsException: Index:
+Fixed bug 1037: Facing a showstopper issue in PMD Report Class (report listeners)
+Fixed bug 1039: pmd-nicerhtml.xsl is packaged in wrong location
+Fixed bug 1043: node.getEndLine() always returns 0 (ECMAscript)
+Fixed bug 1044: Unknown option: -excludemarker
+Fixed bug 1046: ant task CPDTask doesn't accept ecmascript
+Fixed bug 1047: False Positive in 'for' loops for LocalVariableCouldBeFinal in 5.0.1
+Fixed bug 1048: CommentContent Rule, String Index out of range Exception
+Fixed bug 1049: Errors in "How to write a rule"
+Fixed bug 1055: Please add a colon in the ant output after line,column for Oracle JDeveloper IDE usage
+Fixed bug 1056: "Error while processing" while running on xml file with DOCTYPE reference
+Fixed bug 1060: GodClassRule >>> wrong method
+
Fixed bug 820: False+ AvoidReassigningParameters
+Fixed bug 1008: pmd-5.0.0: ImmutableField false positive on self-inc/dec
+Fixed bug 1009: pmd-5.0.0: False + UselessParentheses
+Fixed bug 1003: newline characters stripped from CPD data in PMD 5.0.0
+Fixed bug 1001: InsufficientStringBufferDeclaration fails to parse hex
+Fixed bug 522: InefficientStringBuffering bug false +
+Fixed bug 953: String.InefficientStringBuffering false +
+Fixed bug 981: Unable to parse
+Fixed bug 1010: pmd: parsing of generic method call with super fails
+Fixed bug 996: pmd-4.2.6: MissingBreakInSwitch fails to report violation
+Fixed bug 993: Invalid NPath calculation in return statement. Thanks to Prabhjot Singh for the patch.
+Fixed bug 1023: c/c++ \ as a continuation character not supported
+Fixed bug 1033: False+ : SingularField
+Fixed bug 1025: Regression of Crash in PMDTask due to multithreading (Eclipse and Java 1.5)
+Fixed bug 1017: Type resolution very slow for big project. Thanks to Roman for the patch.
+Fixed bug 1036: Documentation: default threshold values removed from v5.0
+Fixed bug 1035: UseObjectForClearerAPI has misspelled message
+Fixed bug 1031: false DontImportJavaLang
+Fixed bug 1034: UseConcurrentHashMap flags calls to methods that return Map
+Fixed bug 1006: Problem with implementation of getPackageNameImage method
+Fixed bug 1014: AvoidLiteralsInIfCondition must NOT consider null
+Fixed bug 1013: jnlp link for CPD is wrong
+
+PMD Command Line Changes:
+ Improved command line interface (CLI) parsing using JCommander.
+ Note: this breaks compatibility, but should be easy to fix.
+ With "-d" you specify nowtThe source files / source directory to be scanned.
+ With "-f" you select the report format (like text, html, ...)
+ With "-R" you select the rulesets to be used.
+ Example: pmd -d c:\data\pmd\pmd\test-data\Unused1.java -f xml -R rulesets/java/unusedcode.xml
+
+Improved JSP parser to be less strict with not valid XML documents (like HTML). Thanks to Victor Bucutea.
+Fixed bgastviewer not working. Thanks to Victor Bucutea.
+Improved CPD: Support in CPD for IgnoreAnnotations and SuppressWarnings("CPD-START"). Thanks to Matthew Short.
+Fixed C# support for CPD - thanks to TIOBE Software.
+
+New Ecmascript rules:
+
+ Basic ruleset: AvoidTrailingComma
+
Fixed bug 3515487: Inconsistent reference to ruleset file in documentation
+Fixed bug 3470274: Using Label for lines in XMLRenderer
+Fixed bug 3175710: NPE in InsufficientStringBufferDeclaration
+
+CPD:
+- Exit with status code 4 when CPD detects code duplication (Patch ID: 3497021)
+
This version of PMD breaks API compatibility with prior versions of PMD, as well
+as RuleSet XML compatibility. Also the maven coordinates (groupId) have been changed.
+The decision to break compatibility, allows PMD
+internals and code organization to be improved to better handle additional
+languages. This opportunity was used to remove depreciated APIs, and beat up
+any code which has thumbed its nose at the developers over the years. ;)
+
+The following is relatively complete list of the major changes (this may not be
+100% accurate, see actual source code when in doubt):
+
+Fixed bug (no number) - Fixed UseStringBufferLengthRule only worked once per class
+All StringBuffer-related rules now also catch StringBuilder-related issues in the same way
+
+ API Change - Unification of treatment of languages within PMD core:
+ Added - net.sourceforge.pmd.lang.Language (now an 'enum')
+ Added - net.sourceforge.pmd.lang.LanguageVersion
+ Added - net.sourceforge.pmd.lang.LanguageVersionDiscoverer
+ Added - net.sourceforge.pmd.lang.LanguageVersionHandler
+ Added - net.sourceforge.pmd.lang.XPathHandler
+ Added - net.sourceforge.pmd.lang.ast.xpath.AbstractASTXPathHandler
+ Added - net.sourceforge.pmd.lang.xpath.Initializer
+ Added - net.sourceforge.pmd.lang.ast.AbstractTokenManager
+ Added - net.sourceforge.pmd.lang.ast.CharStream
+ Added - net.sourceforge.pmd.lang.ast.JavaCharStream
+ Added - net.sourceforge.pmd.lang.ast.SimpleCharStream
+ Added - net.sourceforge.pmd.lang.ast.TokenMgrError
+ Added - net.sourceforge.pmd.lang.rule.stat.StatisticalRule
+ Added - net.sourceforge.pmd.lang.rule.stat.StatisticalRuleHelper
+ Added - net.sourceforge.pmd.lang.java.rule.AbstractStatisticalJavaRule
+ Added - net.sourceforge.pmd.lang.rule.AbstractRuleViolationFactory
+ Added - net.sourceforge.pmd.lang.rule.RuleViolationFactory
+ Added - net.sourceforge.pmd.lang.java.rule.JavaRuleViolationFactory
+ Added - net.sourceforge.pmd.lang.jsp.rule.JspRuleViolationFactory
+ Renamed - net.sourceforge.pmd.AbstractRule to net.sourceforge.pmd.lang.rule.AbstractRule
+ Renamed - net.sourceforge.pmd.AbstractJavaRule to net.sourceforge.pmd.lang.java.rule.AbstractJavaRule
+ Renamed - net.sourceforge.pmd.AbstractRuleChainVisitor to net.sourceforge.pmd.lang.rule.AbstractRuleChainVisitor
+ Renamed - net.sourceforge.pmd.RuleChainVisitor to net.sourceforge.pmd.lang.rule.RuleChainVisitor
+ Renamed - net.sourceforge.pmd.SourceFileSelector to net.sourceforge.pmd.lang.rule.LanguageFilenameFilter
+ Renamed - net.sourceforge.pmd.rule.XPathRule to net.sourceforge.pmd.lang.rule.XPathRule
+ Renamed - net.sourceforge.pmd.jsp.rule.AbstractJspRule to net.sourceforge.pmd.lang.jsp.rule.AbstractJspRule
+ Renamed - net.sourceforge.pmd.ast.CompilationUnit to net.sourceforge.pmd.lang.ast.RootNode
+ Renamed - net.sourceforge.pmd.ast.JavaRuleChainVisitor to net.sourceforge.pmd.lang.java.rule.JavaRuleChainVisitor
+ Renamed - net.sourceforge.pmd.jsp.ast.JspRuleChainVisitor to net.sourceforge.pmd.lang.jsp.rule.JspRuleChainVisitor
+ Renamed - net.sourceforge.pmd.parser.Parser to net.sourceforge.pmd.lang.Parser
+ Renamed - net.sourceforge.pmd.parser.TokenManager to net.sourceforge.pmd.lang.TokenManager
+ Renamed - net.sourceforge.pmd.parser.* into net.sourceforge.pmd.lang.{Language}
+ Renamed - net.sourceforge.pmd.sourcetypehandlers.SourceTypeHandler to net.sourceforge.pmd.lang.LanguageVersionHandler
+ Renamed - net.sourceforge.pmd.sourcetypehandlers.VisitorStarter to net.sourceforge.pmd.lang.VisitorStarter
+ Renamed - net.sourceforge.pmd.sourcetypehandlers.* into net.sourceforge.pmd.lang.{Language}
+ Renamed - net.sourceforge.pmd.stat.StatisticalRule to net.sourceforge.pmd.lang.rule.StatisticalRuleHelper
+ Renamed - net.sourceforge.pmd.jaxen.TypeOfFunction to net.sourceforge.pmd.lang.java.xpath.TypeOfFunction
+ Renamed - net.sourceforge.pmd.jaxen.MatchesFunction to net.sourceforge.pmd.lang.xpath.MatchesFunction
+ Renamed - net.sourceforge.pmd.jaxen.Attribute to net.sourceforge.pmd.lang.ast.xpath.Attribute
+ Renamed - net.sourceforge.pmd.jaxen.AttributeAxisIterator to net.sourceforge.pmd.lang.ast.xpath.AttributeAxisIterator
+ Renamed - net.sourceforge.pmd.jaxen.DocumentNavigator to net.sourceforge.pmd.lang.ast.xpath.DocumentNavigator
+ Renamed - net.sourceforge.pmd.jaxen.NodeIterator to net.sourceforge.pmd.lang.ast.xpath.NodeIterator
+ Renamed - net.sourceforge.pmd.ast.* into net.sourceforge.pmd.lang.java.ast.*
+ Renamed - net.sourceforge.pmd.rules.* into net.sourceforge.pmd.lang.java.rule.* and updated to follow conventions
+ Renamed - net.sourceforge.pmd.jsp.ast.* into net.sourceforge.pmd.lang.jsp.ast.*
+ Renamed - net.sourceforge.pmd.jsp.rules.* into net.sourceforge.pmd.lang.jsp.ast.rule.* and updated to follow conventions
+ Deleted - net.sourceforge.pmd.cpd.cppast.* into net.sourceforge.pmd.lang.cpp.ast.*
+ Deleted - net.sourceforge.pmd.CommonAbstractRule
+ Deleted - net.sourceforge.pmd.SourceFileConstants
+ Deleted - net.sourceforge.pmd.SourceType
+ Deleted - net.sourceforge.pmd.SourceTypeDiscoverer
+ Deleted - net.sourceforge.pmd.SourceTypeToRuleLanguageMapper
+ Deleted - net.sourceforge.pmd.TargetJDK1_3
+ Deleted - net.sourceforge.pmd.TargetJDK1_4
+ Deleted - net.sourceforge.pmd.TargetJDK1_5
+ Deleted - net.sourceforge.pmd.TargetJDK1_6
+ Deleted - net.sourceforge.pmd.TargetJDK1_7
+ Deleted - net.sourceforge.pmd.TargetJDKVersion
+ Deleted - net.sourceforge.pmd.cpd.SourceFileOrDirectoryFilter
+ Deleted - net.sourceforge.pmd.sourcetypehandlers.SourceTypeHandlerBroker
+ Deleted - net.sourceforge.pmd.ast.JavaCharStream
+ Deleted - net.sourceforge.pmd.ast.CharStream
+ Deleted - net.sourceforge.pmd.ast.TokenMgrError
+ Deleted - net.sourceforge.pmd.jsp.ast.JspCharStream
+ Deleted - net.sourceforge.pmd.jsp.ast.TokenMgrError
+
+ API Change - Generalize RuleViolation treatment
+ Renamed - net.sourceforge.pmd.IRuleViolation to net.sourceforge.pmd.RuleViolation
+ Renamed - net.sourceforge.pmd.RuleViolation to net.sourceforge.pmd.lang.rule.AbstractRuleViolation
+ Added - net.sourceforge.pmd.RuleViolationComparator
+ Added - net.sourceforge.pmd.lang.java.rule.JavaRuleViolation
+ Added - net.sourceforge.pmd.lang.jsp.rule.JspRuleViolation
+
+ API Change - Generalize DFA treatment
+ Renamed - net.sourceforge.pmd.dfa.IDataFlowNode to net.sourceforge.pmd.lang.dfa.DataFlowNode
+ Renamed - net.sourceforge.pmd.dfa.DataFlowNode to net.sourceforge.pmd.lang.dfa.AbstractDataFlowNode
+ Renamed - net.sourceforge.pmd.dfa.Linker to net.sourceforge.pmd.lang.dfa.Linker
+ Renamed - net.sourceforge.pmd.dfa.LinkerException to net.sourceforge.pmd.lang.dfa.LinkerException
+ Renamed - net.sourceforge.pmd.dfa.NodeType to net.sourceforge.pmd.lang.dfa.NodeType
+ Renamed - net.sourceforge.pmd.dfa.StackObject to net.sourceforge.pmd.lang.dfa.StackObject
+ Renamed - net.sourceforge.pmd.dfa.SequenceChecker to net.sourceforge.pmd.lang.dfa.SequenceChecker
+ Renamed - net.sourceforge.pmd.dfa.SequenceException to net.sourceforge.pmd.lang.dfa.SequenceException
+ Renamed - net.sourceforge.pmd.dfa.StartOrEndDataFlowNode to net.sourceforge.pmd.lang.dfa.StartOrEndDataFlowNode
+ Renamed - net.sourceforge.pmd.dfa.Structure to net.sourceforge.pmd.lang.dfa.Structure
+ Renamed - net.sourceforge.pmd.dfa.variableaccess.VariableAccess to net.sourceforge.pmd.lang.dfa.VariableAccess
+ Renamed - net.sourceforge.pmd.dfa.variableaccess.VariableAccessException to net.sourceforge.pmd.lang.dfa.VariableAccessException
+ Renamed - net.sourceforge.pmd.dfa.pathfinder.* to net.sourceforge.pmd.lang.dfa.pathfinder.*
+ Renamed - net.sourceforge.pmd.dfa.report.* to net.sourceforge.pmd.lang.dfa.report.*
+ Renamed - net.sourceforge.pmd.dfa.DaaRuleViolation to net.sourceforge.pmd.lang.java.dfa.DaaRuleViolation
+ Renamed - net.sourceforge.pmd.dfa.DataFlowFacade to net.sourceforge.pmd.lang.java.dfa.DataFlowFacade
+ Renamed - net.sourceforge.pmd.dfa.StatementAndBraceFinder to net.sourceforge.pmd.lang.java.dfa.StatementAndBraceFinder
+ Renamed - net.sourceforge.pmd.dfa.variableaccess.VariableAccessVisitor to net.sourceforge.pmd.lang.java.dfa.VariableAccessVisitor
+ Added - net.sourceforge.pmd.lang.java.dfa.JavaDataFlowNode
+ Added - net.sourceforge.pmd.lang.DataFlowHandler
+
+ API Change - Generalize Symbol Table treatement
+ Deleted - net.sourceforge.pmd.symboltable.JspSymbolFacade
+ Deleted - net.sourceforge.pmd.symboltable.JspScopeAndDeclarationFinder
+ Renamed - net.sourceforge.pmd.symboltable.* to net.sourceforge.pmd.lang.java.symboltable.*
+
+ API Change - Generalize Type Resolution treatment
+ Renamed - net.sourceforge.pmd.typeresolution.* to net.sourceforge.pmd.lang.java.typeresolution.*
+
+ API Change - Generalize Property Descriptor treatment
+ Renamed - net.sourceforge.pmd.properties.* to net.sourceforge.pmd.lang.rule.properties.*
+ Renamed - net.sourceforge.pmd.properties.AbstractPMDProperty to net.sourceforge.pmd.lang.rule.properties.AbstractProperty
+ Changed - net.sourceforge.pmd.properties.PropertyDescriptor to use Generics, and other changes
+ Added - net.sourceforge.pmd.lang.rule.properties.* new types and other API changes
+
+ API Change - Generalize AST treatment
+ Added - net.sourceforge.pmd.lang.ast.Node (interface extracted from old Node/SimpleNode)
+ Added - net.sourceforge.pmd.lang.ast.AbstractNode
+ Added - net.sourceforge.pmd.ast.DummyJavaNode
+ Added - net.sourceforge.pmd.jsp.ast.AbstractJspNode
+ Added - net.sourceforge.pmd.jsp.ast.JspNode
+ Renamed - net.sourceforge.pmd.ast.SimpleJavaNode to net.sourceforge.pmd.ast.AbstractJavaNode
+ Renamed - net.sourceforge.pmd.ast.SimpleJavaTypeNode to net.sourceforge.pmd.ast.AbstractJavaTypeNode
+ Renamed - net.sourceforge.pmd.ast.SimpleJavaAccessNode to net.sourceforge.pmd.ast.AbstractJavaAccessNode
+ Renamed - net.sourceforge.pmd.ast.SimpleJavaAccessTypeNode to net.sourceforge.pmd.ast.AbstractJavaAccessTypeNode
+ Deleted - net.sourceforge.pmd.ast.Node
+ Deleted - net.sourceforge.pmd.ast.SimpleNode
+ Deleted - net.sourceforge.pmd.ast.AccessNodeInterface
+ Deleted - net.sourceforge.pmd.jsp.ast.Node
+ Deleted - net.sourceforge.pmd.jsp.ast.SimpleNode
+
+ API Change - General code reorganization/cleanup
+ Renamed - net.sourceforge.pmd.AbstractDelegateRule to net.sourceforge.pmd.lang.rule.AbstractDelegateRule
+ Renamed - net.sourceforge.pmd.MockRule to net.sourceforge.pmd.lang.rule.MockRule
+ Renamed - net.sourceforge.pmd.RuleReference to net.sourceforge.pmd.lang.rule.RuleReference
+ Renamed - net.sourceforge.pmd.ScopedLogHandlersManager to net.sourceforge.pmd.util.log.ScopedLogHandlersManager
+ Renamed - net.sourceforge.pmd.util.AntLogHandler to net.sourceforge.pmd.util.log.AntLogHandler
+ Renamed - net.sourceforge.pmd.util.ConsoleLogHandler to net.sourceforge.pmd.util.log.ConsoleLogHandler
+ Renamed - net.sourceforge.pmd.util.PmdLogFormatter to net.sourceforge.pmd.util.log.PmdLogFormatter
+
+ API Change - Changes to Rule/RuleSet/RuleSets
+ Removed - boolean Rule.include()
+ Removed - void Rule.setInclude(boolean)
+ Removed - String Rule.getRulePriorityName()
+ Removed - String Rule.getExample()
+ Removed - Rule.LOWEST_PRIORITY
+ Removed - Rule.PRIORITIES
+ Removed - Properties Rule.getProperties()
+ Removed - Rule.addProperties(Properties)
+ Removed - boolean Rule.hasProperty(String)
+ Removed - RuleSet.applies(Language,Language)
+ Removed - RuleSet.getLanguage()
+ Removed - RuleSet.setLanguage(Language)
+ Removed - RuleSets.applies(Language,Language)
+ Changed - void Rule.setPriority(int) to void Rule.setPriority(RulePriority)
+ Changed - int Rule.getPriority() to void RulePriority Rule.getPriority()
+ Changed - XXX Rule.getXXXProperty(String) to <T> Rule.getProperty(PropertyDescriptor<T>)
+ Changed - XXX Rule.getXXXProperty(PropertyDescriptor) to <T> Rule.getProperty(PropertyDescriptor<T>)
+ Changed - Rule.addProperty(String, String) to Rule.setProperty(PropertyDescriptor<T>, T)
+ Changed - Rule.setProperty(PropertyDescriptor, Object) to Rule.setProperty(PropertyDescriptor<T>, T)
+ Changed - Rule.setProperty(PropertyDescriptor, Object[]) to Rule.setProperty(PropertyDescriptor<T>, T)
+ Changed - Rule.propertyValuesByDescriptor() to Rule.getPropertiesByPropertyDescriptor()
+ Changed - PropertyDescriptor Rule.propertyDescriptorFor(String) to PropertyDescriptor Rule.getPropertyDescriptor(String)
+ Changed - boolean RuleSet.usesDFA() to boolean RuleSet.usesDFA(Language)
+ Changed - boolean RuleSet.usesTypeResolution() to boolean RuleSet.usesTypeResolution(Language)
+ Added - Rule.setLanguage(Language)
+ Added - Language Rule.getLanguage()
+ Added - Rule.setMinimumLanguageVersion(LanguageVersion)
+ Added - LanguageVersion Rule.getMinimumLanguageVersion()
+ Added - Rule.setMaximumLanguageVersion(LanguageVersion)
+ Added - LanguageVersion Rule.getMaximumLanguageVersion()
+ Added - Rule.setDeprecated(boolean)
+ Added - boolean Rule.isDeprecated()
+ Added - String Rule.dysfunctionReason();
+ Added - Rule.definePropertyDescriptor(PropertyDescriptor)
+ Added - List<PropertyDescriptor> Rule.getPropertyDescriptors()
+ Added - RuleSet.applies(Rule,LanguageVersion)
+
+ API Change - Changes to PMD class
+ Renamed - PMD.EXCLUDE_MARKER to PMD.SUPPRESS_MARKER
+ Removed - PMD.processFile(InputStream, RuleSet, RuleContext)
+ Removed - PMD.processFile(InputStream, String, RuleSet, RuleContext)
+ Removed - PMD.processFile(Reader, RuleSet, RuleContext)
+ Removed - PMD.processFile(Reader, RuleSets, RuleContext, LanguageVersion)
+ Moved - PMD.getExcludeMarker() to Configuration.getSuppressMarker()
+ Moved - PMD.setExcludeMarker(String) to Configuration.getSuppressMarker(String)
+ Moved - PMD.getClassLoader() to Configuration.getClassLoader()
+ Moved - PMD.setClassLoader(ClassLoader) to Configuration.getClassLoader(ClassLoader)
+ Moved - PMD.setDefaultLanguageVersion(LanguageVersion) to Configuration.setDefaultLanguageVersion(LanguageVersion)
+ Moved - PMD.setDefaultLanguageVersions(List<LanguageVersion>) to Configuration.setDefaultLanguageVersions(List<LanguageVersion>)
+ Moved - PMD.createClasspathClassLoader(String) to Configuration.createClasspathClassLoader(String)
+
+ API Change - Changes to Node interface
+ Renamed - Node.findChildrenOfType(Class) as Node.findDescendantsOfType(Class)
+ Renamed - Node.getFirstChildOfType(Class) as Node.getFirstDescendantOfType(Class)
+ Renamed - Node.containsChildOfType(Class) as Node.hasDescendantOfType(Class)
+ Renamed - Node.getAsXml() as Node.getAsDocument()
+ Added - Node.findChildrenOfType(Class), non recursive version
+ Added - Node.getFirstChildOfType(Class), non recursive version
+
+ API Change - Remove deprecated APIs
+ Removed - AccessNode.setXXX() methods, use AccessNode.setXXX(boolean) instead.
+ Removed - PMDException.getReason()
+ Removed - RuleSetFactory.createRuleSet(String,ClassLoader), use RuleSetFactory.setClassLoader(ClassLoader) and RuleSetFactory.createRuleSets(String) instead.
+ Removed - net.sourceforge.pmd.cpd.FileFinder use net.sourceforge.pmd.util.FileFinder instead.
+
+ API Change - RuleSetFactory
+ Added - RuleSetFactory.setClassLoader(ClassLoader)
+ Added - RuleSetFactory.createRuleSets(List<RuleSetReferenceId>)
+ Added - RuleSetFactory.createRuleSet(RuleSetReferenceId)
+ Added - RuleSetFactory.setClassLoader(ClassLoader)
+ Added - RuleSetReferenceId class to handle parsing of RuleSet strings, see RuleSetReferenceId.parse(String)
+ Renamed - RuleSetFactory.createSingleRuleSet(String) to RuleSetFactory.createRuleSet(String);
+ Removed - RuleSetFactory.createRuleSets(String, ClassLoader), use RuleSetFactory.createRuleSets(String) instead.
+ Removed - RuleSetFactory.createSingleRuleSet(String, ClassLoader), use RuleSetFactory.createSingleRuleSet(String) instead.
+ Removed - RuleSetFactory.createRuleSet(InputStream, ClassLoader), use RuleSetFactory.createRuleSet(RuleSetReferenceId) instead.
+ Removed - ExternalRuleID, use RuleSetReferenceId instead
+ Removed - SimpleRuleSetNameMapper, use RuleSetReferenceId instead
+
+ API Change - Changes to Renderer class, and Renderer implementations
+ Added - Renderer.getName()
+ Added - Renderer.setName(String)
+ Added - Renderer.getDescription()
+ Added - Renderer.setDescription(String)
+ Added - Renderer.getPropertyDefinitions()
+ Added - Renderer.isShowSuppressedViolations()
+ Added - AbstractAccumulatingRenderer
+ Removed - Renderer.render(Report)
+ Removed - Renderer.render(Report, Writer)
+ Renamed - Renderer.showSuppressedViolations(boolean) to Renderer.setShowSuppressedViolations(boolean)
+ Renamed - PapariTextRenderer to TextColorRenderer
+ Renamed - OntheFlyRenderer to AbstractIncrementingRenderer
+
+PMD command line changes:
+
+ Removed -lineprefix use -property linePrefix {value} instead
+ Removed -linkprefix use -property linkPrefix {value} instead
+ Removed -xslt use -property xsltFilename {value} instead
+ Removed -nojsp now obsolete
+ Removed -targetjdk use -version {name} {version} instead
+ Added -version {name} {version} to set language version to use for a given language
+ Added -property {name} {value} as generic way to pass properties to Renderers
+ Added -showsuppressed as a means to show suppressed rule violations (consistent with Ant task behavior)
+ Renamed 'nicehtml' report to 'xslt'
+ Renamed 'papari' report to 'textcolor'
+ Renamed -excludemarker option to -suppressmarker
+ Renamed -cpus option to -threads
+
+Ant changes:
+
+ Removed - <formatter> 'linkPrefix' attribute, use <param name="linkPrefix"> instead
+ Removed - <formatter> 'linePrefix' attribute, use <param name="linePrefix"> instead
+ Changed - <formatter> is optional - if not specified, falls back to "text" and console output.
+ Removed - <pmd> 'targetJDK' attribute to <version>lang version</version> instead
+ Added - <param name="name" value="value"/> as generic way to pass properties to Renderers on <formatter>
+ Renamed - <pmd> 'excludeMarker' attribute to 'suppressMarker'
+ Renamed - <pmd> 'cpus' attribute to 'threads'
+
+Maven changes:
+ The new maven coordinates are: net.sourceforge.pmd:pmd, e.g.
+ <dependency>
+ <groupId>net.sourceforge.pmd</groupId>
+ <artifactId>pmd</artifactId>
+ <version>5.0</version>
+ </dependency>
+
+New features:
+
+New Language 'ecmascript' added, for writing XPathRule and Java Rules against ECMAScript/JavaScript documents (must be standalone, not embedded in HTML). Many thanks to Rhino!
+New Language 'xml' added, for writing XPathRules against XML documents
+New Language 'xsl' added, as a derivative from XML.
+Rules can now define a 'violationSuppressRegex' property to universally suppress violations with messages matching the given regular expression
+Rules can now define a 'violationSuppressXPath' property to universally suppress violations on nodes which match the given relative XPath expression
+Rules are now directly associated with a corresponding Language, and a can also be associated with a specific Language Version range if desired.
+Rules can now be flagged with deprecated='true' in the RuleSet XML to allow the PMD Project to indicate a Rule (1) is scheduled for removal, (2) has been removed, or (3) has been renamed/moved.
+XPathRules can now query using XPath 2.0 with 'version=2.0"', or XPath 2.0 in XPath 1.0 compatibility mode using 'version="1.0 compatibility"'. Many thanks to Saxon!
+Rules can now use property values in messages, for example ${propertyName} will expand to the value of the 'propertyName' property on the Rule.
+Rules can now use violation specific values in messages, specifically ${variableName}, ${methodName}, ${className}, ${packageName}.
+New XPath function 'getCommentOn' can be used to search for strings in comments - Thanks to Andy Throgmorton
+
+CPD:
+Add .hxx and .hpp as valid file extension for CPD - Thanks to Ryan Pavlik
+Add options to to the CPD command line task - Thanks to Cd-Man
+Add C# support for CPD - thanks to Florian Bauer
+Fix small bug in Rule Designer UI
+Performance enhacement when parsing Javadoc (Patch ID: 3217201), thanks to Cd-Man
+Rework the XMLRenderer to use proper XML API and strictly uses the system value for encoding (Fix bug: 1435751)
+
+Other changes:
+Rule property API upgrades:
+ All numeric property descriptors can specify upper & lower limits
+ Newly functional Method & Type descriptors allow rule developers to incorporate/watch for individual methods or types
+ Better initialization error detection
+ Deprecated old string-keyed property API, will leave some methods behind for XPath rules however
+'41' and '42' shortcuts for rulesets added
+The default Java version processed by PMD is now uniformly Java 1.5.
+RuleViolations in Reports now uses List internally, and RuleViolationComparator is no longer broken
+TokenManager errors now include a file name whenever possible for every AST in PMD
+Added file encoding option to CPD GUI, which already existed for the command line and Ant
+AssignmentInOperand enhanced to catch assignment in 'for' condition, as well as use of increment/decrement operators. Customization properties added to allow assignment in if/while/for, or use of increment/decrement.
+Fix false positive on CastExpressions for UselessParentheses
+Fix false positive where StringBuffer.setLength(0) was using default constructor size of 16, instead of actual constructor size.
+Fix false negative for non-primitive types for VariableNamingConventions, also expanded scope to local and method/constructors, and enhanced customization options to choose between members/locals/parameters (all checked by default)
+Fix false negative for UseArraysAsList when the array was passed as method parameter - thanks to Andy Throgmorton
+Improve TooManyMethods rule - thanks to a patch from Riku Nykanen
+Improve DoNotCallSystemExit - thanks to a patch from Steven Christou
+Correct -benchmark reporting of Rule visits via the RuleChain
+Creating an Empty Code Ruleset and moved the following rules from Basic ruleset:
+ * Empty Code Rules
+ * EmptyCatchBlock
+ * EmptyIfStmt
+ * EmptyWhileStmt
+ * EmptyTryBlock
+ * EmptyFinallyBlock
+ * EmptySwitchStatements
+ * EmptySynchronizedBlock
+ * EmptyStatementNotInLoop
+ * EmptyInitializer
+ * EmptyStatementBlock
+ * EmptyStaticInitializer
+ Basic rulesets still includes a reference to those rules.
+Creating a unnecessary Code Ruleset and moved the following rules from Basic ruleset:
+ * UnnecessaryConversionTemporary
+ * UnnecessaryReturn
+ * UnnecessaryFinalModifier
+ * UselessOverridingMethod
+ * UselessOperationOnImmutable
+ * UnusedNullCheckInEquals
+ * UselessParentheses
+ Basic rulesets still includes a reference to those rules.
+
+Fixed bug 2920057 - Fixed False + on CloseResource
+Fixed bug 1808110 - Fixed performance issues on PreserveStackTrace
+Fixed bug 2832322 - cpd.xml file tag path attribute should be entity-encoded
+Fixed bug 2826119 - False +: DoubleCheckedLocking warning with volatile field
+Fixed bug 2835074 - False -: DoubleCheckedLocking with reversed null check
+Fixed bug 1932242 - EmptyMethodInAbstractClassShouldBeAbstract false +
+Fixed bug 1928009 - Error using migration ruleset in PMD 4.2
+Fixed bug 1808110 - PreserveStackTrace
+Fixed bug 1988829 - Violation reported without source file name (actually a fix to ConsecutiveLiteralAppends)
+Fixed bug 1989814 - false +: ConsecutiveLiteralAppends
+Fixed bug 1977230 - false positive: UselessOverridingMethod
+Fixed bug 1998185 - BeanMembersShouldSerialize vs @SuppressWarnings("serial")
+Fixed bug 2002722 - false + in UseStringBufferForStringAppends
+Fixed bug 2056318 - False positive for AvoidInstantiatingObjectsInLoops
+Fixed bug 1977438 - False positive for UselessStringValueOf
+Fixed bug 2050064 - False + SuspiciousOctalEscape with backslash literal
+Fixed bug 1556594 - Wonky detection of NullAssignment
+Fixed bug 1481051 - false + UnusedNullCheckInEquals (and other false positives too)
+Fixed bug 1943204 - Ant task: <ruleset> path should be relative to Ant basedir
+Fixed patch 2075906 - Add toString() to the rule UnnecessaryWrapperObjectCreation
+Fixed bug 2315623 - @SuppressWarnings("PMD.UseSingleton") has no effect
+Fixed bug 2230809 - False +: ClassWithOnlyPrivateConstructorsShouldBeFinal
+Fixed bug 2338341 - ArrayIndexOutOfBoundsException in CPD (on Ruby)
+Fixed bug 2315599 - False +: UseSingleton with class containing constructor
+Fixed bug 1955852 - false positives for UnusedPrivateMethod & UnusedLocalVariable
+Fixed bug 2404700 - UseSingleton should not act on enums
+Fixed bug - JUnitTestsShouldIncludeAssert now detects Junit 4 Assert.assert... constructs
+Fixed bug 1609038 - Xslt report generators break if path contains "java"
+Fixed bug 2142986 - UselessOverridingMethod doesn't consider annotations
+Fixed bug 2027626 - False + : AvoidFinalLocalVariable
+Fixed bug 2606609 - False "UnusedImports" positive in package-info.java
+Fixed bug 2645268 - ClassCastException in UselessOperationOnImmutable.getDeclaration
+Fixed bug 2724653 - AvoidThreadGroup reports false positives
+Fixed bug 2904832 - Type resolution not working for ASTType when using an inner class
+Fixed bug 1435751 - XML format does not support UTF-8
+Fixed bug 3303811 - Deadlink on "Similar projects" page
+Fixed bug 3017616 - Updated documentation regarding Netbeans plugin - thanks to Jesse Glick
+Fixed bug 3427563 - Deprecated class (android.util.config) - thanks to Lukas Reschke for the patch
+
+ruleset.dtd and ruleset_xml_schema.xsd added to jar file in rulesets directory
+bin and java14/bin scripts:
+ retroweaver version was not correct in java14/bin scripts
+ support for extra languages in cpd.sh
+ standard unix scripts can be used with cygwin
+Upgrading UselessOperationOnImmutable to detect more use cases, especially on String and fix false positives
+AvoidDuplicateLiteralRule now has 'skipAnnotations' boolean property
+Fixed false positive in UnusedImports: javadoc comments are parsed to check @see and other tags
+Fixed parsing bug: constant fields in annotation classes
+Bug fix: NPE in MoreThanOneLogger
+UnnecessaryParentheses now checks all expressions, not just return statements
+UnusedFormalParameter now reports violations on the parameter node, not the method/constructor node
+Updates to RuleChain to honor RuleSet exclude-pattern
+Optimizations and false positive fixes in PreserveStackTrace
+@SuppressWarnings("all") disables all warnings
+SingularField now checks for multiple fields in the same declaration
+Java grammar enhanced to include AnnotationMethodDeclaration as parent node of method related children of AnnotationTypeMemberDeclaration
+JavaCC generated artifacts updated to JavaCC 4.1.
+Dependencies updates: asm updated to 3.2
+Ant requirement is now 1.7.0 or higher for compilation
+ JUnit testing jar is packaged on 1.7.0+ only in ant binary distributions
+ Note that the ant task still works with 1.6.0 and higher
+All comment types are now stored in ASTCompilationUnit, not just formal ones
+Fixed false negative in UselessOverridingMethod
+Fixed handling of escape characters in UseIndexOfChar and AppendCharacterWithChar
+Fixed ClassCastException on generic method in BeanMembersShouldSerialize
+Fixed ClassCastException in symbol table code
+Support for Java 1.4 runtime dropped, PMD now requires Java 5 or higher. PMD can still process Java 1.4 source files.
+Support for Java 1.7
+Text renderer is now silent if there's no violation instead of displaying "No problems found!"
+RuleSet short names now require a language prefix, 'basic' is now 'java-basic', and 'rulesets/basic.xml' is now 'rulesets/java/basic.xml'
+The JSP RuleSets are now in the 'jsp' language, and are 'jsp-basic', 'jsp-basic-jsf', 'rulesets/jsp/basic.xml' and 'rulesets/jsp/basic-jsp.xml'
+Enhanced logging in the ClassTypeResolver to provide more detailed messaging.
+AvoidUsingHardCodedIP modified to not use InetAddress.getByName(String), instead does better pattern analysis.
+The JSP/JSF parser can now parse Unicode input.
+The JSP/JSP parser can now handle <script>...</script> tags. The AST HtmlScript node contains the content.
+Added Ecmascript as a supported language for CPD.
+The RuleSet XML Schema namespace is now: http://pmd.sourceforge.net/ruleset/2.0.0
+The RuleSet XML Schema is located in the source at: etc/ruleset_2_0_0.xsd
+The RuleSet DTD is located in the source at: etc/ruleset_2_0_0.dtd
+Improved include/exclude pattern matching performance for ends-with type patterns.
+Modify (and hopefully fixed) CPD algorithm thanks to a patch from Juan Jesús García de Soria.
+Fixed character reference in xml report - thanks to Seko
+Enhanced SuspiciousEqualsMethodName rule - thanks to Andy Throgmorton
+Add a script to launch CPDGUI on Unix system - thanks to Tom Wheeler
+
+New Java rules:
+
+ Basic ruleset: ExtendsObject,CheckSkipResult,AvoidBranchingStatementAsLastInLoop,DontCallThreadRun,DontUseFloatTypeForLoopIndices
+ Controversial ruleset: AvoidLiteralsInIfCondition, AvoidPrefixingMethodParameters, OneDeclarationPerLine, UseConcurrentHashMap
+ Coupling ruleset: LoosePackageCoupling,LawofDemeter
+ Design ruleset: LogicInversion,UseVarargs,FieldDeclarationsShouldBeAtStartOfClass,GodClass
+ Empty ruleset: EmptyInitializer,EmptyStatementBlock
+ Import ruleset: UnnecessaryFullyQualifiedName
+ Optimization ruleset: RedundantFieldInitializer
+ Naming ruleset: ShortClassName, GenericsNaming
+ StrictException ruleset: AvoidThrowingNewInstanceOfSameException, AvoidCatchingGenericException, AvoidLosingExceptionInformation
+ Unnecessary ruleset: UselessParentheses
+ JUnit ruleset: JUnitTestContainsTooManyAsserts, UseAssertTrueInsteadOfAssertEquals
+ Logging with Jakarta Commons ruleset: GuardDebugLogging
+
+New Java ruleset:
+ android.xml: new rules specific to the Android platform
+
+New JSP rules:
+ Basic ruleset: NoInlineScript
+
+New ECMAScript rules:
+ Basic ruleset: AssignmentInOperand,ConsistentReturn,InnaccurateNumericLiteral,ScopeForInVariable,UnreachableCode,EqualComparison,GlobalVariable
+ Braces ruleset: ForLoopsMustUseBraces,IfStmtsMustUseBraces,IfElseStmtsMustUseBraces,WhileLoopsMustUseBraces
+ Unnecessary ruleset: UnnecessaryParentheses,UnnecessaryBlock
+
+New XML rules:
+ Basic ruleset: MistypedCDATASection
+
Add support for Java 7 grammer - thanks to Dinesh Bolkensteyn and SonarSource
+Add options --ignore-literals and --ignore-identifiers to the CPD command line task, thanks to Cd-Man
+Fixed character reference in xml report - thanks to Seko
+Add C# support for CPD - thanks to Florian Bauer
+Fix small bug in Rule Designer UI
+Improve TooManyMethods rule - thanks to a patch from Riku Nykanen
+Improve DoNotCallSystemExit - thanks to a patch from Steven Christou
+Fix false negative for UseArraysAsList when the array was passed as method parameter - thanks to Andy Throgmorton
+Enhanced SuspiciousEqualsMethodName rule - thanks to Andy Throgmorton
+Add a script to launch CPDGUI on Unix system - thanks to Tom Wheeler
+
+New Rule:
+ Basic ruleset: DontCallThreadRun - thanks to Andy Throgmorton
+ Logging with Jakarta Commons ruleset: GuardDebugLogging
+
Fixed bug 2920057 - False + : CloseRessource whith an external getter
+Fixed bug 1808110 - Fixed performance issue on PreserveStackTrace
+Fixed bug 2832322 - cpd.xml file tag path attribute should be entity-encoded
+Fixed bug 2590258 - NPE with nicerhtml output
+Fixed bug 2317099 - False + in SimplifyCondition
+Fixed bug 2606609 - False "UnusedImports" positive in package-info.java
+Fixed bug 2645268 - ClassCastException in UselessOperationOnImmutable.getDeclaration
+Fixed bug 2724653 - AvoidThreadGroup reports false positives
+Fixed bug 2835074 - False -: DoubleCheckedLocking with reversed null check
+Fixed bug 2826119 - False +: DoubleCheckedLocking warning with volatile field
+Fixed bug 2904832 - Type resolution not working for ASTType when using an inner class
+
+Modify (and hopefully fixed) CPD algorithm thanks to a patch from Juan Jesús García de Soria.
+Correct -benchmark reporting of Rule visits via the RuleChain
+Fix issue with Type Resolution incorrectly handling of Classes with same name as a java.lang Class.
+The JSP/JSF parser can now parse Unicode input.
+The JSP/JSP parser can now handle <script>...</script> tags. The AST HtmlScript node contains the content.
+Added Ecmascript as a supported language for CPD.
+Improved include/exclude pattern matching performance for ends-with type patterns.
+
+Dependencies updates: asm updated to 3.2
+
+Android ruleset: CallSuperLast rule now also checks for finish() redefinitions
+
+New rule:
+ Android: DoNotHardCodeSDCard
+ Controversial : AvoidLiteralsInIfCondition (patch 2591627), UseConcurrentHashMap
+ StrictExceptions : AvoidCatchingGenericException, AvoidLosingExceptionInformation
+ Naming : GenericsNaming
+ JSP: NoInlineScript
+
Enhanced logging in the ClassTypeResolver to provide more detailed messaging.
+Fixed bug 2315623 - @SuppressWarnings("PMD.UseSingleton") has no effect
+Fixed bug 2230809 - False +: ClassWithOnlyPrivateConstructorsShouldBeFinal
+Fixed bug 2338341 - ArrayIndexOutOfBoundsException in CPD (on Ruby)
+Fixed bug 2315599 - False +: UseSingleton with class containing constructor
+Fixed bug 1955852 - false positives for UnusedPrivateMethod & UnusedLocalVariable
+Fixed bug 2404700 - UseSingleton should not act on enums
+Fixed bug 2225474 - VariableNamingConventions does not work with nonprimitives
+Fixed bug 1609038 - Xslt report generators break if path contains "java"
+Fixed bug - JUnitTestsShouldIncludeAssert now detects Junit 4 Assert.assert... constructs
+Fixed bug 2142986 - UselessOverridingMethod doesn't consider annotations
+Fixed bug 2027626 - False + : AvoidFinalLocalVariable
+
+New rule:
+ StrictExceptions : AvoidThrowingNewInstanceOfSameException
+New ruleset:
+ android.xml: new rules specific to the Android platform
+
Fixed bug 1481051 - false + UnusedNullCheckInEquals (and other false positives too)
+Fixed bug 1943204 - Ant task: <ruleset> path should be relative to Ant basedir
+Fixed bug 2139720 - Exception in PMD Rule Designer for inline comments in source
+Fixed patch 2075906 - Add toString() to the rule UnnecessaryWrapperObjectCreation
+Fixed ClassCastException on generic method in BeanMembersShouldSerialize
+Fixed ClassCastException in symbol table code
+
JavaCC generated artifacts updated to JavaCC 4.1d1.
+Java grammar enhanced to include AnnotationMethodDeclaration as parent node of method related children of AnnotationTypeMemberDeclaration
+Fixes for exclude-pattern
+Updates to RuleChain to honor RuleSet exclude-pattern
+Upgrading UselessOperationOnImmutable to detect more use cases, especially on String and fix false positives
+Fixed bug 1988829 - Violation reported without source file name (actually a fix to ConsecutiveLiteralAppends)
+Fixed bug 1989814 - false +: ConsecutiveLiteralAppends
+Fixed bug 1977230 - false positive: UselessOverridingMethod
+Fixed bug 1998185 - BeanMembersShouldSerialize vs @SuppressWarnings("serial")
+Fixed bug 2002722 - false + in UseStringBufferForStringAppends
+Fixed bug 2056318 - False positive for AvoidInstantiatingObjectsInLoops
+Fixed bug 1977438 - False positive for UselessStringValueOf
+Fixed bug 2050064 - False + SuspiciousOctalEscape with backslash literal
+Fixed bug 1556594 - Wonky detection of NullAssignment
+Optimizations and false positive fixes in PreserveStackTrace
+@SuppressWarnings("all") disables all warnings
+All comment types are now stored in ASTCompilationUnit, not just formal ones
+Fixed false negative in UselessOverridingMethod
+Fixed handling of escape characters in UseIndexOfChar and AppendCharacterWithChar
+
+New rule:
+ Basic ruleset: EmptyInitializer
+
Fixed false positive in UnusedImports: javadoc comments are parsed to check @see and other tags
+Fixed parsing bug: constant fields in annotation classes
+Bug fix: NPE in MoreThanOneLogger
+UnnecessaryParentheses now checks all expressions, not just return statements
+
'41' and '42' shortcuts for rulesets added
+Fixed bug 1928009 - Error using migration ruleset in PMD 4.2
+Fixed bug 1932242 - EmptyMethodInAbstractClassShouldBeAbstract false +
+Fixed bug 1808110 - PreserveStackTrace
+
+AvoidDuplicateLiteralRule now has 'skipAnnotations' boolean property
+ruleset.dtd and ruleset_xml_schema.xsd added to jar file in rulesets directory
+Update RuleSetWriter to handle non-Apache TRAX implementations, add an option to not use XML Namespaces
+Added file encoding option to CPD GUI, which already existed for the command line and Ant
+bin and java14/bin scripts:
+ retroweaver version was not correct in java14/bin scripts
+ support for extra languages in cpd.sh
+ standard unix scripts can be used with cygwin
+
Fixed bug 1920155 - CheckResultSet: Does not pass for loop conditionals
+
Fixed bug 1912831 - False + UnusedPrivateMethod with varargs
+Fixed bug 1913536 - Rule Designer does not recognize JSP(XML)
+Add -auxclasspath option for specifying Type Resolution classpath from command line and auxclasspath nested element for ant task.
+Fixed formatting problems in loggers.
+
+Ant task upgrade:
+ Added a new attribute 'maxRuleCount' to indicate whether or not to fail the build if PMD finds that much violations.
+
Fixed bug 1866198 - PMD should not register global Logger
+Fixed bug 1843273 - False - on SimplifyBooleanReturns
+Fixed bug 1848888 - Fixed false positive in UseEqualsToCompareStrings
+Fixed bug 1874313 - Documentation bugs
+Fixed bug 1855409 - False + in EmptyMethodInAbstractClassShouldBeAbstract
+Fixed bug 1888967 - Updated xpath query to detect more "empty" methods.
+Fixed bug 1891399 - Check for JUnit4 test method fails
+Fixed bug 1894821 - False - for Test Class without Test Cases
+Fixed bug 1882457 - PositionLiteralsFirstInComparisons rule not working OK
+Fixed bug 1842505 - XML output incorrect for inner classes
+Fixed bug 1808158 - Constructor args could also be final
+Fixed bug 1902351 - AvoidReassigningParameters not identify parent field
+Fixed other false positives in EmptyMethodInAbstractClassShouldBeAbstract
+Fixed other issues in SimplifyBooleanReturns
+Modified AvoidReassigningParameter to also check constructor arguments for reassignement
+
+New rules:
+ Basic ruleset: AvoidMultipleUnaryOperators
+ Controversial ruleset: DoNotCallGarbageCollectionExplicitly,UseObjectForClearerAPI
+ Design ruleset : ReturnEmptyArrayRatherThanNull,TooFewBranchesForASwitchStatement,AbstractClassWithoutAnyMethod
+ Codesize : TooManyMethods
+ StrictExceptions : DoNotThrowExceptionInFinally
+ Strings : AvoidStringBufferField
+
+Rule upgrade:
+ CyclomaticComplexity now can be configured to display only class average complexity or method complexity, or both.
+
+Designer upgrade:
+ A new panel for symbols and a tooltips on AST node that displays line, column and access node attributes (private,
+ static, abstract,...)
+
+1.7 added as a valid option for targetjdk.
+New elements under <ruleset>: <exclude-pattern> to match files exclude from processing, with <include-pattern> to override.
+Rules can now be written which produce violations based upon aggregate file processing (i.e. cross/multiple file violations).
+PMD Rule Designer can now shows Symbol Table contents for the selected AST node.
+PMD Rule Designer shows position info in tooltip for AST nodes and highlights matching code for selected AST node in code window.
+CPD Ant task will report to System.out when 'outputFile' not given.
+RuleSetWriter class can be used to Serialize a RuleSet to XML in a standard fashion. Recommend PMD IDE plugins standardize their behavior.
+retroweaver updated to version 2.0.5.
+
Fixed annotation bug: ClassCastException when a formal parameter had multiple annotations
+Added a Visual Studio renderer for CPD; just use "--format vs".
+Dependencies updates: asm to 3.1, retroweaver to 2.0.2, junit to 4.4
+new ant target ("regress") to test regression bugs only
+
New rules:
+ Basic ruleset: AvoidUsingHardCodedIP,CheckResultSet
+ Controversial ruleset: AvoidFinalLocalVariable,AvoidUsingShortType,AvoidUsingVolatile,AvoidUsingNativeCode,AvoidAccessibilityAlteration
+ Design ruleset: ClassWithOnlyPrivateConstructorsShouldBeFinal,EmptyMethodInAbstractClassShouldBeAbstract
+ Imports ruleset: TooManyStaticImports
+ J2ee ruleset: DoNotCallSystemExit, StaticEJBFieldShouldBeFinal,DoNotUseThreads
+ Strings ruleset: UseEqualsToCompareStrings
+
+Fixed bug 674394 - fixed false positive in DuplicateImports for disambiguation import
+Fixed bug 631681 - fixed false positive in UnusedPrivateField when field is accessed by outer class
+Fixed bug 985989 - fixed false negative in ConstructorCallsOverridableMethod for inner static classes
+Fixed bug 1409944 - fixed false positive in SingularField for lock objects
+Fixed bug 1472195 - fixed false positives in PositionLiteralsFirstInComparisons when the string is used as a parameter
+Fixed bug 1522517 - fixed false positive in UselessOverridingMethod for clone method
+Fixed bug 1744065 - fixed false positive in BooleanInstantiation when a custom Boolean is used
+Fixed bug 1765613 - fixed NullPointerException in CloneMethodMustImplementCloneable when checking enum
+Fixed bug 1740480 - fixed false positive in ImmutableField when the assignment is inside an 'if'
+Fixed bug 1702782 - fixed false positive in UselessOperationOnImmutable when an Immutable on which an operation is performed is compareTo'd
+Fixed bugs 1764288/1744069/1744071 - When using Type Resolution all junit test cases will notice if you're using an extended TestCase
+Fixed bug 1793215 - pmd-nicerhtml.xsl does not display line numbers
+Fixes bug 1796928 - fixed false positive in AvoidThrowingRawExceptionTypes, when a Type name is the same as a RawException.
+Fixed bug 1811506 - False - : UnusedFormalParameter (property "checkall" needs to be set)
+Fixed false negative in UnnecessaryCaseChange
+
+The Java 1.5 source code parser is now the default for testcode used in PMD's unit tests.
+Added TypeResolution to the XPath rule. Use typeof function to determine if a node is of a particular type
+Adding a GenericLiteralChecker, a generic rule that require a regex as property. It will log a violation if a Literal is matched by the regex. See the new rule AvoidUsingHardCodedIP for an example.
+Adding support for multiple line span String in CPD's AbstractTokenizer, this may change, for the better, CPD's Ruby parsing.
+This release adds 'nicehtml', with the plan for the next major release to make nicehtml->html, and html->oldhtml. This feature uses an XSLT transformation, default stylesheet maybe override with '-xslt filename'.
+New CPD command line feature : Using more than one directory for sources. You can now have several '--files' on the command line.
+SingularField greatly improved to generate very few false positives (none?). Moved from controversial to design. Two options added to restore old behaviour (mostly).
+Jaxen updated to 1.1.1, now Literal[@Image='""'] works in XPath expressions.
+
Fixed bug 1697397 - fixed false positives in ClassCastExceptionWithToArray
+Fixed bug 1728789 - removed redundant rule AvoidNonConstructorMethodsWithClassName; MethodWithSameNameAsEnclosingClass is faster and does the same thing.
+
New rules:
+ Typeresolution ruleset: SignatureDeclareThrowsException - re-implementation using the new Type Resolution facility (old rule is still available)
+Fixed bug 1698550 - CloneMethodMustImplementCloneable now accepts a clone method that throws CloneNotSupportedException in a final class
+Fixed bug 1680568 - The new typeresolution SignatureDeclareThrowsException rule now ignores setUp and tearDown in JUnit 4 tests and tests that do not directly extend TestCase
+The new typeresolution SignatureDeclareThrowsException rule can now ignore JUnit classes completely by setting the IgnoreJUnitCompletely property
+Fixed false positive in UselessOperationOnImmutable
+PMD now defaults to using a Java 1.5 source code parser.
+
New rules:
+ Strict exception ruleset: DoNotExtendJavaLangError
+ Basic JSP ruleset: JspEncoding
+ J2EE ruleset: MDBAndSessionBeanNamingConvention, RemoteSessionInterfaceNamingConvention, LocalInterfaceSessionNamingConvention, LocalHomeNamingConvention, RemoteInterfaceNamingConvention
+ Optimizations ruleset: AddEmptyString
+ Naming: BooleanGetMethodName
+New rulesets:
+ Migrating To JUnit4: Rules that help move from JUnit 3 to JUnit 4
+Fixed bug 1670717 - 'Copy xml to clipboard' menu command now works again in the Designer
+Fixed bug 1618858 - PMD no longer raises an exception on XPath like '//ConditionalExpression//ConditionalExpression'
+Fixed bug 1626232 - Commons logging rules (ProperLogger and UseCorrectExceptionLogging) now catch more cases
+Fixed bugs 1626201 & 1633683 - BrokenNullCheck now catches more cases
+Fixed bug 1626715 - UseAssertSameInsteadOfAssertTrue now correctly checks classes which contain the null constant
+Fixed bug 1531216 - ImmutableField. NameOccurrence.isSelfAssignment now recognizes this.x++ as a self assignment
+Fixed bug 1634078 - StringToString now recognizes toString on a String Array, rather than an element.
+Fixed bug 1631646 - UselessOperationOnImmutable doesn't throw on variable.method().variable.
+Fixed bug 1627830 - UseLocaleWithCaseConversions now works with compound string operations
+Fixed bug 1613807 - DontImportJavaLang rule allows import to Thread inner classes
+Fixed bug 1637573 - The PMD Ant task no longer closes System.out if toConsole is set
+Fixed bug 1451251 - A new UnusedImports rule, using typeresolution, finds unused import on demand rules
+Fixed bug 1613793 - MissingSerialVersionUID rule now doesn't fire on abstract classes
+Fixed bug 1666646 - ImmutableField rule doesn't report against volatile variables
+Fixed bug 1693924 - Type resolution now works for implicit imports
+Fixed bug 1705716 - Annotation declarations now trigger a new scope level in the symbol table.
+Fixed bug 1743938 - False +: InsufficientStringBufferDeclaration with multiply
+Fixed bug 1657957 - UseStringBufferForStringAppends now catches self-assignments
+Applied patch 1612455 - RFE 1411022 CompareObjectsWithEquals now catches the case where comparison is against new Object
+Implemented RFE 1562230 - Added migration rule to check for instantiation of Short/Byte/Long
+Implemented RFE 1627581 - SuppressWarnings("unused") now suppresses all warnings in unusedcode.xml
+XPath rules are now chained together for an extra speedup in processing
+PMD now requires JDK 1.5 to be compiled. Java 1.4 support is provided using Retroweaver
+- PMD will still analyze code from earlier JDKs
+- to run pmd with 1.4, use the files from the java14 directory (weaved pmd jar and support files)
+TypeResolution now looks at some ASTName nodes.
+Memory footprint reduced: most renderers now use less memory by generating reports on the fly.
+Ant task now takes advantage of multithreading code and on the fly renderers
+Ant task now logs more debug info when using -verbose
+PMD command line now has -benchmark: output a benchmark report upon completion; default to System.err
+
New rules:
+ Basic ruleset: BigIntegerInstantiation, AvoidUsingOctalValues
+ Codesize ruleset: NPathComplexity, NcssTypeCount, NcssMethodCount, NcssConstructorCount
+ Design ruleset: UseCollectionIsEmpty
+ Strings ruleset: StringBufferInstantiationWithChar
+ Typeresolution ruleset: Loose Coupling - This is a re-implementation using the new Type Resolution facility
+Fixed bug 1610730 - MisplacedNullCheck now catches more cases
+Fixed bug 1570915 - AvoidRethrowingException no longer reports a false positive for certain nested exceptions.
+Fixed bug 1571324 - UselessStringValueOf no longer reports a false positive for additive expressions.
+Fixed bug 1573795 - PreserveStackTrace doesn't throw CastClassException on exception with 0 args
+Fixed bug 1573591 - NonThreadSafeSingleton doesn't throw NPE when using this keyword
+Fixed bug 1371753 - UnnecessaryLocalBeforeReturn is now less aggressive in its reporting.
+Fixed bug 1566547 - Annotations with an empty MemberValueArrayInitializer are now parsed properly.
+Fixed bugs 1060761 / 1433119 & RFE 1196954 - CloseResource now takes an optional parameter to identify closure methods
+Fixed bug 1579615 - OverrideBothEqualsAndHashcode no longer throws an Exception on equals methods that don't have Object as a parameter type.
+Fixed bug 1580859 - AvoidDecimalLiteralsInBigDecimalConstructor now catches more cases.
+Fixed bug 1581123 - False +: UnnecessaryWrapperObjectCreation.
+Fixed bug 1592710 - VariableNamingConventions no longer reports false positives on certain enum declarations.
+Fixed bug 1593292 - The CPD GUI now works with the 'by extension' option selected.
+Fixed bug 1560944 - CPD now skips symlinks.
+Fixed bug 1570824 - HTML reports generated on Windows no longer contain double backslashes. This caused problems when viewing those reports with Apache.
+Fixed bug 1031966 - Re-Implemented CloneMethodMustImplementCloneable as a typeresolution rule. This rule can now detect super classes/interfaces which are cloneable
+Fixed bug 1571309 - Optional command line options may be used either before or after the mandatory arguments
+Applied patch 1551189 - SingularField false + for initialization blocks
+Applied patch 1573981 - false + in CloneMethodMustImplementCloneable
+Applied patch 1574988 - false + in OverrideBothEqualsAndHashcode
+Applied patch 1583167 - Better test code management. Internal JUnits can now be written in XML's
+Applied patch 1613674 - Support classpaths with spaces in pmd.bat
+Applied patch 1615519 - controversial/DefaultPackage XPath rule is wrong
+Applied patch 1615546 - Added option to command line to write directly to a file
+Implemented RFE 1566313 - Command Line now takes minimumpriority attribute to filter out rulesets
+PMD now requires JDK 1.4 to run
+- PMD will still analyze code from earlier JDKs
+- PMD now uses the built-in JDK 1.4 regex utils vs Jakarta ORO
+- PMD now uses the JDK javax.xml APIs rather than being hardcoded to use Xerces and Xalan
+SummaryHTML Report changes from Brent Fisher - now contains linePrefix to support source output from javadoc using "linksource"
+Fixed CSVRenderer - had flipped line and priority columns
+Fixed bug in Ant task - CSV reports were being output as text.
+Fixed false negatives in UseArraysAsList.
+Fixed several JDK 1.5 parsing bugs.
+Fixed several rules (exceptions on jdk 1.5 and jdk 1.6 source code).
+Fixed array handling in AvoidReassigningParameters and UnusedFormalParameter.
+Fixed bug in UselessOverridingMethod: false + when adding synchronization.
+Fixed false positives in LocalVariableCouldBeFinal.
+Fixed false positives in MethodArgumentCouldBeFinal.
+Modified annotation suppression to use @SuppressWarning("PMD") to suppress all warnings and @SuppressWarning("PMD.UnusedLocalVariable") to suppress a particular rule's warnings.
+Rules can now call RuleContext.getSourceType() if they need to make different checks on JDK 1.4 and 1.5 code.
+CloseResource rule now checks code without java.sql import.
+ArrayIsStoredDirectly rule now checks Constructors
+undo/redo added to text areas in Designer.
+Better 'create rule XML' panel in Designer.
+use of entrySet to iterate over Maps.
+1.6 added as a valid option for targetjdk.
+PMD now allows rules to use Type Resolution. This was referenced in patch 1257259.
+Renderers use less memory when generating reports.
+New DynamicXPathRule class to speed up XPath based rules by providing a base type for the XPath expression.
+Multithreaded processing on multi core or multi cpu systems.
+Performance Refactoring, XPath rules re-written as Java:
+ AssignmentInOperand
+ AvoidDollarSigns
+ DontImportJavaLang
+ DontImportSun
+ MoreThanOneLogger
+ SuspiciousHashcodeMethodName
+ UselessStringValueOf
+
New rules:
+ Basic ruleset: BrokenNullCheck
+ Strict exceptions ruleset: AvoidRethrowingException
+ Optimizations ruleset: UnnecessaryWrapperObjectCreation
+ Strings ruleset: UselessStringValueOf
+Fixed bug 1498910 - AssignmentInOperand no longer has a typo in the message.
+Fixed bug 1498960 - DontImportJavaLang no longer reports static imports of java.lang members.
+Fixed bug 1417106 - MissingBreakInSwitch no longer flags stmts where every case has either a return or a throw.
+Fixed bug 1412529 - UncommentedEmptyConstructor no longer flags private constructors.
+Fixed bug 1462189 - InsufficientStringBufferDeclaration now resets when it reaches setLength the same way it does at a Constructor
+Fixed bug 1497815 - InsufficientStringBufferDeclaration rule now takes the length of the constructor into account, and adds the length of the initial string to its initial length
+Fixed bug 1504842 - ExceptionSignatureDeclaration no longer flags methods starting with 'test'.
+Fixed bug 1516728 - UselessOverridingMethod no longer raises an NPE on methods that use generics.
+Fixed bug 1522054 - BooleanInstantiation now detects instantiations inside method calls.
+Fixed bug 1522056 - UseStringBufferForStringAppends now flags appends which occur in static initializers and constructors
+Fixed bug 1526530 - SingularField now finds fields which are hidden at the method or static level
+Fixed bug 1529805 - UnusedModifier no longer throws NPEs on JDK 1.5 enums.
+Fixed bug 1531593 - UnnecessaryConversionTemporary no longer reports false positives when toString() is invoked inside the call to 'new Long/Integer/etc()'.
+Fixed bug 1512871 - Improved C++ tokenizer error messages - now they include the filename.
+Fixed bug 1531152 - CloneThrowsCloneNotSupportedException now reports the proper line number.
+Fixed bug 1531236 - IdempotentOperations reports fewer false positives.
+Fixed bug 1544564 - LooseCoupling rule now checks for ArrayLists
+Fixed bug 1544565 - NonThreadSafeSingleton now finds if's with compound statements
+Fixed bug 1561784 - AbstractOptimizationRule no longer throws ClassCastExceptions on certain postfix expressions.
+Fixed a bug in AvoidProtectedFieldInFinalClass - it no longer reports false positives for protected fields in inner classes.
+Fixed a bug in the C++ grammar - the tokenizer now properly recognizes macro definitions which are followed by a multiline comment.
+Modified C++ tokenizer to use the JavaCC STATIC option; this results in about a 30% speedup in tokenizing.
+Implemented RFE 1501850 - UnusedFormalParameter now catches cases where a parameter is assigned to but not used.
+Applied patch 1481024 (implementing RFE 1490181)- NOPMD messages can now be reported with a user specified msg, e.g., //NOPMD - this is expected
+Added JSP support to the copy/paste detector.
+Placed JSF/JSP ruleset names in rulesets/jsprulesets.properties
+Added the image to the ASTEnumConstant nodes.
+Added new XSLT stylesheet for CPD XML->HTML from Max Tardiveau.
+Refactored UseIndexOfChar to extract common functionality into AbstractPoorMethodCall.
+Improved CPD GUI and Designer look/functionality; thanks to Brian Remedios for the changes!
+Rewrote the NOPMD mechanism to collect NOPMD markers as the source file is tokenized. This eliminates an entire scan of each source file.
+Applied patch from Jason Bennett to enhance CyclomaticComplexity rule to account for conditional or/and nodes, do stmts, and catch blocks.
+Applied patch from Xavier Le Vourch to reduce false postives from CloneMethodMustImplementCloneable.
+Updated Jaxen library to beta 10.
+Performance Refactoring, XPath rules re-written as Java:
+ BooleanInstantiation
+ UselessOperationOnImmutable
+ OverrideBothEqualsAndHashcode
+ UnnecessaryReturn
+ UseStringBufferForStringAppends
+ SingularField
+ NonThreadSafeSingleton
+
New rules:
+ Basic-JSP ruleset: DuplicateJspImport
+ Design ruleset: PreserveStackTrace
+ J2EE ruleset: UseProperClassLoader
+Implemented RFE 1462019 - Add JSPs to Ant Task
+Implemented RFE 1462020 - Add JSPs to Designer
+Fixed bug 1461426 InsufficientStringBufferDeclaration does not consider paths
+Fixed bug 1462184 False +: InsufficientStringBufferDeclaration - wrong size
+Fixed bug 1465574 - UnusedPrivateMethod no longer reports false positives when a private method is called from a method with a parameter of the same name.
+Fixed bug 1114003 - UnusedPrivateMethod no longer reports false positives when two methods have the same name and number of arguments but different types. The fix causes PMD to miss a few valid cases, but, c'est la vie.
+Fixed bug 1472843 - UnusedPrivateMethod no longer reports false positives when a private method is only called from a method that contains a variable with the same name as that method.
+Fixed bug 1461442 - UseAssertSameInsteadOfAssertTrue now ignores comparisons to null; UseAssertNullInsteadOfAssertTrue will report those.
+Fixed bug 1474778 - UnnecessaryCaseChange no longer flags usages of toUpperCase(Locale).
+Fixed bug 1423429 - ImmutableField no longer reports false positives on variables which can be set via an anonymous inner class that is created in the constructor.
+Fixed major bug in CPD; it was not picking up files other than .java or .jsp.
+Fixed a bug in CallSuperInConstructor; it now checks inner classes/enums more carefully.
+Fixed a bug in VariableNamingConventions; it was not setting the warning message properly.
+Fixed bug in C/C++ parser; a '$' is now allowed in an identifier. This is useful in VMS.
+Fixed a symbol table bug; PMD no longer crashes on enumeration declarations in the same scope containing the same field name
+Fixed a bug in ASTVariableDeclaratorId that triggered a ClassCastException if a annotation was used on a parameter.
+Added RuleViolation.getBeginColumn()/getEndColumn()
+Added an optional 'showSuppressed' item to the Ant task; this is false by default and toggles whether or not suppressed items are shown in the report.
+Added an IRuleViolation interface and modified various code classes (include Renderer implementations and Report) to use it.
+Modified JJTree grammar to use conditional node descriptors for various expression nodes and to use node suppression for ASTModifier nodes; this replaces a bunch of DiscardableNodeCleaner hackery. It also fixed bug 1445026.
+Modified C/CPP grammar to only build the lexical analyzer; we're not using the parser for CPD, just the token manager. This reduces the PMD jar file size by about 50 KB.
+
New rules:
+ Basic ruleset: AvoidThreadGroup
+ Design ruleset: UnsynchronizedStaticDateFormatter
+ Strings ruleset: InefficientEmptyStringCheck, InsufficientStringBufferDeclaration
+ JUnit ruleset: SimplifyBooleanAssertion
+ Basic-JSF ruleset: DontNestJsfInJstlIteration
+ Basic-JSP ruleset: NoLongScripts, NoScriptlets, NoInlineStyleInformation, NoClassAttribute, NoJspForward, IframeMissingSrcAttribute, NoHtmlComments
+Fixed bug 1414985 - ConsecutiveLiteralAppends now checks for intervening references between appends.
+Fixed bug 1418424 - ConsecutiveLiteralAppends no longer flags appends in separate methods.
+Fixed bug 1416167 - AppendCharacterWithChar now catches cases involving escaped characters.
+Fixed bug 1421409 - Ant task now has setter to allow minimumPriority attribute to be used.
+Fixed bug 1416164 - InefficientStringBuffering no longer reports false positives on the three argument version of StringBuffer.append().
+Fixed bug 1415326 - JUnitTestsShouldContainAsserts no longer errors out on JDK 1.5 generics.
+Fixed bug 1415333 - CyclomaticComplexity no longer errors out on JDK 1.5 enums.
+Fixed bug 1415663 - PMD no longer fails to parse abstract classes declared in a method.
+Fixed bug 1433439 - UseIndexOfChar no longer reports false positives on case like indexOf('a' + getFoo()).
+Fixed bug 1435218 - LoggerIsNotStaticFinal no longer reports false positives for local variables.
+Fixed bug 1413745 - ArrayIsStoredDirectly no longer reports false positives for array deferences.
+Fixed bug 1435751 - Added encoding type of UTF-8 to the CPD XML file.
+Fixed bug 1441539 - ConsecutiveLiteralAppends no longer flags appends() involving method calls.
+Fixed bug 1339470 - PMD no longer fails to parse certain non-static initializers.
+Fixed bug 1425772 - PMD no longer fails with errors in ASTFieldDeclaration when parsing some JDK 1.5 code.
+Fixed bugs 1448123 and 1449175 - AvoidFieldNameMatchingTypeName, SingularField, TooManyFields, and AvoidFieldNameMatchingMethodName no longer error out on enumerations.
+Fixed bug 1444654 - migrating_to_14 and migrating_to_15 no longer refer to rule tests.
+Fixed bug 1445231 - TestClassWithoutTestCases: no longer flags abstract classes.
+Fixed bug 1445765 - PMD no longer uses huge amounts of memory. However, you need to use RuleViolation.getBeginLine(); RuleViolation.getNode() is no more.
+Fixed bug 1447295 - UseNotifyAllInsteadOfNotify no longer flags notify() methods that have a parameter.
+Fixed bug 1455965 - MethodReturnsInternalArray no longer flags variations on 'return new Object[] {}'.
+Implemented RFE 1415487 - Added a rulesets/releases/35.xml ruleset (and similar rulesets for previous releases) contains rules new to PMD v3.5
+Wouter Zelle fixed a false positive in NonThreadSafeSingleton.
+Wouter Zelle fixed a false positive in InefficientStringBuffering.
+The CPD Ant task now supports an optional 'language' attribute.
+Removed some ill-advised casts from the parsers.
+Fixed bug in CallSuperInConstructor; it no longer flag classes without extends clauses.
+Fixed release packaging; now entire xslt/ directory contents are included.
+Added more XSLT from Dave Corley - you can use them to filter PMD reports by priority level.
+You can now access the name of a MemberValuePair node using getImage().
+PositionLiteralsFirstInComparisons was rewritten in XPath.
+Added a getVersionString method to the TargetJDKVersion interface.
+Added an option '--targetjdk' argument to the Benchmark utility.
+Applied a patch from Wouter Zelle to clean up the Ant Formatter class, fix a TextRenderer bug, and make toConsole cleaner.
+Rewrote AvoidCallingFinalize in Java; fixed bug and runs much faster, too.
+Uploaded ruleset schema to http://pmd.sf.net/ruleset_xml_schema.xsd
+UseIndexOfChar now catches cases involving lastIndexOf.
+Rules are now run in the order in which they're listed in a ruleset file. Internally, they're now stored in a List vs a Set, and RuleSet.getRules() now returns a Collection.
+Upgraded to JUnit version 3.8.2.
+
New rules:
+ Basic ruleset: UselessOperationOnImmutable, MisplacedNullCheck, UnusedNullCheckInEquals
+ Migration ruleset: IntegerInstantiation
+ JUnit ruleset: UseAssertNullInsteadOfAssertTrue
+ Strings ruleset: AppendCharacterWithChar, ConsecutiveLiteralAppends, UseIndexOfChar
+ Design ruleset: AvoidConstantsInterface
+ Optimizations ruleset: UseArraysAsList, AvoidArrayLoops
+ Controversial ruleset: BooleanInversion
+Fixed bug 1371980 - InefficientStringBuffering no longer flags StringBuffer methods other than append().
+Fixed bug 1277373 - InefficientStringBuffering now catches more cases.
+Fixed bug 1376760 - InefficientStringBuffering no longer throws a NullPointerException when processing certain expressions.
+Fixed bug 1371757 - Misleading example in AvoidSynchronizedAtMethodLevel
+Fixed bug 1373510 - UseAssertSameInsteadOfAssertTrue no longer has a typo in its message, and its message is more clear.
+Fixed bug 1375290 - @SuppressWarnings annotations are now implemented correctly; they accept one blank argument to suppress all warnings.
+Fixed bug 1376756 - UselessOverridingMethod no longer throws an exception on overloaded methods.
+Fixed bug 1378358 - StringInstantiation no longer throws ClassCastExceptions on certain allocation patterns.
+Fixed bug 1371741 - UncommentedEmptyConstructor no longer flags constructors that consist of a this() or a super() invocation.
+Fixed bug 1277373 - InefficientStringBuffering no longer flags concatenations that involve a static final String.
+Fixed bug 1379701 - CompareObjectsWithEquals no longer flags comparisons of array elements.
+Fixed bug 1380969 - UnusedPrivateMethod no longer flags private static methods that are only invoked in a static context from a field declaration.
+Fixed bug 1384594 - Added a 'prefix' property for BeanMembersShouldSerializeRule
+Fixed bug 1394808 - Fewer missed hits for AppendCharacterWithChar and InefficientStringBuffering, thanks to Allan Caplan for catching these
+Fixed bug 1400754 - A NPE is no longer thrown on certain JDK 1.5 enum usages.
+Partially fixed bug 1371753 - UnnecessaryLocalBeforeReturn message now reflects the fact that that rule flags all types
+Fixed a bug in UseStringBufferLength; it no longers fails with an exception on expressions like StringBuffer.toString.equals(x)
+Fixed a bug in CPD's C/C++ parser so that it no longer fails on multi-line literals; thx to Tom Judge for the nice patch.
+CPD now recognizes '--language c' and '--language cpp' as both mapping to the C/C++ parser.
+Modified renderers to support disabling printing of suppressed warnings. Introduced a new AbstractRenderer class that all Renderers can extends to get the current behavior - that is, suppressed violations are printed.
+Implemented RFE 1375435 - you can now embed regular expressions inside XPath rules, i.e., //ClassOrInterfaceDeclaration[matches(@Image, 'F?o')].
+Added current CLASSPATH to pmd.bat.
+UnusedFormalParameter now catches unused constructor parameters, and its warning message now reflects whether it caught a method or a constructor param.
+Rebuilt JavaCC parser with JavaCC 4.0.
+Added jakarta-oro-2.0.8.jar as a new dependency to support regular expression in XPath rules.
+Ant task now supports a 'minimumPriority' attribute; only rules with this priority or higher will be run.
+Renamed Ant task 'printToConsole' attribute to 'toConsole' and it can only be used inside a formatter element.
+Added David Corley's Javascript report, more details are here: http://tomcopeland.blogs.com/juniordeveloper/2005/12/demo_of_some_ni.html
+
New rules:
+ Basic ruleset: ClassCastExceptionWithToArray, AvoidDecimalLiteralsInBigDecimalConstructor
+ Design ruleset: NonThreadSafeSingleton, UncommentedEmptyMethod, UncommentedEmptyConstructor
+ Controversial ruleset: DefaultPackage
+ Naming ruleset: MisleadingVariableName
+ Migration ruleset: ReplaceVectorWithList, ReplaceHashtableWithMap, ReplaceEnumerationWithIterator, AvoidEnumAsIdentifier, AvoidAssertAsIdentifier
+ Strings ruleset: UseStringBufferLength
+Fixed bug 1292745 - Removed unused source file ExceptionTypeChecking.java
+Fixed bug 1292609 - The JDK 1.3 parser now correctly handles certain 'assert' usages. Also added a 'JDK 1.3' menu item to the Designer.
+Fixed bug 1292689 - Corrected description for UnnecessaryLocalBeforeReturn
+Fixed bug 1293157 - UnusedPrivateMethod no longer reports false positives for private methods which are only invoked from static initializers.
+Fixed bug 1293277 - Messages that used 'pluginname' had duplicated messages.
+Fixed bug 1291353 - ASTMethodDeclaration isPublic/isAbstract methods always return true. The syntactical modifier - i.e., whether or not 'public' was used in the source code in the method declaration - is available via 'isSyntacticallyPublic' and 'isSyntacticallyAbstract'
+Fixed bug 1296544 - TooManyFields no longer checks the wrong property value.
+Fixed bug 1304739 - StringInstantiation no longer crashes on certain String constructor usages.
+Fixed bug 1306180 - AvoidConcatenatingNonLiteralsInStringBuffer no longer reports false positives on certain StringBuffer usages.
+Fixed bug 1309235 - TooManyFields no longer includes static finals towards its count.
+Fixed bug 1312720 - DefaultPackage no longer flags interface fields.
+Fixed bug 1312754 - pmd.bat now handles command line arguments better in WinXP.
+Fixed bug 1312723 - Added isSyntacticallyPublic() behavior to ASTFieldDeclaration nodes.
+Fixed bug 1313216 - Designer was not displaying 'final' attribute for ASTLocalVariableDeclaration nodes.
+Fixed bug 1314086 - Added logging-jakarta-commons as a short name for rulesets/logging-jakarta-commons.xml to SimpleRuleSetNameMapper.
+Fixed bug 1351498 - Improved UnnecessaryCaseChange warning message.
+Fixed bug 1351706 - CompareObjectsWithEquals now catches more cases.
+Fixed bug 1277373 (and 1347286) - InefficientStringBuffering now flags fewer false positives.
+Fixed bug 1363447 - MissingBreakInSwitch no longer reports false positives for switch statements where each switch label has a return statement.
+Fixed bug 1363458 - MissingStaticMethodInNonInstantiatableClass no longer reports cases where there are public static fields.
+Fixed bug 1364816 - ImmutableField no longer reports false positives for fields assigned in an anonymous inner class in a constructor.
+Implemented RFE 1311309 (and 1119854) - Suppressed RuleViolation counts are now included in the reports.
+Implemented RFE 1220371 - Rule violation suppression via annotations. Per the JLS, @SuppressWarnings can be placed before the following nodes: TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE.
+Implemented RFE 1275547 - OverrideBothEqualsAndHashcode now skips Comparator implementations.
+Applied patch 1306999 - Renamed CloseConnection to CloseResource and added support for checking Statement and ResultSet objects.
+Applied patch 1344754 - EmptyCatchBlock now skips catch blocks that contain comments. This is also requested in RFE 1347884.
+Renamed AvoidConcatenatingNonLiteralsInStringBuffer to InefficientStringBuffering; new name is a bit more concise.
+Modified LongVariable; now it has a property which can be used to override the minimum reporting value.
+Improved CPD XML report.
+CPD no longer skips header files when checking C/C++ code.
+Reworked CPD command line arguments; old-style arguments will still work for one more version, though.
+Lots of documentation improvements.
+
New rules:
+ Design: PositionLiteralsFirstInComparisons, UnnecessaryLocalBeforeReturn
+ Logging-jakarta-commons: ProperLogger
+ Basic: UselessOverridingMethod
+ Naming: PackageCase, NoPackage
+ Strings: UnnecessaryCaseChange
+Implemented RFE 1220171 - rule definitions can now contain a link to an external URL for more information on that rule - for example, a link to the rule's web page. Thanks to Wouter Zelle for designing and implementing this!
+Implemented RFE 1230685 - The text report now includes parsing errors even if no rule violations are reported
+Implemented RFE 787860 - UseSingleton now accounts for JUnit test suite declarations.
+Implemented RFE 1097090 - The Report object now contains the elapsed time for running PMD. This shows up in the XML report as an elapsedTime attribute in the pmd element in the format '2m 5s' or '1h 5h 35s' or '25s' .
+Implemented RFE 1246338 - CPD now handles SCCS directories and NTFS junction points.
+Fixed bug 1226858 - JUnitAssertionsShouldIncludeMessage now checks calls to assertFalse.
+Fixed bug 1227001 - AvoidCallingFinalize no longer flags calls to finalize() within finalizers.
+Fixed bug 1229755 - Fixed typo in ArrayIsStoredDirectly description.
+Fixed bug 1229749 - Improved error message when an external rule is not found.
+Fixed bug 1224849 - JUnitTestsShouldContainAsserts no longer skips method declarations which include explicit throws clauses.
+Fixed bug 1225492 - ConstructorCallsOverridableMethod now reports the correct method name. dvholten's examples in RFE 1235562 also helped with this a great deal.
+Fixed bug 1228589 - DoubleCheckedLocking and ExceptionSignatureDeclaration no longer throw ClassCastExceptions on method declarations that declare generic return types.
+Fixed bug 1235299 - NullAssignment no longer flags null equality comparisons in ternary expressions.
+Fixed bug 1235300 - NullAssignment no longer flags assignments to final fields.
+Fixed bug 1240201 - The UnnecessaryParentheses message is no longer restricted to return statements.
+Fixed bug 1242290 - The JDK 1.5 parser no longer chokes on nested enumerations with a constructor.
+Fixed bug 1242544 - SimplifyConditional no longer flags null checks that precede an instanceof involving an array dereference.
+Fixed bug 1242946 - ArrayIsStoredDirectly no longer reports false positives for equality expression comparisons. As a bonus, its message now includes the variable name :-)
+Fixed bug 1232648 - MethodReturnsInternalArray no longer reports false positives on return statement expressions that involve method invocations on an internal array.
+Fixed bug 1244428 - MissingStaticMethodInNonInstantiatableClass no longer reports warnings for nested classes. Some inner class cases will be missed, but false positives will be eliminated as well.
+Fixed bug 1244443 - EqualsNull now catches more cases.
+Fixed bug 1250949 - The JDK 1.5 parser no longer chokes on annotated parameters and annotated local variables.
+Fixed bug 1245139 - TooManyFields no longer throws a ClassCastException when processing anonymous classes.
+Fixed bug 1251256 - ImmutableField no longer skips assignments in try blocks on methods (which led to false positives).
+Fixed bug 1250949 - The JDK 1.5 parser no longer chokes on AnnotationTypeMemberDeclaration with a default value.
+Fixed bug 1245367 - ImmutableField no longer triggers on assignments in loops in constructors.
+Fixed bug 1251269 - AvoidConcatenatingNonLiteralsInStringBuffer no longer triggers on StringBuffer constructors like 'new StringBuffer(1 + getFoo());'
+Fixed bug 1244570 - AvoidConcatenatingNonLiteralsInStringBuffer no longer triggers on certain AST patterns involving local variable declarations inside Statement nodes.
+Fixed bug 695344 - StringInstantiation no longer triggers on the String(byte[]) constructor.
+Fixed bug 1114754 - UnusedPrivateMethod reports fewer false positives.
+Fixed bug 1290718 - Command line parameter documentation is now correct for targetjdk options.
+Applied patch 1228834 - XPath rules can now use properties to customize rules. Thanks to Wouter Zelle for another great piece of work!
+Fixed a bug in RuleSetFactory that missed some override cases; thx to Wouter Zelle for the report and a fix.
+Fixed a bug in the grammar that didn't allow constructors to have type parameters, which couldn't parse some JDK 1.5 constructs.
+Fixed a bug in ImportFromSamePackage; now it catches the case where a class has an on-demand import for the same package it is in.
+Fixed a bug in CompareObjectsWithEquals; now it catches some local variable cases.
+Fixed a bug in CouplingBetweenObjects; it no longer triggers an exception (which is a bug in the symbol table layer) by calling getEnclosingClassScope() when the node in question isn't enclosed by one.
+Moved AvoidCallingFinalize from the design ruleset to the finalize ruleset and then deleted redundant ExplicitCallToFinalize rule from the finalize ruleset.
+Deleted redundant ExceptionTypeChecking rule from the strictexception ruleset; use AvoidInstanceofChecksInCatchClause in the design ruleset instead.
+Added some new XSLT scripts that create nifty HTML output; thanks to Wouter Zelle for the code.
+Improved UseCorrectExceptionLogging; thx to Wouter Zelle for the new XPath.
+Improved warning message from UnusedPrivateMethod.
+Improved EmptyIfStmt; now it catches the case where an IfStatement is followed by an EmptyStatement node.
+The Ant task now accepts the short names of rulesets (e.g., unusedcode for rulesets/unusedcode.xml).
+Removed unnecessary '.html' suffix from displayed filenames when the linkPrefix attribute is used with the HTML renderer.
+Added an optional 'description' attribute to the 'property' element in the ruleset XML files.
+Added a simplified SimpleNode.addViolation() method to reduce duplicated rule violation creation code.
+Moved from jaxen-1.0-fcs.jar/saxpath-1.0-fcs.jar to jaxen-1.1-beta-7.jar. This yielded a 20% speed increase in the basic ruleset!
+
New rules: UseCorrectExceptionLogging (logging-jakarta-commons ruleset), AvoidPrintStackTrace (logging-java ruleset), CompareObjectsWithEquals (design ruleset)
+Fixed bug 1201577 - PMD now correctly parses method declarations that return generic types.
+Fixed bug 1205709 - PMD no longer takes a long time to report certain parsing errors.
+Fixed bug 1052356 - ImmutableField no longer triggers on fields which are assigned to in a constructor's try statement.
+Fixed bug 1215854 - Package/class/method names are now filled in whenever possible, and the XML report includes all three.
+Fixed bug 1209719 - MethodArgumentCouldBeFinal no longer triggers on arguments which are modified using postfix or prefix expressions. A bug in AvoidReassigningParameters was also fixed under the same bug id.
+Fixed bug 1188386 - MethodReturnsInternalArray no longer flags returning a local array declaration.
+Fixed bug 1172137 - PMD no longer locks up when generating a control flow graph for if statements with labelled breaks.
+Fixed bug 1221094 - JUnitTestsShouldContainAsserts no longer flags static methods.
+Fixed bug 1217028 - pmd.bat now correctly passes parameters to PMD.
+Implemented RFE 1188604 - AvoidThrowingCertainExceptionTypes has been split into AvoidThrowingRawExceptionTypes and AvoidThrowingNullPointerException.
+Implemented RFE 1188369 - UnnecessaryBooleanAssertion now checks for things like 'assertTrue(!foo)'. These should be changed to 'assertFalse(foo)' for clarity.
+Implemented RFE 1199622 - UnusedFormalParameter now defaults to only checking private methods unless a 'checkall' property is set.
+Implemented RFE 1220314 - the symbol table now includes some rudimentary type information.
+Break and continue statement labels (if present) are placed in the image field.
+Fixed bug which caused MissingSerialVersionUID to trigger on all interfaces that implemented other interfaces.
+Modified NullAssignmentRule to catch null assignments in ternary expressions.
+Added two new node types - ASTCatchStatement and ASTFinallyStatement.
+Modified rule XML definition; it no longer includes a symboltable attribute since the symbol table layer is now run for all files analyzed.
+Harden equality of AbstractRule and RuleSet objects (needed for the Eclipse plugin features)
+Change RuleSet.getRuleByName. Now return null instead of throwing a RuntimeException when the rule is not found
+Add .project and .classpath to the module so that it can be checkout as an Eclipse project
+
New rules: SimplifyStartsWith, UnnecessaryParentheses, CollapsibleIfStatements, UseAssertEqualsInsteadOfAssertTrue, UseAssertSameInsteadOfAssertTrue, UseStringBufferForStringAppends, SimplifyConditional, SingularField
+Fixed bug 1170535 - LongVariable now report variables longer than 17 characters, not 12.
+Fixed bug 1182755 - SystemPrintln no longer overreports problems.
+Fixed bug 1188372 - AtLeastOneConstructor no longer fires on interfaces.
+Fixed bug 1190508 - UnnecessaryBooleanAssertion no longer fires on nested boolean literals.
+Fixed bug 1190461 - UnusedLocal no longer misses usages which are on the RHS of a right bit shift operator.
+Fixed bug 1188371 - AvoidInstantiatingObjectsInLoops no longer fires on instantiations in loops when the 'new' keyword is preceded by a 'return' or a 'throw'.
+Fixed bug 1190526 - TooManyFields now accepts a property setting correctly, and default lower bound is 15 vs 10.
+Fixed bug 1196238 - UnusedImports no longer reports false positives for various JDK 1.5 java.lang subpackages.
+Fixed bug 1169731 - UnusedImports no longer reports false positives on types used inside generics. This bug also resulted in a bug in ForLoopShouldBeWhileLoop being fixed, thanks Wim!
+Fixed bug 1187325 - UnusedImports no longer reports a false positive on imports which are used inside an Annotation.
+Fixed bug 1189720 - PMD no longer fails to parse generics that use 'member selectors'.
+Fixed bug 1170109 - The Ant task now supports an optional 'targetjdk' attribute that accepts values of '1.3', '1.4', or '1.5'.
+Fixed bug 1183032 - The XMLRenderer no longer throws a SimpleDateFormat exception when run with JDK 1.3.
+Fixed bug 1097256 - The XMLRenderer now supports optional encoding of UTF8 characters using the 'net.sourceforge.pmd.supportUTF8' environment variable.
+Fixed bug 1198832 - AbstractClassWithoutAbstractMethod no longer flags classes which implement interfaces since these can partially implement the interface and thus don't need to explicitly declare abstract methods.
+Implemented RFE 1193979 - BooleanInstantiation now catches cases like Boolean.valueOf(true)
+Implemented RFE 1171095 - LabeledStatement nodes now contain the image of the label.
+Implemented RFE 1176401 - UnusedFormalParameter now flags public methods.
+Implemented RFE 994338 - The msg produced by ConstructorCallsOverridableMethod now includes the offending method name.
+Modified command line parameters; removed -jdk15 and -jdk13 parameters and added a -'targetjdk [1.3|1.4|1.5]' parameter.
+Modified CSVRenderer to include more columns.
+Optimized rules: FinalFieldCouldBeStatic (115 seconds to 7 seconds), SuspiciousConstantFieldName (48 seconds to 14 seconds), UnusedModifer (49 seconds to 4 seconds)
+
New rules: MissingSerialVersionUID, UnnecessaryFinalModifier, AbstractClassDoesNotContainAbstractMethod, MissingStaticMethodInNonInstantiatableClass, AvoidSynchronizedAtMethodLevel, AvoidCallingFinalize, UseNotifyAllInsteadOfNotify, MissingBreakInSwitch, AvoidInstanceofChecksInCatchClause, AvoidFieldNameMatchingTypeName, AvoidFieldNameMatchingMethodName, AvoidNonConstructorMethodsWithClassName, TestClassWithoutTestCases, TooManyFields, CallSuperInConstructor, UnnecessaryBooleanAssertion, UseArrayListInsteadOfVector
+Implemented RFE 1058039 - PMD's command line interface now accepts abbreviated names for the standard rulesets; for example 'java net.sourceforge.pmd.PMD /my/source/code/ text basic,unusedcode' would run the rulesets/basic.xml and the rulesets/unusedcode.xml rulesets on the source in /my/source/code and produce a text report.
+Implemented RFE 1119851 - PMD's Ant task now supports an 'excludeMarker' attribute.
+Fixed bug 994400 - False +: ConstructorCallsOverridableMethodRule, thanks to ereissner for reporting it
+Fixed bug 1146116 - JUnitTestsShouldIncludeAssert no longer crashes on inner Interface
+Fixed bug 1114625 - UnusedPrivateField no longer throws an NPE on standalone postfix expressions which are prefixed with 'this'.
+Fixed bug 1114020 - The Ant task now reports a complete stack trace when run with the -verbose flag.
+Fixed bug 1117983 - MethodArgumentCouldBeFinal no longer reports false positives on try..catch blocks.
+Fixed bug 797742 - PMD now parses JDK 1.5 source code. Note that it's not perfect yet; more testing/bug reports are welcome!
+Fixed a bug - the StatisticalRule no longer 'merges' data points when using the 'topscore' property.
+Fixed a bug - the PMD Ant task's failOnRuleViolation attribute no longer causes a BuildException in the case when no rule violations occur.
+Modified the XSLT to add a summary section.
+Added Ruby support to CPD.
+Optimized various rules and wrote a benchmarking application; results are here - http://infoether.com/~tom/pmd_timing.txt
+
Fixed bug 1113927 - ExceptionAsFlowControl no longer throws NPEs on code where a throw statement exists without a try statement wrapping it.
+Fixed bug 1113981 - AvoidConcatenatingNonLiteralsInStringBuffer no longer throws NPEs on code where an append appears as a child of an ExplicitConstructorInvocation node.
+Fixed bug 1114039 - AvoidInstantiatingObjectsInLoops's message no longer contains a spelling error.
+Fixed bug 1114029 - The 'optimization' rules no longer throw NPEs at various points.
+Fixed bug 1114251 - The 'sunsecure' rules no longer throw NPEs at various points.
+
New rules: LocalVariableCouldBeFinal, MethodArgumentCouldBeFinal, AvoidInstantiatingObjectsInLoops, ArrayIsStoredDirectly, MethodReturnsInternalArray, AssignmentToNonFinalStatic, AvoidConcatenatingNonLiteralsInStringBuffer
+Fixed bug 1088459 - JUnitTestsShouldContainAsserts no longer throws ClassCastException on interface, native, and abstract method declarations.
+Fixed bug 1100059 - The Ant task now generates a small empty-ish report if there are no violations.
+Implemented RFE 1086168 - PMD XML reports now contain a version and timestamp attribute in the <pmd> element.
+Implemented RFE 1031950 - The PMD Ant task now supports nested ruleset tags
+Fixed a bug in the rule override logic; it no longer requires the "class" attribute of a rule be listed in the overrides section.
+Added 'ignoreLiterals' and 'ignoreIdentifiers' boolean options to the CPD task.
+Cleaned up a good bit of the symbol table code; thanks much to Harald Gurres for the patch.
+CPD now contains a generic copy/paste checker for programs in any language
+
New rules: AvoidProtectedFieldInFinalClass, SystemPrintln
+Fixed bug 1050173 - ImmutableFieldRule no longer reports false positives for static fields.
+Fixed bug 1050286 - ImmutableFieldRule no longer reports false positives for classes which have multiple constructors only a subset of which set certain fields.
+Fixed bug 1055346 - ImmutableFieldRule no longer reports false positive on preinc/predecrement/postfix expressions.
+Fixed bug 1041739 - EmptyStatementNotInLoop no longer reports false positives for nested class declarations in methods.
+Fixed bug 1039963 - CPD no longer fails to parse C++ files with multi-line macros.
+Fixed bug 1053663 - SuspiciousConstantFieldName no longer reports false positives for interface members.
+Fixed bug 1055930 - CouplingBetweenObjectsRule no longer throws a NPE on interfaces
+Fixed a possible NPE in dfa.report.ReportTree.
+Implemented RFE 1058033 - Renamed run.[sh|bat] to pmd.[sh|bat].
+Implemented RFE 1058042 - XML output is more readable now.
+Applied patch 1051956 - Rulesets that reference rules using "ref" can now override various properties.
+Applied patch 1070733 - CPD's Java checker now has an option to ignore both literals and identifiers - this can help find large duplicate code blocks, but can also result in false positives.
+YAHTMLRenderer no longer has dependence on Ant packages.
+Modified the AST to correctly include PostfixExpression nodes. Previously a statement like "x++;" was embedded in the parent StatementExpression node.
+Moved BooleanInstantiation from the design ruleset to the basic ruleset.
+Updated Xerces libraries to v2.6.2.
+Many rule names had the word "Rule" tacked on to the end. Various folks thought this was a bad idea, so here are the new names of those rules which were renamed:
+- basic.xml: UnnecessaryConversionTemporary, OverrideBothEqualsAndHashcode, DoubleCheckedLocking
+- braces.xml: WhileLoopsMustUseBraces, IfElseStmtsMustUseBraces, ForLoopsMustUseBraces
+- clone.xml: ProperCloneImplementation
+- codesize.xml: CyclomaticComplexity, ExcessivePublicCount
+- controversial.xml: UnnecessaryConstructor, AssignmentInOperand, DontImportSun, SuspiciousOctalEscape
+- coupling.xml: CouplingBetweenObjects, ExcessiveImports, LooseCoupling
+- design.xml: UseSingleton, SimplifyBooleanReturns, AvoidReassigningParameters, ConstructorCallsOverridableMethod, AccessorClassGeneration, CloseConnection, OptimizableToArrayCall, IdempotentOperations. ImmutableField
+- junit.xml: JUnitAssertionsShouldIncludeMessage, JUnitTestsShouldIncludeAssert
+- logging-java.xml: MoreThanOneLogger, LoggerIsNotStaticFinal
+- naming.xml: ShortMethodName, VariableNamingConventions, ClassNamingConventions, AbstractNaming
+- strictexception.xml: ExceptionAsFlowControl, AvoidCatchingNPE, AvoidThrowingCertainExceptionTypes
+Continued working on JDK 1.5 compatibility - added support for static import statements, varargs, and the new for loop syntax
+- still TODO: generics and annotations (note that autoboxing shouldn't require a grammar change)
+- Good article on features: http://java.sun.com/developer/technicalArticles/releases/j2se15/
+
New rules: InstantiationToGetClass, IdempotentOperationsRule, SuspiciousEqualsMethodName, SimpleDateFormatNeedsLocale, JUnitTestsShouldContainAssertsRule, SuspiciousConstantFieldName, ImmutableFieldRule, MoreThanOneLoggerRule, LoggerIsNotStaticFinalRule, UseLocaleWithCaseConversions
+Applied patch in RFE 992576 - Enhancements to VariableNamingConventionsRule
+Implemented RFE 995910 - The HTML report can now include links to HTMLlized source code - for example, the HTML generated by JXR.
+Implemented RFE 665824 - PMD now ignores rule violations in lines containing the string 'NOPMD'.
+Fixed bug in SimplifyBooleanExpressions - now it catches more cases.
+Fixed bugs in AvoidDuplicateLiterals - now it ignores small duplicate literals, its message is more helpful, and it catches more cases.
+Fixed bug 997893 - UnusedPrivateField now detects assignments to members of private fields as a usage.
+Fixed bug 1020199 - UnusedLocalVariable no longer flags arrays as unused if an assignment is made to an array slot.
+Fixed bug 1027133 - Now ExceptionSignatureDeclaration skips certain JUnit framework methods.
+Fixed bug 1008548 - The 'favorites' ruleset no longer contains a broken reference.
+Fixed bug 1045583 - UnusedModifier now correctly handles anonymous inner classes within interface field declarations.
+Partially fixed bug 998122 - CloseConnectionRule now checks for imports of java.sql before reporting a rule violation.
+Applied patch 1001694 - Now PMD can process zip/jar files of source code.
+Applied patch 1032927 - The XML report now includes the rule priority.
+Added data flow analysis facade from Raik Schroeder.
+Added two new optional attributes to rule definitions - symboltable and dfa. These allow the symbol table and DFA facades to be configured on a rule-by-rule basis. Note that if your rule needs the symbol table; you'll need to add symboltable="true" to your rule definition. FWIW, this also results in about a 5% speedup for rules that don't need either layer.
+Added a "logging" ruleset - thanks to Miguel Griffa for the code!
+Enhanced the ASTViewer - and renamed it 'Designer' - to display data flows.
+Moved development environment to Maven 1.0.
+Moved development environment to Ant 1.6.2. This is nice because using the new JUnit task attribute "forkmode='perBatch'" cuts test runtime from 90 seconds to 7 seconds. Sweet.
+MethodWithSameNameAsEnclosingClass now reports a more helpful line number.
+
New rules: CloneMethodMustImplementCloneable, CloneThrowsCloneNotSupportedException, EqualsNull, ConfusingTernary
+Created new "clone" ruleset and moved ProperCloneImplementationRule over from the design ruleset.
+Moved LooseCoupling from design.xml to coupling.xml.
+Some minor performance optimizations - removed some unnecessary casts from the grammar, simplified some XPath rules.
+Postfix expressions (i.e., x++) are now available in the grammar. To access them, search for StatementExpressions with an image of "++" or "--" - i.e., in XPath, //StatementExpression[@Image="++"]. This is an odd hack and hopefully will get cleared up later.
+Ant task and CLI now used BufferedInputStreams.
+Converted AtLeastOneConstructor rule from Java code to XPath.
+Implemented RFE 743460: The XML report now contains the ruleset name.
+Implemented RFE 958714: Private field and local variables that are assigned but not used are now flagged as unused.
+Fixed bug 962782 - BeanMembersShouldSerializeRule no longer reports set/is as being a violation.
+Fixed bug 977022 - UnusedModifier no longer reports false positives for modifiers of nested classes in interfaces
+Fixed bug 976643 - IfElseStmtsMustUseBracesRule no longer reports false positives for certain if..else constructs.
+Fixed bug 985961 - UseSingletonRule now fires on classes which contain static fields
+Fixed bug 977031 - FinalizeDoesNotCallSuperFinalize no longer reports a false positive when a finalizer contains a call to super.finalize in a try {} finally {} block.
+
New rules: ExceptionAsFlowControlRule, BadComparisonRule, AvoidThrowingCertainExceptionTypesRule, AvoidCatchingNPERule, OptimizableToArrayCallRule
+Major grammar changes - lots of new node types added, many superfluous nodes removed from the runtime AST. Bug 786611 - http://sourceforge.net/tracker/index.php?func=detail&aid=786611&group_id=56262&atid=479921 - explains it a bit more.
+Fixed bug 786611 - Expressions are no longer over-expanded in the AST
+Fixed bug 874284 - The AST now contains tokens for bitwise or expressions - i.e., "|"
+
Moved development environment to Maven 1.0-RC2.
+Fixed bug 925840 - Messages were no longer getting variable names plugged in correctly
+Fixed bug 919308 - XMLRenderer was still messed up; 'twas missing a quotation mark.
+Fixed bug 923410 - PMD now uses the default platform character set encoding; optionally, you can pass in a character encoding to use.
+Implemented RFE 925839 - Added some more detail to the UseSingletonRule.
+Added an optional 'failuresPropertyName' attribute to the Ant task.
+Refactored away duplicate copies of XPath rule definitions in regress/, yay!
+Removed manifest from jar file; it was only there for the Main-class attribute, and it's not very useful now since PMD has several dependencies.
+Began working on JDK 1.5 compatibility - added support for EnumDeclaration nodes.
+
Fixed bug 895661 - XML reports containing error elements no longer have malformed XML.
+Fixed a bug in UnconditionalIfStatement - it no longer flags things like "if (x==true)".
+Applied Steve Hawkins' improvements to CPD:
+- Various optimizations; now it runs about 4 times faster!
+- fixed "single match per file" bug
+- tweaked source code slicing
+- CSV renderer
+Added two new renderers - SummaryHTMLRenderer and PapariTextRenderer.
+Moved development environment to Ant 1.6 and JavaCC 3.2.
+
New rules: DontImportSunRule, EmptyFinalizer, EmptyStaticInitializer, AvoidDollarSigns, FinalizeOnlyCallsSuperFinalize, FinalizeOverloaded, FinalizeDoesNotCallSuperFinalize, MethodWithSameNameAsEnclosingClass, ExplicitCallToFinalize, NonStaticInitializer, DefaultLabelNotLastInSwitchStmt, NonCaseLabelInSwitchStatement, SuspiciousHashcodeMethodName, EmptyStatementNotInLoop, SuspiciousOctalEscapeRule
+FinalizeShouldBeProtected moved from design.xml to finalizers.xml.
+Added isTrue() to ASTBooleanLiteral.
+Added UnaryExpression to the AST.
+Added isPackagePrivate() to AccessNode.
+
New rules: AbstractNamingRule, ProperCloneImplementationRule
+Fixed bug 840926 - AvoidReassigningParametersRule no longer reports a false positive when assigning a value to an array slot when the array is passed as a parameter to a method
+Fixed bug 760520 - RuleSetFactory is less strict about whitespace in ruleset.xml files.
+Fixed bug 826805 - JumbledIncrementorRule no longer reports a false positive when a outer loop incrementor is used as an array index
+Fixed bug 845343 - AvoidDuplicateLiterals now picks up cases when a duplicate literal appears in field declarations.
+Fixed bug 853409 - VariableNamingConventionsRule no longer requires that non-static final fields be capitalized
+Fixed a bug in OverrideBothEqualsAndHashcodeRule; it no longer reports a false positive when equals() is passed the fully qualified name of Object.
+Implemented RFE 845348 - UnnecessaryReturn yields more useful line numbers now
+Added a ruleset DTD and a ruleset XML Schema.
+Added 'ExplicitExtends' and 'ExplicitImplements' attributes to UnmodifiedClassDeclaration nodes.
+
Relicensed under a BSD-style license.
+Fixed bug 822245 - VariableNamingConventionsRule now handles interface fields correctly.
+Added new rules: EmptySynchronizedBlock, UnnecessaryReturn
+ASTType now has an getDimensions() method.
+
Added new rule: CloseConnectionRule
+Fixed bug 782246 - FinalFieldCouldBeStatic no longer flags fields in interfaces.
+Fixed bug 782235 - "ant -version" now prints more details when a file errors out.
+Fixed bug 779874 - LooseCouplingRule no longer triggers on ArrayList
+Fixed bug 781393 - VariableNameDeclaration no longer throws ClassCastExpression since ASTLocalVariableDeclaration now subclasses AccessNode
+Fixed bug 797243 - CPD XML report can no longer contain ]]> (CDEnd)
+Fixed bug 690196 - PMD now handles both JDK 1.3 and 1.4 code - i.e., usage of "assert" as an identifier.
+Fixed bug 805092 - VariableNamingConventionsRule no longer flags serialVersionUID as a violation
+Fixed bug - Specifying a non-existing rule format on the command line no longer results in a ClassNotFoundException.
+XPath rules may now include pluggable parameters. This feature is very limited. For now.
+Tweaked CPD time display field
+Made CPD text fields uneditable
+Added more error checking to CPD GUI input
+Added "dialog cancelled" check to CPD "Save" function
+Added Boris Gruschko's AST viewer.
+Added Jeff Epstein's TextPad integration.
+ASTType now has an isArray() method.
+
Fixed bug 781077 - line number "-1" no longer appears for nodes with siblings.
+
Added new rules: VariableNamingConventionsRule, MethodNamingConventionsRule, ClassNamingConventionsRule, AvoidCatchingThrowable, ExceptionSignatureDeclaration, ExceptionTypeChecking, BooleanInstantiation
+Fixed bug 583047 - ASTName column numbers are now correct
+Fixed bug 761048 - Symbol table now creates a scope level for anonymous inner classes
+Fixed bug 763529 - AccessorClassGenerationRule no longer crashes when given a final inner class
+Fixed bug 771943 - AtLeastOneConstructorRule and UnnecessaryConstructorRule no longer reports false positives on inner classes.
+Applied patch from Chris Webster to fix another UnnecessaryConstructorRule problem.
+Added ability to accept a comma-delimited string of files and directories on the command line.
+Added a CSVRenderer.
+Added a "-shortfilenames" argument to the PMD command line interface.
+Modified grammer to provide information on whether an initializer block is static.
+ASTViewer now shows node images and modifiers
+ASTViewer now saves last edited text to ~/.pmd_astviewer
+Moved the PMD Swing UI into a separate module - pmd-swingui.
+Updated license.txt to point to new location.
+
Added new rules: FinalizeShouldBeProtected, FinalFieldCouldBeStatic, BeanMembersShouldSerializeRule
+Removed "verbose" attribute from PMD and CPD Ant tasks; now they use built in logging so you can do a "ant -verbose cpd" or "ant -verbose pmd". Thanks to Philippe T'Seyen for the code.
+Added "excludes" feature to rulesets; thanks to Gael Marziou for the suggestion.
+Removed "LinkedList" from LooseCouplingRule checks; thx to Randall Schulz for the suggestion.
+CPD now processes PHP code.
+Added VBHTMLRenderer; thanks to Vladimir Bossicard for the code.
+Added "Save" item to CPD GUI; thanks to mcclain looney for the patch.
+Fixed bug 732592 - Ant task now accepts a nested classpath element.
+Fixed bug 744915 - UseSingletonRule no longer fires on abstract classes, thanks to Pablo Casado for the bug report.
+Fixed bugs 735396 and 735399 - false positives from ConstructorCallsOverridableMethodRule
+Fixed bug 752809 - UnusedPrivateMethodRule now catches unused private static methods, thanks to Conrad Roche for the bug report.
+
Added new rules: ReturnFromFinallyBlock, SimplifyBooleanExpressions
+Added a new Ant task for CPD; thanks to Andy Glover for the code.
+Added ability to specify a class name as a renderer on the command line or in the formatter "type" attribute of the Ant task.
+Brian Ewins completely rewrote CPD using a portion of the Burrows-Wheeler Transform - it's much, much, much faster now.
+Rebuilt parser with JavaCC 3.0; made several parser optimizations.
+The Ant task now accepts a <classpath> element to aid in loading custom rulesets. Thanks to Luke Francl for the suggestion.
+Fixed several bugs in UnnecessaryConstructorRule; thanks to Adam Nemeth for the reports and fixes.
+All test-data classes have been inlined into their respective JUnit tests.
+
Added new rules: ConstructorCallsOverridableMethodRule, AtLeastOneConstructorRule, JUnitAssertionsShouldIncludeMessageRule, DoubleCheckedLockingRule, ExcessivePublicCountRule, AccessorClassGenerationRule
+The Ant task has been updated; if you set "verbose=true" full stacktraces are printed. Thx to Paul Roebuck for the suggestion.
+Moved JUnit rules into their own package - "net.sourceforge.pmd.rules.junit".
+Incorporated new ResourceLoader; thanks to Dave Fuller
+Incorporated new XPath-based rule definitions; thanks to Dan Sheppard for the excellent work.
+Fixed bug 697187 - Problem with nested ifs
+Fixed bug 699287 - Grammar bug; good catch by David Whitmore
+
Added new rules: CyclomaticComplexityRule, AssignmentInOperandRule
+Added numbering to the HTMLRenderer; thx to Luke Francl for the code.
+Added an optional Ant task attribute 'failOnRuleViolation'. This stops the build if any rule violations are found.
+Added an XSLT script for processing the PMD XML report; thx to Mats for the code.
+The Ant task now determines whether the formatter toFile attribute is absolute or relative and routes the report appropriately.
+Moved several rules into a new "controversial" ruleset.
+Fixed bug 672742 - grammar typo was hosing up ASTConstructorDeclaration which was hosing up UseSingletonRule
+Fixed bug 674393 - OnlyOneReturn rule no longer counts returns that are inside anonymous inner classes as being inside the containing method. Thx to C. Lamont Gilbert for the bug report.
+Fixed bug 674420 - AvoidReassigningParametersRule no longer counts parameter field reassignment as a violation. Thx to C. Lamont Gilbert for the bug report.
+Fixed bug 673662 - The Ant task's "failOnError" attribute works again. Changed the semantics of this attribute, though, so it fails the build if errors occurred. A new attribute 'failOnRuleViolation' serves the purpose of stopping the build if rule violations are found.
+Fixed bug 676340 - Symbol table now creates new scope level when it encounters a switch statement. See the bug for code details; generally, this bug would have triggered runtime exceptions on certain blocks of code.
+Fixed bug 683465 - JavaCC parser no longer has ability to throw java.lang.Error; now it only throws java.lang.RuntimeExceptions. Thx to Gunnlaugur Thor Briem for a good discussion on this topic.
+Fixed bug in OverrideBothEqualsAndHashcodeRule - it no longer bails out with a NullPtrException on interfaces that declare a method signature "equals(Object)". Thx to Don Leckie for catching that.
+
Added new rules: ImportFromSamePackageRule, SwitchDensityRule, NullAssignmentRule, UnusedModifierRule, ForLoopShouldBeWhileLoopRule
+Updated LooseCouplingRule to check for usage of Vector; thx to Vladimir for the good catch.
+Updated AvoidDuplicateLiteralsRule to report the line number of the first occurrence of the duplicate String.
+Modified Ant task to use a formatter element; this lets you render a report in several formats without having to rerun PMD.
+Added a new Ant task attribute - shortFilenames.
+Modified Ant task to ignore whitespace in the ruleset attribute
+Added rule priority settings.
+Added alternate row colorization to HTML renderer.
+Fixed bug 650623 - the Ant task now uses relative directories for the report file
+Fixed bug 656944 - PMD no longer prints errors to System.out, instead it just rethrows any exceptions
+Fixed bug 660069 - this was a symbol table bug; thanks to mcclain looney for the report.
+Fixed bug 668119 - OverrideBothEqualsAndHashcodeRule now checks the signature on equals(); thanks to mcclain looney for the report.
+
Fixed bug 633879: EmptyFinallyBlockRule now handles multiple catch blocks followed by a finally block.
+Fixed bug 633892: StringToStringRule false positive exposed problem in symbol table usage to declaration code.
+Fixed bug 617971: Statistical rules no longer produce tons of false positives due to accumulated results.
+Fixed bug 633209: OnlyOneReturn rule no longer requires the return stmt to be the last statement.
+Enhanced EmptyCatchBlockRule to flag multiple consecutive empty catch blocks.
+Renamed AvoidStringLiteralsRule to AvoidDuplicateLiteralsRule.
+Modified Ant task to truncate file paths to make the HTML output neater.
+
Added new rules: StringToStringRule, AvoidReassigningParametersRule, UnnecessaryConstructorRule, AvoidStringLiteralsRule
+Fixed bug 631010: AvoidDeeplyNestedIfStmtsRule works correctly with if..else stmts now
+Fixed bug 631605: OnlyOneReturn handles line spillover now.
+Moved AvoidDeeplyNestedIfStmts from the braces ruleset to the design ruleset.
+Moved several rules from the design ruleset to the codesize ruleset.
+Added a new "favorites" ruleset.
+
Added new rules: OnlyOneReturnRule, JumbledIncrementerRule, AvoidDeeplyNestedIfStmtsRule
+PMD is now built and tested with JUnit 3.8.1 and Ant 1.5.
+Added support for IntelliJ's IDEAJ.
+Fixed bug 610018 - StringInstantiationRule now allows for String(byte[], int, int) usage.
+Fixed bug 610693 - UnusedPrivateInstanceVariable handles parameter shadowing better.
+Fixed bug 616535 - Command line interface input checking is better now.
+Fixed bug 616615 - Command line interface allows the text renderer to be used now
+Fixed a bug - the statistics rules now handle interfaces better.
+
Added new rules: JUnitSpellingRule, JUnitStaticSuiteRule, StringInstantiationRule
+Added new rulesets - junit, strings.
+Added a printToConsole attribute to the Ant task so that you can see the report right there in the Ant output.
+Fixed bug in PMD GUI - rules are now saved correctly.
+Fixed bug 597916 - CPD line counts are accurate now.
+
Added new rules: UnusedImportsRule, EmptySwitchStmtRule, SwitchStmtsShouldHaveDefaultRule, IfStmtsMustUseBracesRule
+Fixed bug 597813 - Rule properties are now parsed correctly
+Fixed bug 597905 - UseSingletonRule now resets its state correctly
+Moved several rules into a new ruleset - braces.
+Improved CPD by removing import statements and package statements from the token set.
+Added Metrics API to the Report.
+Updated PMD GUI.
+
Added new rules: LongParameterListRule, SimplifyBooleanReturnsRule
+Enhanced statistics rules to support various ways of triggering rule violations
+Added rule customization via XML parameters
+Enhanced CopyAndPasteDetector; added a GUI
+Fixed bug 592060 - UnusedPrivateInstanceVariable handles explicitly referenced statics correctly
+Fixed bug 593849 - UnusedPrivateInstanceVariable handles nested classes better
+
Added new rule: UnusedFormalParameterRule
+Fixed bug 588083 - ForLoopsNeedBraces rule correctly handles a variety of for statement formats
+Added prototype of the copy and paste detector
+
Added new rules: UnusedPrivateMethodRule, WhileLoopsMustUseBracesRule, ForLoopsMustUseBracesRule, LooseCouplingRule
+Fixed bug 583482 - EmptyCatchBlock and EmptyFinallyBlock no longer report an incorrect line number.
+
Added new rules: ExcessiveClassLength, ExcessiveMethodLength
+DuplicateImportsRule now reports the correct line number.
+Fixed bug 582639 - Rule violations are now reported on the proper line
+Fixed bug 582509 - Removed unneeded throws clause
+Fixed bug 583009 - Now rulesets.properties is in the jar file
+
Added new rules: DontImportJavaLangRule, DuplicateImportsRule
+Added new ruleset: rulesets/imports.xml
+Changed sorting of RuleViolations to group Files together.
+Changed XML Renderer to improved format.
+Created DVSL Stylesheet for the new format.
+Moved the Cougaar rules out of the PMD core.
+Fixed bug 580093 - OverrideBothEqualsAndHashcodeRule reports a more correct line number.
+Fixed bug 581853 - UnusedLocalVariableRule now handles anonymous inner classes correctly.
+Fixed bug 580278 - this was a side effect of bug 581853.
+Fixed bug 580123 - UnusedPrivateInstanceVariable now checks for instance variable usage in inner classes.
+
Added new rules: OverrideBothEqualsAndHashcodeRule, EmptyTryBlock, EmptyFinallyBlock
+Reports are now sorted by line number
+RuleSets can now reference rules in other RuleSets
+Fixed bug 579718 - made 'ruleset not found' error message clearer.
+
Added new rules: UseSingletonRule, ShortVariableRule, LongVariableRule, ShortMethodNameRule
+Moved rules into RuleSets which are defined in XML files in the ruleset directory
+Ant task:
+-Added a 'failonerror' attribute
+-Changed 'rulesettype' to 'rulesetfiles'
+-Removed 'text' report format; only 'html' and 'xml' are available now
+
Added new rules: IfElseStmtsMustUseBracesRule, EmptyWhileStmtRule
+Modified command line interface to accept a rule set
+Fixed bug in EmptyCatchBlockRule
+Fixed typo in UnnecessaryConversionTemporaryRule
+Moved Ant task to the net.sourceforge.pmd.ant package
+Added new HTML report format
+
Initial release
+
ApexUnit (rulesets/apex/apexunit.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ +ApexUnitTestClassShouldHaveAsserts, ApexUnitTestShouldNotUseSeeAllDataTrue
+Braces (rulesets/apex/braces.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ +ForLoopsMustUseBraces, IfElseStmtsMustUseBraces, IfStmtsMustUseBraces, WhileLoopsMustUseBraces
+Complexity (rulesets/apex/complexity.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ +AvoidDeeplyNestedIfStmts, ExcessiveClassLength, ExcessiveParameterList, ExcessivePublicCount, NcssConstructorCount, NcssMethodCount, NcssTypeCount, StdCyclomaticComplexity, TooManyFields
+Default ruleset used by the CodeClimate Engine for Salesforce.com Apex (rulesets/apex/ruleset.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ +ApexBadCrypto, ApexCRUDViolation, ApexCSRF, ApexDangerousMethods, ApexDoc, ApexInsecureEndpoint, ApexOpenRedirect, ApexSharingViolations, ApexSOQLInjection, ApexSuggestUsingNamedCred, ApexUnitTestClassShouldHaveAsserts, ApexUnitTestShouldNotUseSeeAllDataTrue, ApexXSSFromEscapeFalse, ApexXSSFromURLParam, AvoidDeeplyNestedIfStmts, AvoidDirectAccessTriggerMap, AvoidDmlStatementsInLoops, AvoidGlobalModifier, AvoidHardcodingId, AvoidLogicInTrigger, AvoidNonExistentAnnotations, AvoidSoqlInLoops, AvoidSoslInLoops, ClassNamingConventions, CyclomaticComplexity, EmptyCatchBlock, EmptyIfStmt, EmptyStatementBlock, EmptyTryOrFinallyBlock, EmptyWhileStmt, ExcessiveClassLength, ExcessiveParameterList, ExcessivePublicCount, ForLoopsMustUseBraces, IfElseStmtsMustUseBraces, IfStmtsMustUseBraces, MethodNamingConventions, MethodWithSameNameAsEnclosingClass, NcssConstructorCount, NcssMethodCount, NcssTypeCount, OneDeclarationPerLine, StdCyclomaticComplexity, TooManyFields, VariableNamingConventions, WhileLoopsMustUseBraces
+Empty Code (rulesets/apex/empty.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ +EmptyCatchBlock, EmptyIfStmt, EmptyStatementBlock, EmptyTryOrFinallyBlock, EmptyWhileStmt
+Metrics temporary ruleset (rulesets/apex/metrics.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ + +Performance (rulesets/apex/performance.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ +AvoidDmlStatementsInLoops, AvoidSoqlInLoops, AvoidSoslInLoops
+quickstart (rulesets/apex/quickstart.xml
):
Quickstart configuration of PMD for Salesforce.com Apex. Includes the rules that are most likely to apply everywhere.
+ +It contains the following rules:
+ +ApexBadCrypto, ApexCRUDViolation, ApexCSRF, ApexDangerousMethods, ApexDoc, ApexInsecureEndpoint, ApexOpenRedirect, ApexSharingViolations, ApexSOQLInjection, ApexSuggestUsingNamedCred, ApexUnitTestClassShouldHaveAsserts, ApexUnitTestShouldNotUseSeeAllDataTrue, ApexXSSFromEscapeFalse, ApexXSSFromURLParam, AvoidDeeplyNestedIfStmts, AvoidDirectAccessTriggerMap, AvoidGlobalModifier, AvoidHardcodingId, AvoidLogicInTrigger, AvoidNonExistentAnnotations, ClassNamingConventions, CyclomaticComplexity, DebugsShouldUseLoggingLevel, EmptyCatchBlock, EmptyIfStmt, EmptyStatementBlock, EmptyTryOrFinallyBlock, EmptyWhileStmt, ExcessiveClassLength, ExcessiveParameterList, ExcessivePublicCount, FieldNamingConventions, ForLoopsMustUseBraces, FormalParameterNamingConventions, IfElseStmtsMustUseBraces, IfStmtsMustUseBraces, LocalVariableNamingConventions, MethodNamingConventions, MethodWithSameNameAsEnclosingClass, NcssConstructorCount, NcssMethodCount, NcssTypeCount, OneDeclarationPerLine, OperationWithLimitsInLoop, PropertyNamingConventions, StdCyclomaticComplexity, TooManyFields, WhileLoopsMustUseBraces
+Security (rulesets/apex/security.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ +ApexBadCrypto, ApexCRUDViolation, ApexCSRF, ApexDangerousMethods, ApexInsecureEndpoint, ApexOpenRedirect, ApexSharingViolations, ApexSOQLInjection, ApexSuggestUsingNamedCred, ApexXSSFromEscapeFalse, ApexXSSFromURLParam
+Style (rulesets/apex/style.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ +AvoidDirectAccessTriggerMap, AvoidGlobalModifier, AvoidHardcodingId, AvoidLogicInTrigger, ClassNamingConventions, MethodNamingConventions, MethodWithSameNameAsEnclosingClass, VariableNamingConventions
+Since: PMD 6.13.0
+ +Priority: Medium (3)
+ +The second parameter of System.assert/third parameter of System.assertEquals/System.assertNotEquals is a message. +Having a second/third parameter provides more information and makes it easier to debug the test failure and +improves the readability of test output.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.bestpractices.ApexAssertionsShouldIncludeMessageRule
+ +Example(s):
+ +@isTest
+public class Foo {
+ @isTest
+ static void methodATest() {
+ System.assertNotEquals('123', o.StageName); // not good
+ System.assertEquals('123', o.StageName, 'Opportunity stageName is wrong.'); // good
+ System.assert(o.isClosed); // not good
+ System.assert(o.isClosed, 'Opportunity is not closed.'); // good
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Bug Risk | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +100 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/bestpractices.xml/ApexAssertionsShouldIncludeMessage" />
+
Since: PMD 5.5.1
+ +Priority: Medium (3)
+ +Apex unit tests should include at least one assertion. This makes the tests more robust, and using assert +with messages provide the developer a clearer idea of what the test does.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.bestpractices.ApexUnitTestClassShouldHaveAssertsRule
+ +Example(s):
+ +@isTest
+public class Foo {
+ public static testMethod void testSomething() {
+ Account a = null;
+ // This is better than having a NullPointerException
+ // System.assertNotEquals(a, null, 'account not found');
+ a.toString();
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Bug Risk | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +100 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/bestpractices.xml/ApexUnitTestClassShouldHaveAsserts" />
+
Since: PMD 6.13.0
+ +Priority: Medium (3)
+ +Apex test methods should have @isTest annotation. +As testMethod keyword is deprecated, Salesforce advices to use @isTest annotation for test class/methods.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.bestpractices.ApexUnitTestMethodShouldHaveIsTestAnnotationRule
+ +Example(s):
+ +@isTest
+private class ATest {
+ @isTest
+ static void methodATest() {
+ }
+ static void methodBTest() {
+ }
+ @isTest static void methodCTest() {
+ System.assert(1==2);
+ }
+ @isTest static void methodCTest() {
+ System.debug('I am a debug statement');
+ }
+ private void fetchData() {
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Bug Risk | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +100 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/bestpractices.xml/ApexUnitTestMethodShouldHaveIsTestAnnotation" />
+
Since: PMD 5.5.1
+ +Priority: Medium (3)
+ +Apex unit tests should not use @isTest(seeAllData=true) because it opens up the existing database data for unexpected modification by tests.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.bestpractices.ApexUnitTestShouldNotUseSeeAllDataTrueRule
+ +Example(s):
+ +@isTest(seeAllData = true)
+public class Foo {
+ public static testMethod void testSomething() {
+ Account a = null;
+ // This is better than having a NullPointerException
+ // System.assertNotEquals(a, null, 'account not found');
+ a.toString();
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Bug Risk | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +100 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/bestpractices.xml/ApexUnitTestShouldNotUseSeeAllDataTrue" />
+
Since: PMD 5.5.0
+ +Priority: Medium (3)
+ +Global classes should be avoided (especially in managed packages) as they can never be deleted or changed in signature. Always check twice if something needs to be global. +Many interfaces (e.g. Batch) required global modifiers in the past but don’t require this anymore. Don’t lock yourself in.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.bestpractices.AvoidGlobalModifierRule
+ +Example(s):
+ +global class Unchangeable {
+ global UndeletableType unchangable(UndeletableType param) {
+ // ...
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Style | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +100 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/bestpractices.xml/AvoidGlobalModifier" />
+
Since: PMD 5.5.0
+ +Priority: Medium (3)
+ +As triggers do not allow methods like regular classes they are less flexible and suited to apply good encapsulation style. +Therefore delegate the triggers work to a regular class (often called Trigger handler class).
+ +See more here: https://developer.salesforce.com/page/Trigger_Frameworks_and_Apex_Trigger_Best_Practices
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.bestpractices.AvoidLogicInTriggerRule
+ +Example(s):
+ +trigger Accounts on Account (before insert, before update, before delete, after insert, after update, after delete, after undelete) {
+ for(Account acc : Trigger.new) {
+ if(Trigger.isInsert) {
+ // ...
+ }
+
+ // ...
+
+ if(Trigger.isDelete) {
+ // ...
+ }
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Style | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +200 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/bestpractices.xml/AvoidLogicInTrigger" />
+
Since: PMD 6.18.0
+ +Priority: Medium (3)
+ +The first parameter of System.debug, when using the signature with two parameters, is a LoggingLevel enum.
+ +Having the Logging Level specified provides a cleaner log, and improves readability of it.
+ +This rule is defined by the following XPath expression:
+//MethodCallExpression[lower-case(@FullMethodName)='system.debug'][count(*)=2
+ or ($strictMode=true() and count(*)=3 and lower-case(VariableExpression/@Image)='debug')]
+
Example(s):
+ +@isTest
+public class Foo {
+ @isTest
+ static void bar() {
+ System.debug('Hey this code executed.'); // not good
+ System.debug(LoggingLevel.WARN, 'Hey, something might be wrong.'); // good
+ System.debug(LoggingLevel.DEBUG, 'Hey, something happened.'); // not good when on strict mode
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Style | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +1 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
strictMode | +false | +If true, mark statements that use the DEBUG enum of LoggingLevel. | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/bestpractices.xml/DebugsShouldUseLoggingLevel" />
+
Use this rule and customize it:
+<rule ref="category/apex/bestpractices.xml/DebugsShouldUseLoggingLevel">
+ <properties>
+ <property name="strictMode" value="false" />
+ </properties>
+</rule>
+
Since: PMD 6.23.0
+ +Priority: Low (5)
+ +Detects when a local variable is declared and/or assigned but not used.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.bestpractices.UnusedLocalVariableRule
+ +Example(s):
+ +public Boolean bar(String z) {
+ String x = 'some string'; // not used
+
+ String y = 'some other string'; // used in the next line
+ return z.equals(y);
+ }
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Style | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +1 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/bestpractices.xml/UnusedLocalVariable" />
+
Since: PMD 5.5.0
+ +Priority: High (1)
+ +Configurable naming conventions for type declarations. This rule reports +type declarations which do not match the regex that applies to their +specific kind (e.g. enum or interface). Each regex can be configured through +properties.
+ +By default this rule uses the standard Apex naming convention (Pascal case).
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.codestyle.ClassNamingConventionsRule
+ +Example(s):
+ +public class FooClass { } // This is in pascal case, so it's ok
+
+public class fooClass { } // This will be reported unless you change the regex
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Style | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +5 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
testClassPattern | +[A-Z][a-zA-Z0-9_]* | +Regex which applies to test class names | +no | +
abstractClassPattern | +[A-Z][a-zA-Z0-9_]* | +Regex which applies to abstract class names | +no | +
classPattern | +[A-Z][a-zA-Z0-9_]* | +Regex which applies to class names | +no | +
interfacePattern | +[A-Z][a-zA-Z0-9_]* | +Regex which applies to interface names | +no | +
enumPattern | +[A-Z][a-zA-Z0-9_]* | +Regex which applies to enum names | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/codestyle.xml/ClassNamingConventions" />
+
Use this rule and customize it:
+<rule ref="category/apex/codestyle.xml/ClassNamingConventions">
+ <properties>
+ <property name="testClassPattern" value="[A-Z][a-zA-Z0-9_]*" />
+ <property name="abstractClassPattern" value="[A-Z][a-zA-Z0-9_]*" />
+ <property name="classPattern" value="[A-Z][a-zA-Z0-9_]*" />
+ <property name="interfacePattern" value="[A-Z][a-zA-Z0-9_]*" />
+ <property name="enumPattern" value="[A-Z][a-zA-Z0-9_]*" />
+ </properties>
+</rule>
+
Since: PMD 6.23.0
+ +Priority: Medium (3)
+ +Field declarations should appear before method declarations within a class.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.codestyle.FieldDeclarationsShouldBeAtStartRule
+ +Example(s):
+ +class Foo {
+ public Integer someField; // good
+
+ public void someMethod() {
+ }
+
+ public Integer anotherField; // bad
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Style | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +1 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/codestyle.xml/FieldDeclarationsShouldBeAtStart" />
+
Since: PMD 6.15.0
+ +Priority: High (1)
+ +Configurable naming conventions for field declarations. This rule reports variable declarations +which do not match the regex that applies to their specific kind —e.g. constants (static final), +static field, final field. Each regex can be configured through properties.
+ +By default this rule uses the standard Apex naming convention (Camel case).
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.codestyle.FieldNamingConventionsRule
+ +Example(s):
+ +public class Foo {
+ Integer instanceField; // This is in camel case, so it's ok
+
+ Integer INSTANCE_FIELD; // This will be reported unless you change the regex
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Style | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +1 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
enumConstantPattern | +[A-Z][A-Z0-9_]* | +Regex which applies to enum constant field names | +no | +
constantPattern | +[A-Z][A-Z0-9_]* | +Regex which applies to constant field names | +no | +
finalPattern | +[a-z][a-zA-Z0-9]* | +Regex which applies to final field names | +no | +
staticPattern | +[a-z][a-zA-Z0-9]* | +Regex which applies to static field names | +no | +
instancePattern | +[a-z][a-zA-Z0-9]* | +Regex which applies to instance field names | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/codestyle.xml/FieldNamingConventions" />
+
Use this rule and customize it:
+<rule ref="category/apex/codestyle.xml/FieldNamingConventions">
+ <properties>
+ <property name="enumConstantPattern" value="[A-Z][A-Z0-9_]*" />
+ <property name="constantPattern" value="[A-Z][A-Z0-9_]*" />
+ <property name="finalPattern" value="[a-z][a-zA-Z0-9]*" />
+ <property name="staticPattern" value="[a-z][a-zA-Z0-9]*" />
+ <property name="instancePattern" value="[a-z][a-zA-Z0-9]*" />
+ </properties>
+</rule>
+
Since: PMD 5.6.0
+ +Priority: Medium (3)
+ +Avoid using ‘for’ statements without using surrounding braces. If the code formatting or +indentation is lost then it becomes difficult to separate the code being controlled +from the rest.
+ +This rule is defined by the following XPath expression:
+//ForLoopStatement/BlockStatement[@CurlyBrace= false()]
+|
+//ForEachStatement/BlockStatement[@CurlyBrace= false()]
+
Example(s):
+ +for (int i = 0; i < 42; i++) // not recommended
+ foo();
+
+for (int i = 0; i < 42; i++) { // preferred approach
+ foo();
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Style | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +1 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/codestyle.xml/ForLoopsMustUseBraces" />
+
Since: PMD 6.15.0
+ +Priority: High (1)
+ +Configurable naming conventions for formal parameters of methods. +This rule reports formal parameters which do not match the regex that applies to their +specific kind (e.g. method parameter, or final method parameter). Each regex can be +configured through properties.
+ +By default this rule uses the standard Apex naming convention (Camel case).
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.codestyle.FormalParameterNamingConventionsRule
+ +Example(s):
+ +public class Foo {
+ public bar(Integer methodParameter) { } // This is in camel case, so it's ok
+
+ public baz(Integer METHOD_PARAMETER) { } // This will be reported unless you change the regex
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Style | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +1 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
finalMethodParameterPattern | +[a-z][a-zA-Z0-9]* | +Regex which applies to final method parameter names | +no | +
methodParameterPattern | +[a-z][a-zA-Z0-9]* | +Regex which applies to method parameter names | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/codestyle.xml/FormalParameterNamingConventions" />
+
Use this rule and customize it:
+<rule ref="category/apex/codestyle.xml/FormalParameterNamingConventions">
+ <properties>
+ <property name="finalMethodParameterPattern" value="[a-z][a-zA-Z0-9]*" />
+ <property name="methodParameterPattern" value="[a-z][a-zA-Z0-9]*" />
+ </properties>
+</rule>
+
Since: PMD 5.6.0
+ +Priority: Medium (3)
+ +Avoid using if..else statements without using surrounding braces. If the code formatting +or indentation is lost then it becomes difficult to separate the code being controlled +from the rest.
+ +This rule is defined by the following XPath expression:
+//IfBlockStatement/BlockStatement[@CurlyBrace= false()][count(child::*) > 0]
+|
+//IfElseBlockStatement/BlockStatement[@CurlyBrace= false()][count(child::*) > 0]
+
Example(s):
+ +// this is OK
+if (foo) x++;
+
+// but this is not
+if (foo)
+ x = x+1;
+else
+ x = x-1;
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Style | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +1 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/codestyle.xml/IfElseStmtsMustUseBraces" />
+
Since: PMD 5.6.0
+ +Priority: Medium (3)
+ +Avoid using if statements without using braces to surround the code block. If the code +formatting or indentation is lost then it becomes difficult to separate the code being +controlled from the rest.
+ +This rule is defined by the following XPath expression:
+//IfBlockStatement/BlockStatement[@CurlyBrace= false()]
+
Example(s):
+ +if (foo) // not recommended
+ x++;
+
+if (foo) { // preferred approach
+ x++;
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Style | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +1 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/codestyle.xml/IfStmtsMustUseBraces" />
+
Since: PMD 6.15.0
+ +Priority: High (1)
+ +Configurable naming conventions for local variable declarations. +This rule reports variable declarations which do not match the regex that applies to their +specific kind (e.g. local variable, or final local variable). Each regex can be configured through +properties.
+ +By default this rule uses the standard Apex naming convention (Camel case).
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.codestyle.LocalVariableNamingConventionsRule
+ +Example(s):
+ +public class Foo {
+ public Foo() {
+ Integer localVariable; // This is in camel case, so it's ok
+
+ Integer LOCAL_VARIABLE; // This will be reported unless you change the regex
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Style | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +1 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
finalLocalPattern | +[a-z][a-zA-Z0-9]* | +Regex which applies to final local variable names | +no | +
localPattern | +[a-z][a-zA-Z0-9]* | +Regex which applies to local variable names | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/codestyle.xml/LocalVariableNamingConventions" />
+
Use this rule and customize it:
+<rule ref="category/apex/codestyle.xml/LocalVariableNamingConventions">
+ <properties>
+ <property name="finalLocalPattern" value="[a-z][a-zA-Z0-9]*" />
+ <property name="localPattern" value="[a-z][a-zA-Z0-9]*" />
+ </properties>
+</rule>
+
Since: PMD 5.5.0
+ +Priority: High (1)
+ +Configurable naming conventions for method declarations. This rule reports +method declarations which do not match the regex that applies to their +specific kind (e.g. static method, or test method). Each regex can be +configured through properties.
+ +By default this rule uses the standard Apex naming convention (Camel case).
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.codestyle.MethodNamingConventionsRule
+ +Example(s):
+ +public class Foo {
+ public void instanceMethod() { } // This is in camel case, so it's ok
+
+ public void INSTANCE_METHOD() { } // This will be reported unless you change the regex
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Style | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +1 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
skipTestMethodUnderscores | +false | +Deprecated Skip underscores in test methods | +no | +
testPattern | +[a-z][a-zA-Z0-9]* | +Regex which applies to test method names | +no | +
staticPattern | +[a-z][a-zA-Z0-9]* | +Regex which applies to static method names | +no | +
instancePattern | +[a-z][a-zA-Z0-9]* | +Regex which applies to instance method names | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/codestyle.xml/MethodNamingConventions" />
+
Use this rule and customize it:
+<rule ref="category/apex/codestyle.xml/MethodNamingConventions">
+ <properties>
+ <property name="testPattern" value="[a-z][a-zA-Z0-9]*" />
+ <property name="staticPattern" value="[a-z][a-zA-Z0-9]*" />
+ <property name="instancePattern" value="[a-z][a-zA-Z0-9]*" />
+ </properties>
+</rule>
+
Since: PMD 6.7.0
+ +Priority: High (1)
+ +Apex allows the use of several variables declaration of the same type on one line. However, it +can lead to quite messy code. This rule looks for several declarations on the same line.
+ +This rule is defined by the following XPath expression:
+//VariableDeclarationStatements
+ [count(VariableDeclaration) > 1]
+ [$strictMode or count(distinct-values(VariableDeclaration/@BeginLine)) != count(VariableDeclaration)]
+|
+//FieldDeclarationStatements
+ [count(FieldDeclaration) > 1]
+ [$strictMode or count(distinct-values(FieldDeclaration/VariableExpression/@BeginLine)) != count(FieldDeclaration/VariableExpression)]
+
Example(s):
+ +Integer a, b; // not recommended
+
+Integer a,
+ b; // ok by default, can be flagged setting the strictMode property
+
+Integer a; // preferred approach
+Integer b;
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Style | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +1 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
strictMode | +false | +If true, mark combined declaration even if the declarations are on separate lines. | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/codestyle.xml/OneDeclarationPerLine" />
+
Use this rule and customize it:
+<rule ref="category/apex/codestyle.xml/OneDeclarationPerLine">
+ <properties>
+ <property name="strictMode" value="false" />
+ </properties>
+</rule>
+
Since: PMD 6.15.0
+ +Priority: High (1)
+ +Configurable naming conventions for property declarations. This rule reports +property declarations which do not match the regex that applies to their +specific kind (e.g. static property, or instance property). Each regex can be +configured through properties.
+ +By default this rule uses the standard Apex naming convention (Camel case).
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.codestyle.PropertyNamingConventionsRule
+ +Example(s):
+ +public class Foo {
+ public Integer instanceProperty { get; set; } // This is in camel case, so it's ok
+
+ public Integer INSTANCE_PROPERTY { get; set; } // This will be reported unless you change the regex
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Style | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +1 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
staticPattern | +[a-z][a-zA-Z0-9]* | +Regex which applies to static property names | +no | +
instancePattern | +[a-z][a-zA-Z0-9]* | +Regex which applies to instance property names | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/codestyle.xml/PropertyNamingConventions" />
+
Use this rule and customize it:
+<rule ref="category/apex/codestyle.xml/PropertyNamingConventions">
+ <properties>
+ <property name="staticPattern" value="[a-z][a-zA-Z0-9]*" />
+ <property name="instancePattern" value="[a-z][a-zA-Z0-9]*" />
+ </properties>
+</rule>
+
Deprecated
+ +Since: PMD 5.5.0
+ +Priority: High (1)
+ +A variable naming conventions rule - customize this to your liking. Currently, it +checks for final variables that should be fully capitalized and non-final variables +that should not include underscores.
+ +This rule is deprecated and will be removed with PMD 7.0.0. The rule is replaced
+by the more general rules FieldNamingConventions
,
+FormalParameterNamingConventions
,
+LocalVariableNamingConventions
, and
+PropertyNamingConventions
.
This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.codestyle.VariableNamingConventionsRule
+ +Example(s):
+ +public class Foo {
+ public static final Integer MY_NUM = 0;
+ public String myTest = '';
+ DataModule dmTest = new DataModule();
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Style | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +5 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated 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 with the default properties by just referencing it:
+<rule ref="category/apex/codestyle.xml/VariableNamingConventions" />
+
Use this rule and customize it:
+<rule ref="category/apex/codestyle.xml/VariableNamingConventions">
+ <properties>
+ <property name="checkMembers" value="true" />
+ <property name="checkLocals" value="true" />
+ <property name="checkParameters" value="true" />
+ <property name="staticPrefix" value="" />
+ <property name="staticSuffix" value="" />
+ <property name="memberPrefix" value="" />
+ <property name="memberSuffix" value="" />
+ <property name="localPrefix" value="" />
+ <property name="localSuffix" value="" />
+ <property name="parameterPrefix" value="" />
+ <property name="parameterSuffix" value="" />
+ </properties>
+</rule>
+
Since: PMD 5.6.0
+ +Priority: Medium (3)
+ +Avoid using ‘while’ statements without using braces to surround the code block. If the code +formatting or indentation is lost then it becomes difficult to separate the code being +controlled from the rest.
+ +This rule is defined by the following XPath expression:
+//WhileLoopStatement/BlockStatement[@CurlyBrace= false()]
+
Example(s):
+ +while (true) // not recommended
+ x++;
+
+while (true) { // preferred approach
+ x++;
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Style | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +1 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/codestyle.xml/WhileLoopsMustUseBraces" />
+
Since: PMD 5.5.0
+ +Priority: Medium (3)
+ +Avoid creating deeply nested if-then statements since they are harder to read and error-prone to maintain.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.design.AvoidDeeplyNestedIfStmtsRule
+ +Example(s):
+ +public class Foo {
+ public void bar(Integer x, Integer y, Integer z) {
+ if (x>y) {
+ if (y>z) {
+ if (z==x) {
+ // !! too deep
+ }
+ }
+ }
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Complexity | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +200 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
problemDepth | +3 | +The if statement depth reporting threshold | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/design.xml/AvoidDeeplyNestedIfStmts" />
+
Use this rule and customize it:
+<rule ref="category/apex/design.xml/AvoidDeeplyNestedIfStmts">
+ <properties>
+ <property name="problemDepth" value="3" />
+ </properties>
+</rule>
+
Since: PMD 6.22.0
+ +Priority: Medium (3)
+ +Methods that are highly complex are difficult to read and more costly to maintain. If you include too much decisional +logic within a single method, you make its behavior hard to understand and more difficult to modify.
+ +Cognitive complexity is a measure of how difficult it is for humans to read and understand a method. Code that contains +a break in the control flow is more complex, whereas the use of language shorthands doesn’t increase the level of +complexity. Nested control flows can make a method more difficult to understand, with each additional nesting of the +control flow leading to an increase in cognitive complexity.
+ +Information about Cognitive complexity can be found in the original paper here: +https://www.sonarsource.com/docs/CognitiveComplexity.pdf
+ +By default, this rule reports methods with a complexity of 15 or more. Reported methods should be broken down into less +complex components.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.design.CognitiveComplexityRule
+ +Example(s):
+ +public class Foo {
+ // Has a cognitive complexity of 0
+ public void createAccount() {
+ Account account = new Account(Name = 'PMD');
+ insert account;
+ }
+
+ // Has a cognitive complexity of 1
+ public Boolean setPhoneNumberIfNotExisting(Account a, String phone) {
+ if (a.Phone == null) { // +1
+ a.Phone = phone;
+ update a;
+ return true;
+ }
+
+ return false;
+ }
+
+ // Has a cognitive complexity of 5
+ public void updateContacts(List<Contact> contacts) {
+ List<Contact> contactsToUpdate = new List<Contact>();
+
+ for (Contact contact : contacts) { // +1
+ if (contact.Department == 'Finance') { // +2
+ contact.Title = 'Finance Specialist';
+ contactsToUpdate.add(contact);
+ } else if (contact.Department == 'Sales') { // +2
+ contact.Title = 'Sales Specialist';
+ contactsToUpdate.add(contact);
+ }
+ }
+
+ update contactsToUpdate;
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Style | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +1 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
classReportLevel | +50 | +Total class cognitive complexity reporting threshold | +no | +
methodReportLevel | +15 | +Cognitive complexity reporting threshold | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/design.xml/CognitiveComplexity" />
+
Use this rule and customize it:
+<rule ref="category/apex/design.xml/CognitiveComplexity">
+ <properties>
+ <property name="classReportLevel" value="50" />
+ <property name="methodReportLevel" value="15" />
+ </properties>
+</rule>
+
Since: PMD 6.0.0
+ +Priority: Medium (3)
+ +The complexity of methods directly affects maintenance costs and readability. Concentrating too much decisional logic +in a single method makes its behaviour hard to read and change.
+ +Cyclomatic complexity assesses the complexity of a method by counting the number of decision points in a method, +plus one for the method entry. Decision points are places where the control flow jumps to another place in the +program. As such, they include all control flow statements, such as ‘if’, ‘while’, ‘for’, and ‘case’.
+ +Generally, numbers ranging from 1-4 denote low complexity, 5-7 denote moderate complexity, 8-10 denote +high complexity, and 11+ is very high complexity. By default, this rule reports methods with a complexity >= 10. +Additionally, classes with many methods of moderate complexity get reported as well once the total of their +methods’ complexities reaches 40, even if none of the methods was directly reported.
+ +Reported methods should be broken down into several smaller methods. Reported classes should probably be broken down +into subcomponents.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.design.CyclomaticComplexityRule
+ +Example(s):
+ +public class Complicated {
+ public void example() { // This method has a cyclomatic complexity of 12
+ int x = 0, y = 1, z = 2, t = 2;
+ boolean a = false, b = true, c = false, d = true;
+ if (a && b || b && d) {
+ if (y == z) {
+ x = 2;
+ } else if (y == t && !d) {
+ x = 2;
+ } else {
+ x = 2;
+ }
+ } else if (c && d) {
+ while (z < y) {
+ x = 2;
+ }
+ } else {
+ for (int n = 0; n < t; n++) {
+ x = 2;
+ }
+ }
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Style | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +1 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
classReportLevel | +40 | +Total class complexity reporting threshold | +no | +
methodReportLevel | +10 | +Cyclomatic complexity reporting threshold | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/design.xml/CyclomaticComplexity" />
+
Use this rule and customize it:
+<rule ref="category/apex/design.xml/CyclomaticComplexity">
+ <properties>
+ <property name="classReportLevel" value="40" />
+ <property name="methodReportLevel" value="10" />
+ </properties>
+</rule>
+
Since: PMD 5.5.0
+ +Priority: Medium (3)
+ +Excessive class file lengths are usually indications that the class may be burdened with excessive +responsibilities that could be provided by external classes or functions. In breaking these methods +apart the code becomes more managable and ripe for reuse.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.design.ExcessiveClassLengthRule
+ +Example(s):
+ +public class Foo {
+ public void bar1() {
+ // 1000 lines of code
+ }
+ public void bar2() {
+ // 1000 lines of code
+ }
+ public void bar3() {
+ // 1000 lines of code
+ }
+ public void barN() {
+ // 1000 lines of code
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
topscore | ++ | Deprecated Top score value | +no | +
minimum | +1000.0 | +Minimum reporting threshold | +no | +
cc_categories | +Complexity | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +150 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
sigma | ++ | Deprecated Sigma value | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/design.xml/ExcessiveClassLength" />
+
Use this rule and customize it:
+<rule ref="category/apex/design.xml/ExcessiveClassLength">
+ <properties>
+ <property name="minimum" value="1000.0" />
+ </properties>
+</rule>
+
Since: PMD 5.5.0
+ +Priority: Medium (3)
+ +Methods with numerous parameters are a challenge to maintain, especially if most of them share the +same datatype. These situations usually denote the need for new objects to wrap the numerous parameters.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.design.ExcessiveParameterListRule
+ +Example(s):
+ +// too many arguments liable to be mixed up
+public void addPerson(Integer birthYear, Integer birthMonth, Integer birthDate, Integer height, Integer weight, Integer ssn) {
+ // ...
+}
+// preferred approach
+public void addPerson(Date birthdate, BodyMeasurements measurements, int ssn) {
+ // ...
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
topscore | ++ | Deprecated Top score value | +no | +
minimum | +4.0 | +Minimum reporting threshold | +no | +
cc_categories | +Complexity | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +50 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
sigma | ++ | Deprecated Sigma value | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/design.xml/ExcessiveParameterList" />
+
Use this rule and customize it:
+<rule ref="category/apex/design.xml/ExcessiveParameterList">
+ <properties>
+ <property name="minimum" value="4.0" />
+ </properties>
+</rule>
+
Since: PMD 5.5.0
+ +Priority: Medium (3)
+ +Classes with large numbers of public methods and attributes require disproportionate testing efforts +since combinational side effects grow rapidly and increase risk. Refactoring these classes into +smaller ones not only increases testability and reliability but also allows new variations to be +developed easily.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.design.ExcessivePublicCountRule
+ +Example(s):
+ +public class Foo {
+ public String value;
+ public Bar something;
+ public Variable var;
+ // [... more more public attributes ...]
+
+ public void doWork() {}
+ public void doMoreWork() {}
+ public void doWorkAgain() {}
+ // [... more more public methods ...]
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
topscore | ++ | Deprecated Top score value | +no | +
minimum | +20.0 | +Minimum reporting threshold | +no | +
cc_categories | +Complexity | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +150 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
sigma | ++ | Deprecated Sigma value | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/design.xml/ExcessivePublicCount" />
+
Use this rule and customize it:
+<rule ref="category/apex/design.xml/ExcessivePublicCount">
+ <properties>
+ <property name="minimum" value="20.0" />
+ </properties>
+</rule>
+
Since: PMD 5.5.0
+ +Priority: Medium (3)
+ +This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of lines +of code for a given constructor. NCSS ignores comments, and counts actual statements. Using this algorithm, +lines of code that are split are counted as one.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.design.NcssConstructorCountRule
+ +Example(s):
+ +public class Foo extends Bar {
+ //this constructor only has 1 NCSS lines
+ public Foo() {
+ super();
+
+
+
+
+ super.foo();
+}
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
topscore | ++ | Deprecated Top score value | +no | +
minimum | +20.0 | +Minimum reporting threshold | +no | +
cc_categories | +Complexity | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +50 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
sigma | ++ | Deprecated Sigma value | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/design.xml/NcssConstructorCount" />
+
Use this rule and customize it:
+<rule ref="category/apex/design.xml/NcssConstructorCount">
+ <properties>
+ <property name="minimum" value="20.0" />
+ </properties>
+</rule>
+
Since: PMD 5.5.0
+ +Priority: Medium (3)
+ +This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of lines +of code for a given method. NCSS ignores comments, and counts actual statements. Using this algorithm, +lines of code that are split are counted as one.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.design.NcssMethodCountRule
+ +Example(s):
+ +public class Foo extends Bar {
+ //this method only has 1 NCSS lines
+ public Integer method() {
+ super.method();
+
+
+
+ return 1;
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
topscore | ++ | Deprecated Top score value | +no | +
minimum | +40.0 | +Minimum reporting threshold | +no | +
cc_categories | +Complexity | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +50 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
sigma | ++ | Deprecated Sigma value | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/design.xml/NcssMethodCount" />
+
Use this rule and customize it:
+<rule ref="category/apex/design.xml/NcssMethodCount">
+ <properties>
+ <property name="minimum" value="40.0" />
+ </properties>
+</rule>
+
Since: PMD 5.5.0
+ +Priority: Medium (3)
+ +This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of lines +of code for a given type. NCSS ignores comments, and counts actual statements. Using this algorithm, +lines of code that are split are counted as one.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.design.NcssTypeCountRule
+ +Example(s):
+ +//this class only has 6 NCSS lines
+public class Foo extends Bar {
+ public Foo() {
+ super();
+
+
+
+
+
+ super.foo();
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
topscore | ++ | Deprecated Top score value | +no | +
minimum | +500.0 | +Minimum reporting threshold | +no | +
cc_categories | +Complexity | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +250 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
sigma | ++ | Deprecated Sigma value | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/design.xml/NcssTypeCount" />
+
Use this rule and customize it:
+<rule ref="category/apex/design.xml/NcssTypeCount">
+ <properties>
+ <property name="minimum" value="500.0" />
+ </properties>
+</rule>
+
Since: PMD 5.5.0
+ +Priority: Medium (3)
+ +Complexity directly affects maintenance costs is determined by the number of decision points in a method +plus one for the method entry. The decision points include ‘if’, ‘while’, ‘for’, and ‘case labels’ calls. +Generally, numbers ranging from 1-4 denote low complexity, 5-7 denote moderate complexity, 8-10 denote +high complexity, and 11+ is very high complexity.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.design.StdCyclomaticComplexityRule
+ +Example(s):
+ +// This has a Cyclomatic Complexity = 12
+public class Foo {
+1 public void example() {
+2 if (a == b || (c == d && e == f)) {
+3 if (a1 == b1) {
+ fiddle();
+4 } else if a2 == b2) {
+ fiddle();
+ } else {
+ fiddle();
+ }
+5 } else if (c == d) {
+6 while (c == d) {
+ fiddle();
+ }
+7 } else if (e == f) {
+8 for (int n = 0; n < h; n++) {
+ fiddle();
+ }
+ } else {
+ switch (z) {
+9 case 1:
+ fiddle();
+ break;
+10 case 2:
+ fiddle();
+ break;
+11 case 3:
+ fiddle();
+ break;
+12 default:
+ fiddle();
+ break;
+ }
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Complexity | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +250 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated 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 with the default properties by just referencing it:
+<rule ref="category/apex/design.xml/StdCyclomaticComplexity" />
+
Use this rule and customize it:
+<rule ref="category/apex/design.xml/StdCyclomaticComplexity">
+ <properties>
+ <property name="reportLevel" value="10" />
+ <property name="showClassesComplexity" value="true" />
+ <property name="showMethodsComplexity" value="true" />
+ </properties>
+</rule>
+
Since: PMD 5.5.0
+ +Priority: Medium (3)
+ +Classes that have too many fields can become unwieldy and could be redesigned to have fewer fields, +possibly through grouping related fields in new objects. For example, a class with individual +city/state/zip fields could park them within a single Address field.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.design.TooManyFieldsRule
+ +Example(s):
+ +public class Person {
+ // too many separate fields
+ Integer birthYear;
+ Integer birthMonth;
+ Integer birthDate;
+ Double height;
+ Double weight;
+}
+
+public class Person {
+ // this is more manageable
+ Date birthDate;
+ BodyMeasurements measurements;
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Complexity | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +200 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
maxfields | +15 | +Max allowable fields | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/design.xml/TooManyFields" />
+
Use this rule and customize it:
+<rule ref="category/apex/design.xml/TooManyFields">
+ <properties>
+ <property name="maxfields" value="15" />
+ </properties>
+</rule>
+
Since: PMD 6.8.0
+ +Priority: Medium (3)
+ +This rule validates that:
+ +Method overrides and tests are both exempted from having ApexDoc.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.documentation.ApexDocRule
+ +Example(s):
+ +/**
+ * @description Hello World
+ */
+public class HelloWorld {
+ /**
+ * @description Bar
+ * @return Bar
+ */
+ public Object bar() { return null; }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Style | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +1 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/documentation.xml/ApexDoc" />
+
Since: PMD 5.5.3
+ +Priority: Medium (3)
+ +Having DML operations in Apex class constructor or initializers can have unexpected side effects: +By just accessing a page, the DML statements would be executed and the database would be modified. +Just querying the database is permitted.
+ +In addition to constructors and initializers, any method called init
is checked as well.
Salesforce Apex already protects against this scenario and raises a runtime exception.
+ +Note: This rule has been moved from category "Security" to "Error Prone" with PMD 6.21.0, since +using DML in constructors is not a security problem, but crashes the application.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.errorprone.ApexCSRFRule
+ +Example(s):
+ +public class Foo {
+ // initializer
+ {
+ insert data;
+ }
+
+ // static initializer
+ static {
+ insert data;
+ }
+
+ // constructor
+ public Foo() {
+ insert data;
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Security | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +100 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/errorprone.xml/ApexCSRF" />
+
Since: PMD 6.0.0
+ +Priority: Medium (3)
+ +Avoid directly accessing Trigger.old and Trigger.new as it can lead to a bug. Triggers should be bulkified and iterate through the map to handle the actions for each item separately.
+ +This rule is defined by the following XPath expression:
+//ArrayLoadExpression[TriggerVariableExpression and LiteralExpression]
+
Example(s):
+ +trigger AccountTrigger on Account (before insert, before update) {
+ Account a = Trigger.new[0]; //Bad: Accessing the trigger array directly is not recommended.
+
+ for ( Account a : Trigger.new ) {
+ //Good: Iterate through the trigger.new array instead.
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Style | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +1 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/errorprone.xml/AvoidDirectAccessTriggerMap" />
+
Since: PMD 6.0.0
+ +Priority: Medium (3)
+ +When deploying Apex code between sandbox and production environments, or installing Force.com AppExchange packages, +it is essential to avoid hardcoding IDs in the Apex code. By doing so, if the record IDs change between environments, +the logic can dynamically identify the proper data to operate against and not fail.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.errorprone.AvoidHardcodingIdRule
+ +Example(s):
+ +public without sharing class Foo {
+ void foo() {
+ //Error - hardcoded the record type id
+ if (a.RecordTypeId == '012500000009WAr') {
+ //do some logic here.....
+ } else if (a.RecordTypeId == '0123000000095Km') {
+ //do some logic here for a different record type...
+ }
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Style | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +100 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/errorprone.xml/AvoidHardcodingId" />
+
Since: PMD 6.5.0
+ +Priority: Medium (3)
+ +Apex supported non existent annotations for legacy reasons. +In the future, use of such non-existent annotations could result in broken apex code that will not compile. +This will prevent users of garbage annotations from being able to use legitimate annotations added to Apex in the future. +A full list of supported annotations can be found at https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_annotation.htm
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.errorprone.AvoidNonExistentAnnotationsRule
+ +Example(s):
+ +@NonExistentAnnotation public class ClassWithNonexistentAnnotation {
+ @NonExistentAnnotation public void methodWithNonExistentAnnotation() {
+ // ...
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Style | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +1 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/errorprone.xml/AvoidNonExistentAnnotations" />
+
Since: PMD 6.0.0
+ +Priority: Medium (3)
+ +Empty Catch Block finds instances where an exception is caught, but nothing is done. +In most circumstances, this swallows an exception which should either be acted on +or reported.
+ +This rule is defined by the following XPath expression:
+//CatchBlockStatement[./BlockStatement[count(*) = 0]]
+
Example(s):
+ +public void doSomething() {
+ ...
+ try {
+ insert accounts;
+ } catch (DmlException dmle) {
+ // not good
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Style | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +1 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/errorprone.xml/EmptyCatchBlock" />
+
Since: PMD 6.0.0
+ +Priority: Medium (3)
+ +Empty If Statement finds instances where a condition is checked but nothing is done about it.
+ +This rule is defined by the following XPath expression:
+//IfBlockStatement
+ [BlockStatement[count(*) = 0]]
+
Example(s):
+ +public class Foo {
+ public void bar(Integer x) {
+ if (x == 0) {
+ // empty!
+ }
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Style | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +1 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/errorprone.xml/EmptyIfStmt" />
+
Since: PMD 6.0.0
+ +Priority: Medium (3)
+ +Empty block statements serve no purpose and should be removed.
+ +This rule is defined by the following XPath expression:
+//Method/ModifierNode[@Abstract!= true() and ../BlockStatement[count(*) = 0]]
+| //Method/BlockStatement//BlockStatement[count(*) = 0 and @Location != parent::*/@Location]
+
Example(s):
+ +public class Foo {
+
+ private Integer _bar;
+
+ public void setBar(Integer bar) {
+ // empty
+ }
+
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Style | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +1 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/errorprone.xml/EmptyStatementBlock" />
+
Since: PMD 6.0.0
+ +Priority: Medium (3)
+ +Avoid empty try or finally blocks - what’s the point?
+ +This rule is defined by the following XPath expression:
+//TryCatchFinallyBlockStatement[./BlockStatement[count(*) = 0]]
+
Example(s):
+ +public class Foo {
+ public void bar() {
+ try {
+ // empty !
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
+
+public class Foo {
+ public void bar() {
+ try {
+ Integer x=2;
+ } finally {
+ // empty!
+ }
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Style | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +1 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/errorprone.xml/EmptyTryOrFinallyBlock" />
+
Since: PMD 6.0.0
+ +Priority: Medium (3)
+ +Empty While Statement finds all instances where a while statement does nothing. +If it is a timing loop, then you should use Thread.sleep() for it; if it is +a while loop that does a lot in the exit expression, rewrite it to make it clearer.
+ +This rule is defined by the following XPath expression:
+//WhileLoopStatement[./BlockStatement[count(*) = 0]]
+
Example(s):
+ +public void bar(Integer a, Integer b) {
+ while (a == b) {
+ // empty!
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Style | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +1 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/errorprone.xml/EmptyWhileStmt" />
+
Since: PMD 5.5.0
+ +Priority: Medium (3)
+ +Non-constructor methods should not have the same name as the enclosing class.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.errorprone.MethodWithSameNameAsEnclosingClassRule
+ +Example(s):
+ +public class MyClass {
+ // this is OK because it is a constructor
+ public MyClass() {}
+ // this is bad because it is a method
+ public void MyClass() {}
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Style | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +50 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/errorprone.xml/MethodWithSameNameAsEnclosingClass" />
+
Since: PMD 6.22.0
+ +Priority: Medium (3)
+ +Test methods marked as a testMethod or annotated with @IsTest, +but not residing in a test class should be moved to a proper +class or have the @IsTest annotation added to the class.
+ +Support for tests inside functional classes was removed in Spring-13 (API Version 27.0), +making classes that violate this rule fail compile-time. This rule is mostly usable when +dealing with legacy code.
+ +This rule is defined by the following XPath expression:
+//UserClass[
+ not(./ModifierNode/Annotation[lower-case(@Image) = 'istest']) and
+ (
+ (./Method/ModifierNode/Annotation[lower-case(@Image) = 'istest']) or
+ (./Method/ModifierNode[@Test = true()])
+ )
+ ]
+
Example(s):
+ +// Violating
+private class TestClass {
+ @IsTest static void myTest() {
+ // Code here
+ }
+}
+
+private class TestClass {
+ static testMethod void myTest() {
+ // Code here
+ }
+}
+
+// Compliant
+@IsTest
+private class TestClass {
+ @IsTest static void myTest() {
+ // Code here
+ }
+}
+
+@IsTest
+private class TestClass {
+ static testMethod void myTest() {
+ // Code here
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Style | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +1 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/errorprone.xml/TestMethodsMustBeInTestClasses" />
+
Deprecated
+ +Since: PMD 5.5.0
+ +Priority: Medium (3)
+ +Avoid DML statements inside loops to avoid hitting the DML governor limit. Instead, try to batch up the data into a list and invoke your DML once on that list of data outside the loop.
+ +This rule is deprecated and will be removed with PMD 7.0.0. The rule is replaced
+by the more general rule OperationWithLimitsInLoop
.
This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.performance.AvoidDmlStatementsInLoopsRule
+ +Example(s):
+ +public class Something {
+ public void foo() {
+ for (Integer i = 0; i < 151; i++) {
+ Account account;
+ // ...
+ insert account;
+ }
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Performance | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +150 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/performance.xml/AvoidDmlStatementsInLoops" />
+
Deprecated
+ +Since: PMD 5.5.0
+ +Priority: Medium (3)
+ +New objects created within loops should be checked to see if they can created outside them and reused.
+ +This rule is deprecated and will be removed with PMD 7.0.0. The rule is replaced
+by the more general rule OperationWithLimitsInLoop
.
This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.performance.AvoidSoqlInLoopsRule
+ +Example(s):
+ +public class Something {
+ public static void main( String as[] ) {
+ for (Integer i = 0; i < 10; i++) {
+ List<Account> accounts = [SELECT Id FROM Account];
+ }
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Performance | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +150 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/performance.xml/AvoidSoqlInLoops" />
+
Deprecated
+ +Since: PMD 6.0.0
+ +Priority: Medium (3)
+ +Sosl calls within loops can cause governor limit exceptions.
+ +This rule is deprecated and will be removed with PMD 7.0.0. The rule is replaced
+by the more general rule OperationWithLimitsInLoop
.
This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.performance.AvoidSoslInLoopsRule
+ +Example(s):
+ +public class Something {
+ public static void main( String as[] ) {
+ for (Integer i = 0; i < 10; i++) {
+ List<List<SObject>> searchList = [FIND 'map*' IN ALL FIELDS RETURNING Account (Id, Name), Contact, Opportunity, Lead];
+ }
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Performance | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +150 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/performance.xml/AvoidSoslInLoops" />
+
Since: PMD 6.29.0
+ +Priority: Medium (3)
+ +Database class methods, DML operations, SOQL queries, or SOSL queries within loops can cause governor limit exceptions. Instead, try to batch up the data into a list and invoke the operation once on that list of data outside the loop.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.performance.OperationWithLimitsInLoopRule
+ +Example(s):
+ +public class Something {
+ public void databaseMethodInsideOfLoop(List<Account> accounts) {
+ for (Account a : accounts) {
+ Database.insert(a);
+ }
+ }
+
+ public void dmlInsideOfLoop() {
+ for (Integer i = 0; i < 151; i++) {
+ Account account;
+ // ...
+ insert account;
+ }
+ }
+
+ public void soqlInsideOfLoop() {
+ for (Integer i = 0; i < 10; i++) {
+ List<Account> accounts = [SELECT Id FROM Account];
+ }
+ }
+
+ public void soslInsideOfLoop() {
+ for (Integer i = 0; i < 10; i++) {
+ List<List<SObject>> searchList = [FIND 'map*' IN ALL FIELDS RETURNING Account (Id, Name), Contact, Opportunity, Lead];
+ }
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Performance | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +150 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/performance.xml/OperationWithLimitsInLoop" />
+
Since: PMD 5.5.3
+ +Priority: Medium (3)
+ +The rule makes sure you are using randomly generated IVs and keys for Crypto
calls.
+Hard-wiring these values greatly compromises the security of encrypted data.
This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.security.ApexBadCryptoRule
+ +Example(s):
+ +public without sharing class Foo {
+ Blob hardCodedIV = Blob.valueOf('Hardcoded IV 123');
+ Blob hardCodedKey = Blob.valueOf('0000000000000000');
+ Blob data = Blob.valueOf('Data to be encrypted');
+ Blob encrypted = Crypto.encrypt('AES128', hardCodedKey, hardCodedIV, data);
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Security | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +100 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/security.xml/ApexBadCrypto" />
+
Since: PMD 5.5.3
+ +Priority: Medium (3)
+ +The rule validates you are checking for access permissions before a SOQL/SOSL/DML operation. +Since Apex runs in system mode not having proper permissions checks results in escalation of +privilege and may produce runtime errors. This check forces you to handle such scenarios.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.security.ApexCRUDViolationRule
+ +Example(s):
+ +public class Foo {
+ public Contact foo(String status, String ID) {
+ Contact c = [SELECT Status__c FROM Contact WHERE Id=:ID];
+
+ // Make sure we can update the database before even trying
+ if (!Schema.sObjectType.Contact.fields.Name.isUpdateable()) {
+ return null;
+ }
+
+ c.Status__c = status;
+ update c;
+ return c;
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Security | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +100 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/security.xml/ApexCRUDViolation" />
+
Deprecated
+ +The rule has been moved to another ruleset. Use instead: ApexCSRF
+ +Deprecated
+ +Since: PMD 5.5.3
+ +Priority: Medium (3)
+ +Having DML operations in Apex class constructor or initializers can have unexpected side effects: +By just accessing a page, the DML statements would be executed and the database would be modified. +Just querying the database is permitted.
+ +In addition to constructors and initializers, any method called init
is checked as well.
Salesforce Apex already protects against this scenario and raises a runtime exception.
+ +Note: This rule has been moved from category "Security" to "Error Prone" with PMD 6.21.0, since +using DML in constructors is not a security problem, but crashes the application.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.errorprone.ApexCSRFRule
+ +Example(s):
+ +public class Foo {
+ // initializer
+ {
+ insert data;
+ }
+
+ // static initializer
+ static {
+ insert data;
+ }
+
+ // constructor
+ public Foo() {
+ insert data;
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Security | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +100 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/security.xml/ApexCSRF" />
+
Since: PMD 5.5.3
+ +Priority: Medium (3)
+ +Checks against calling dangerous methods.
+ +For the time being, it reports:
+ +FinancialForce
’s Configuration.disableTriggerCRUDSecurity()
. Disabling CRUD security
+opens the door to several attacks and requires manual validation, which is unreliable.System.debug
passing sensitive data as parameter, which could lead to exposure
+of private data.This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.security.ApexDangerousMethodsRule
+ +Example(s):
+ +public class Foo {
+ public Foo() {
+ Configuration.disableTriggerCRUDSecurity();
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Security | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +100 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/security.xml/ApexDangerousMethods" />
+
Since: PMD 5.5.3
+ +Priority: Medium (3)
+ +Checks against accessing endpoints under plain http. You should always use +https for security.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.security.ApexInsecureEndpointRule
+ +Example(s):
+ +public without sharing class Foo {
+ void foo() {
+ HttpRequest req = new HttpRequest();
+ req.setEndpoint('http://localhost:com');
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Security | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +100 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/security.xml/ApexInsecureEndpoint" />
+
Since: PMD 5.5.3
+ +Priority: Medium (3)
+ +Checks against redirects to user-controlled locations. This prevents attackers from +redirecting users to phishing sites.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.security.ApexOpenRedirectRule
+ +Example(s):
+ +public without sharing class Foo {
+ String unsafeLocation = ApexPage.getCurrentPage().getParameters.get('url_param');
+ PageReference page() {
+ return new PageReference(unsafeLocation);
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Security | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +100 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/security.xml/ApexOpenRedirect" />
+
Since: PMD 5.5.3
+ +Priority: Medium (3)
+ +Detect classes declared without explicit sharing mode if DML methods are used. This +forces the developer to take access restrictions into account before modifying objects.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.security.ApexSharingViolationsRule
+ +Example(s):
+ +public without sharing class Foo {
+ // DML operation here
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Security | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +100 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/security.xml/ApexSharingViolations" />
+
Since: PMD 5.5.3
+ +Priority: Medium (3)
+ +Detects the usage of untrusted / unescaped variables in DML queries.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.security.ApexSOQLInjectionRule
+ +Example(s):
+ +public class Foo {
+ public void test1(String t1) {
+ Database.query('SELECT Id FROM Account' + t1);
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Security | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +100 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/security.xml/ApexSOQLInjection" />
+
Since: PMD 5.5.3
+ +Priority: Medium (3)
+ +Detects hardcoded credentials used in requests to an endpoint.
+ +You should refrain from hardcoding credentials:
+Instead, you should use Named Credentials and a callout endpoint.
+ +For more information, you can check this
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.security.ApexSuggestUsingNamedCredRule
+ +Example(s):
+ +public class Foo {
+ public void foo(String username, String password) {
+ Blob headerValue = Blob.valueOf(username + ':' + password);
+ String authorizationHeader = 'BASIC ' + EncodingUtil.base64Encode(headerValue);
+ req.setHeader('Authorization', authorizationHeader);
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Security | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +100 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/security.xml/ApexSuggestUsingNamedCred" />
+
Since: PMD 5.5.3
+ +Priority: Medium (3)
+ +Reports on calls to addError
with disabled escaping. The message passed to addError
+will be displayed directly to the user in the UI, making it prime ground for XSS
+attacks if unescaped.
This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.security.ApexXSSFromEscapeFalseRule
+ +Example(s):
+ +public without sharing class Foo {
+ Trigger.new[0].addError(vulnerableHTMLGoesHere, false);
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Security | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +100 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/security.xml/ApexXSSFromEscapeFalse" />
+
Since: PMD 5.5.3
+ +Priority: Medium (3)
+ +Makes sure that all values obtained from URL parameters are properly escaped / sanitized +to avoid XSS attacks.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.apex.rule.security.ApexXSSFromURLParamRule
+ +Example(s):
+ +public without sharing class Foo {
+ String unescapedstring = ApexPage.getCurrentPage().getParameters.get('url_param');
+ String usedLater = unescapedstring;
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
cc_categories | +Security | +Deprecated Code Climate Categories | +yes. Delimiter is ‘|’. | +
cc_remediation_points_multiplier | +50 | +Deprecated Code Climate Remediation Points multiplier | +no | +
cc_block_highlighting | +false | +Deprecated Code Climate Block Highlighting | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/apex/security.xml/ApexXSSFromURLParam" />
+
Basic Ecmascript (rulesets/ecmascript/basic.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ +AssignmentInOperand, AvoidTrailingComma, ConsistentReturn, EqualComparison, GlobalVariable, InnaccurateNumericLiteral, ScopeForInVariable, UnreachableCode, UseBaseWithParseInt
+Braces (rulesets/ecmascript/braces.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ +ForLoopsMustUseBraces, IfElseStmtsMustUseBraces, IfStmtsMustUseBraces, WhileLoopsMustUseBraces
+Controversial Ecmascript (rulesets/ecmascript/controversial.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ + +Unnecessary (rulesets/ecmascript/unnecessary.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ + +Since: PMD 5.0.1
+ +Priority: High (1)
+ +Avoid using with - it’s bad news
+ +This rule is defined by the following XPath expression:
+//WithStatement
+
Example(s):
+ +with (object) {
+ property = 3; // Might be on object, might be on window: who knows.
+}
+
Use this rule by referencing it:
+<rule ref="category/ecmascript/bestpractices.xml/AvoidWithStatement" />
+
Since: PMD 5.0
+ +Priority: Medium High (2)
+ +ECMAScript does provide for return types on functions, and therefore there is no solid rule as to their usage. +However, when a function does use returns they should all have a value, or all with no value. Mixed return +usage is likely a bug, or at best poor style.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.ecmascript.rule.bestpractices.ConsistentReturnRule
+ +Example(s):
+ +// Ok
+function foo() {
+ if (condition1) {
+ return true;
+ }
+ return false;
+}
+
+// Bad
+function bar() {
+ if (condition1) {
+ return;
+ }
+ return false;
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
rhinoLanguageVersion | +ES6 | +Specifies the Rhino Language Version to use for parsing. Defaults to ES6. | +no | +
recordingLocalJsDocComments | +true | +Specifies that JsDoc comments are produced in the AST. | +no | +
recordingComments | +true | +Specifies that comments are produced in the AST. | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/ecmascript/bestpractices.xml/ConsistentReturn" />
+
Use this rule and customize it:
+<rule ref="category/ecmascript/bestpractices.xml/ConsistentReturn">
+ <properties>
+ <property name="rhinoLanguageVersion" value="ES6" />
+ <property name="recordingLocalJsDocComments" value="true" />
+ <property name="recordingComments" value="true" />
+ </properties>
+</rule>
+
Since: PMD 5.0
+ +Priority: High (1)
+ +This rule helps to avoid using accidently global variables by simply missing the "var" declaration. +Global variables can lead to side-effects that are hard to debug.
+ +This rule is defined by the following XPath expression:
+//Assignment[Name/@GlobalName = true()]
+
Example(s):
+ +function(arg) {
+ notDeclaredVariable = 1; // this will create a global variable and trigger the rule
+
+ var someVar = 1; // this is a local variable, that's ok
+
+ window.otherGlobal = 2; // this will not trigger the rule, although it is a global variable.
+}
+
Use this rule by referencing it:
+<rule ref="category/ecmascript/bestpractices.xml/GlobalVariable" />
+
Since: PMD 5.0
+ +Priority: High (1)
+ +A for-in loop in which the variable name is not explicitly scoped to the enclosing scope with the ‘var’ keyword can +refer to a variable in an enclosing scope outside the nearest enclosing scope. This will overwrite the +existing value of the variable in the outer scope when the body of the for-in is evaluated. When the for-in loop +has finished, the variable will contain the last value used in the for-in, and the original value from before +the for-in loop will be gone. Since the for-in variable name is most likely intended to be a temporary name, it +is better to explicitly scope the variable name to the nearest enclosing scope with ‘var’.
+ +This rule is defined by the following XPath expression:
+//ForInLoop[not(child::VariableDeclaration)]/Name[1]
+
Example(s):
+ +// Ok
+function foo() {
+ var p = 'clean';
+ function() {
+ var obj = { dirty: 'dirty' };
+ for (var p in obj) { // Use 'var' here.
+ obj[p] = obj[p];
+ }
+ return x;
+ }();
+
+ // 'p' still has value of 'clean'.
+}
+// Bad
+function bar() {
+ var p = 'clean';
+ function() {
+ var obj = { dirty: 'dirty' };
+ for (p in obj) { // Oh no, missing 'var' here!
+ obj[p] = obj[p];
+ }
+ return x;
+ }();
+
+ // 'p' is trashed and has value of 'dirty'!
+}
+
Use this rule by referencing it:
+<rule ref="category/ecmascript/bestpractices.xml/ScopeForInVariable" />
+
Since: PMD 5.0.1
+ +Priority: High (1)
+ +This rule checks for usages of parseInt. While the second parameter is optional and usually defaults +to 10 (base/radix is 10 for a decimal number), different implementations may behave differently. +It also improves readability, if the base is given.
+ +See also: parseInt()
+ +This rule is defined by the following XPath expression:
+//FunctionCall/Name[
+ @Image = 'parseInt'
+ and
+ count(../*) < 3
+]
+
Example(s):
+ +parseInt("010"); // unclear, could be interpreted as 10 or 7 (with a base of 7)
+
+parseInt("10", 10); // good
+
Use this rule by referencing it:
+<rule ref="category/ecmascript/bestpractices.xml/UseBaseWithParseInt" />
+
Since: PMD 5.0
+ +Priority: Medium High (2)
+ +Avoid assignments in operands; this can make code more complicated and harder to read. This is sometime +indicative of the bug where the assignment operator ‘=’ was used instead of the equality operator ‘==’.
+ +This rule is defined by the following XPath expression:
+//IfStatement[$allowIf = false()]/child::node()[1]/descendant-or-self::node()[self::Assignment or self::UnaryExpression[$allowIncrementDecrement = false() and (@Image = "--" or @Image = "++")]]
+|
+ //WhileLoop[$allowWhile = false()]/child::node()[1]/descendant-or-self::node()[self::Assignment or self::UnaryExpression[$allowIncrementDecrement = false() and (@Image = "--" or @Image = "++")]]
+|
+ //DoLoop[$allowWhile = false()]/child::node()[2]/descendant-or-self::node()[self::Assignment or self::UnaryExpression[$allowIncrementDecrement = false() and (@Image = "--" or @Image = "++")]]
+|
+ //ForLoop[$allowFor = false()]/child::node()[2]/descendant-or-self::node()[self::Assignment or self::UnaryExpression[$allowIncrementDecrement = false() and (@Image = "--" or @Image = "++")]]
+|
+ //ConditionalExpression[$allowTernary = false()]/child::node()[1]/descendant-or-self::node()[self::Assignment or self::UnaryExpression[$allowIncrementDecrement = false() and (@Image = "--" or @Image = "++")]]
+|
+ //ConditionalExpression[$allowTernaryResults = false()]/child::node()[position() = 2 or position() = 3]/descendant-or-self::node()[self::Assignment or self::UnaryExpression[$allowIncrementDecrement = false() and (@Image = "--" or @Image = "++")]]
+
Example(s):
+ +var x = 2;
+// Bad
+if ((x = getX()) == 3) {
+ alert('3!');
+}
+
+function getX() {
+ return 3;
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
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 | +
allowTernary | +false | +Allow assignment within the conditional expression of a ternary operator | +no | +
allowTernaryResults | +false | +Allow assignment within the result expressions of a ternary operator | +no | +
allowIncrementDecrement | +false | +Allow increment or decrement operators within the conditional expression of an if, for, or while statement | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/ecmascript/codestyle.xml/AssignmentInOperand" />
+
Use this rule and customize it:
+<rule ref="category/ecmascript/codestyle.xml/AssignmentInOperand">
+ <properties>
+ <property name="allowIf" value="false" />
+ <property name="allowFor" value="false" />
+ <property name="allowWhile" value="false" />
+ <property name="allowTernary" value="false" />
+ <property name="allowTernaryResults" value="false" />
+ <property name="allowIncrementDecrement" value="false" />
+ </properties>
+</rule>
+
Since: PMD 5.0
+ +Priority: Medium (3)
+ +Avoid using ‘for’ statements without using curly braces.
+ +This rule is defined by the following XPath expression:
+//ForLoop[not(child::Scope)]
+|
+//ForInLoop[not(child::Scope)]
+
Example(s):
+ +// Ok
+for (var i = 0; i < 42; i++) {
+ foo();
+}
+
+// Bad
+for (var i = 0; i < 42; i++)
+ foo();
+
Use this rule by referencing it:
+<rule ref="category/ecmascript/codestyle.xml/ForLoopsMustUseBraces" />
+
Since: PMD 5.0
+ +Priority: Medium (3)
+ +Avoid using if..else statements without using curly braces.
+ +This rule is defined by the following XPath expression:
+//ExpressionStatement[parent::IfStatement[@Else = true()]]
+ [not(child::Scope)]
+ [not(child::IfStatement)]
+
Example(s):
+ +// Ok
+if (foo) {
+ x++;
+} else {
+ y++;
+}
+
+// Bad
+if (foo)
+ x++;
+else
+ y++;
+
Use this rule by referencing it:
+<rule ref="category/ecmascript/codestyle.xml/IfElseStmtsMustUseBraces" />
+
Since: PMD 5.0
+ +Priority: Medium (3)
+ +Avoid using if statements without using curly braces.
+ +This rule is defined by the following XPath expression:
+//IfStatement[@Else = false() and not(child::Scope)]
+
Example(s):
+ +// Ok
+if (foo) {
+ x++;
+}
+
+// Bad
+if (foo)
+ x++;
+
Use this rule by referencing it:
+<rule ref="category/ecmascript/codestyle.xml/IfStmtsMustUseBraces" />
+
Since: PMD 5.5.0
+ +Priority: Medium (3)
+ +The else block in a if-else-construct is unnecessary if the if
block contains a return.
+Then the content of the else block can be put outside.
See also: http://eslint.org/docs/rules/no-else-return
+ +This rule is defined by the following XPath expression:
+//IfStatement[@Else=true()][Scope[1]/ReturnStatement]
+
Example(s):
+ +// Bad:
+if (x) {
+ return y;
+} else {
+ return z;
+}
+
+// Good:
+if (x) {
+ return y;
+}
+return z;
+
Use this rule by referencing it:
+<rule ref="category/ecmascript/codestyle.xml/NoElseReturn" />
+
Since: PMD 5.0
+ +Priority: Medium (3)
+ +An unnecessary Block is present. Such Blocks are often used in other languages to +introduce a new variable scope. Blocks do not behave like this in ECMAScipt, and using them can +be misleading. Considering removing this unnecessary Block.
+ +This rule is defined by the following XPath expression:
+//Block[not(parent::FunctionNode or parent::IfStatement or parent::ForLoop or parent::ForInLoop
+ or parent::WhileLoop or parent::DoLoop or parent::TryStatement or parent::CatchClause)]
+|
+//Scope[not(parent::FunctionNode or parent::IfStatement or parent::ForLoop or parent::ForInLoop
+ or parent::WhileLoop or parent::DoLoop or parent::TryStatement or parent::CatchClause)]
+
Example(s):
+ +if (foo) {
+ // Ok
+}
+if (bar) {
+ {
+ // Bad
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/ecmascript/codestyle.xml/UnnecessaryBlock" />
+
Since: PMD 5.0
+ +Priority: Medium Low (4)
+ +Unnecessary parentheses should be removed.
+ +This rule is defined by the following XPath expression:
+//ParenthesizedExpression/ParenthesizedExpression
+
Example(s):
+ +var x = 1; // Ok
+var y = (1 + 1); // Ok
+var z = ((1 + 1)); // Bad
+
Use this rule by referencing it:
+<rule ref="category/ecmascript/codestyle.xml/UnnecessaryParentheses" />
+
Since: PMD 5.0
+ +Priority: High (1)
+ +A ‘return’, ‘break’, ‘continue’, or ‘throw’ statement should be the last in a block. Statements after these +will never execute. This is a bug, or extremely poor style.
+ +This rule is defined by the following XPath expression:
+//ReturnStatement[following-sibling::node()]
+|
+ //ContinueStatement[following-sibling::node()]
+|
+ //BreakStatement[following-sibling::node()]
+|
+ //ThrowStatement[following-sibling::node()]
+
Example(s):
+ +// Ok
+function foo() {
+ return 1;
+}
+// Bad
+function bar() {
+ var x = 1;
+ return x;
+ x = 2;
+}
+
Use this rule by referencing it:
+<rule ref="category/ecmascript/codestyle.xml/UnreachableCode" />
+
Since: PMD 5.0
+ +Priority: Medium (3)
+ +Avoid using ‘while’ statements without using curly braces.
+ +This rule is defined by the following XPath expression:
+//WhileLoop[not(child::Scope)]
+
Example(s):
+ +// Ok
+while (true) {
+ x++;
+}
+
+// Bad
+while (true)
+ x++;
+
Use this rule by referencing it:
+<rule ref="category/ecmascript/codestyle.xml/WhileLoopsMustUseBraces" />
+
Since: PMD 5.1
+ +Priority: High (1)
+ +This rule helps improve code portability due to differences in browser treatment of trailing commas in object or array literals.
+ +This rule is defined by the following XPath expression:
+//ObjectLiteral[$allowObjectLiteral = false() and @TrailingComma = true()]
+|
+//ArrayLiteral[$allowArrayLiteral = false() and @TrailingComma = true()]
+
Example(s):
+ +function(arg) {
+ var obj1 = { a : 1 }; // Ok
+ var arr1 = [ 1, 2 ]; // Ok
+
+ var obj2 = { a : 1, }; // Syntax error in some browsers!
+ var arr2 = [ 1, 2, ]; // Length 2 or 3 depending on the browser!
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
allowObjectLiteral | +false | +Allow a trailing comma within an object literal | +no | +
allowArrayLiteral | +false | +Allow a trailing comma within an array literal | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/ecmascript/errorprone.xml/AvoidTrailingComma" />
+
Use this rule and customize it:
+<rule ref="category/ecmascript/errorprone.xml/AvoidTrailingComma">
+ <properties>
+ <property name="allowObjectLiteral" value="false" />
+ <property name="allowArrayLiteral" value="false" />
+ </properties>
+</rule>
+
Since: PMD 5.0
+ +Priority: Medium (3)
+ +Using == in condition may lead to unexpected results, as the variables are automatically casted to be of the +same type. The === operator avoids the casting.
+ +This rule is defined by the following XPath expression:
+//InfixExpression[
+ (@Image = "==" or @Image = "!=")
+ and
+ (KeywordLiteral[@Image='true' or @Image = 'false'] or NumberLiteral)
+]
+
Example(s):
+ +// Ok
+if (someVar === true) {
+ ...
+}
+// Ok
+if (someVar !== 3) {
+ ...
+}
+// Bad
+if (someVar == true) {
+ ...
+}
+// Bad
+if (someVar != 3) {
+ ...
+}
+
Use this rule by referencing it:
+<rule ref="category/ecmascript/errorprone.xml/EqualComparison" />
+
Since: PMD 5.0
+ +Priority: Medium High (2)
+ +The numeric literal will have a different value at runtime, which can happen if you provide too much +precision in a floating point number. This may result in numeric calculations being in error.
+ +This rule is defined by the following XPath expression:
+//NumberLiteral[@NormalizedImage != string(@Number)]
+
Example(s):
+ +var a = 9; // Ok
+var b = 999999999999999; // Ok
+var c = 999999999999999999999; // Not good
+var w = 1.12e-4; // Ok
+var x = 1.12; // Ok
+var y = 1.1234567890123; // Ok
+var z = 1.12345678901234567; // Not good
+
Use this rule by referencing it:
+<rule ref="category/ecmascript/errorprone.xml/InnaccurateNumericLiteral" />
+
Android (rulesets/java/android.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ + +Basic (rulesets/java/basic.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ +AvoidBranchingStatementAsLastInLoop, AvoidDecimalLiteralsInBigDecimalConstructor, AvoidMultipleUnaryOperators, AvoidThreadGroup, AvoidUsingHardCodedIP, AvoidUsingOctalValues, BigIntegerInstantiation, BooleanInstantiation, BrokenNullCheck, CheckResultSet, CheckSkipResult, ClassCastExceptionWithToArray, CollapsibleIfStatements, DontCallThreadRun, DontUseFloatTypeForLoopIndices, DoubleCheckedLocking, ExtendsObject, ForLoopShouldBeWhileLoop, JumbledIncrementer, MisplacedNullCheck, OverrideBothEqualsAndHashcode, ReturnFromFinallyBlock, SimplifiedTernary, UnconditionalIfStatement
+Braces (rulesets/java/braces.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ +ForLoopsMustUseBraces, IfElseStmtsMustUseBraces, IfStmtsMustUseBraces, WhileLoopsMustUseBraces
+Clone Implementation (rulesets/java/clone.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ +CloneMethodMustBePublic, CloneMethodMustImplementCloneable, CloneMethodReturnTypeMustMatchClassName, CloneThrowsCloneNotSupportedException, ProperCloneImplementation
+Code Size (rulesets/java/codesize.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ +CyclomaticComplexity, ExcessiveClassLength, ExcessiveMethodLength, ExcessiveParameterList, ExcessivePublicCount, ModifiedCyclomaticComplexity, NcssConstructorCount, NcssCount, NcssMethodCount, NcssTypeCount, NPathComplexity, StdCyclomaticComplexity, TooManyFields, TooManyMethods
+Comments (rulesets/java/comments.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ +CommentContent, CommentDefaultAccessModifier, CommentRequired, CommentSize
+Controversial (rulesets/java/controversial.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ +AssignmentInOperand, AtLeastOneConstructor, AvoidAccessibilityAlteration, AvoidFinalLocalVariable, AvoidLiteralsInIfCondition, AvoidPrefixingMethodParameters, AvoidUsingNativeCode, AvoidUsingShortType, AvoidUsingVolatile, CallSuperInConstructor, DataflowAnomalyAnalysis, DefaultPackage, DoNotCallGarbageCollectionExplicitly, DontImportSun, NullAssignment, OneDeclarationPerLine, OnlyOneReturn, SuspiciousOctalEscape, UnnecessaryConstructor, UnnecessaryParentheses, UseConcurrentHashMap, UseObjectForClearerAPI
+Coupling (rulesets/java/coupling.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ +CouplingBetweenObjects, ExcessiveImports, LawOfDemeter, LooseCoupling, LoosePackageCoupling
+Design (rulesets/java/design.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ +AbstractClassWithoutAbstractMethod, AbstractClassWithoutAnyMethod, AccessorClassGeneration, AccessorMethodGeneration, AssignmentToNonFinalStatic, AvoidDeeplyNestedIfStmts, AvoidInstanceofChecksInCatchClause, AvoidProtectedFieldInFinalClass, AvoidProtectedMethodInFinalClassNotExtending, AvoidReassigningParameters, AvoidSynchronizedAtMethodLevel, BadComparison, ClassWithOnlyPrivateConstructorsShouldBeFinal, CloseResource, CompareObjectsWithEquals, ConfusingTernary, ConstantsInInterface, ConstructorCallsOverridableMethod, DataClass, DefaultLabelNotLastInSwitchStmt, EmptyMethodInAbstractClassShouldBeAbstract, EqualsNull, FieldDeclarationsShouldBeAtStartOfClass, FinalFieldCouldBeStatic, GodClass, IdempotentOperations, ImmutableField, InstantiationToGetClass, LogicInversion, MissingBreakInSwitch, MissingStaticMethodInNonInstantiatableClass, NonCaseLabelInSwitchStatement, NonStaticInitializer, NonThreadSafeSingleton, OptimizableToArrayCall, PositionLiteralsFirstInCaseInsensitiveComparisons, PositionLiteralsFirstInComparisons, PreserveStackTrace, ReturnEmptyArrayRatherThanNull, SimpleDateFormatNeedsLocale, SimplifyBooleanExpressions, SimplifyBooleanReturns, SimplifyConditional, SingleMethodSingleton, SingletonClassReturningNewInstance, SingularField, SwitchDensity, SwitchStmtsShouldHaveDefault, TooFewBranchesForASwitchStatement, UncommentedEmptyConstructor, UncommentedEmptyMethodBody, UnnecessaryLocalBeforeReturn, UnsynchronizedStaticDateFormatter, UseCollectionIsEmpty, UseLocaleWithCaseConversions, UseNotifyAllInsteadOfNotify, UseUtilityClass, UseVarargs
+Empty Code (rulesets/java/empty.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ +EmptyCatchBlock, EmptyFinallyBlock, EmptyIfStmt, EmptyInitializer, EmptyStatementBlock, EmptyStatementNotInLoop, EmptyStaticInitializer, EmptySwitchStatements, EmptySynchronizedBlock, EmptyTryBlock, EmptyWhileStmt
+Finalizer (rulesets/java/finalizers.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ +AvoidCallingFinalize, EmptyFinalizer, FinalizeDoesNotCallSuperFinalize, FinalizeOnlyCallsSuperFinalize, FinalizeOverloaded, FinalizeShouldBeProtected
+Import Statements (rulesets/java/imports.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ +DontImportJavaLang, DuplicateImports, ImportFromSamePackage, TooManyStaticImports, UnnecessaryFullyQualifiedName, UnusedImports
+J2EE (rulesets/java/j2ee.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ +DoNotCallSystemExit, DoNotUseThreads, LocalHomeNamingConvention, LocalInterfaceSessionNamingConvention, MDBAndSessionBeanNamingConvention, RemoteInterfaceNamingConvention, RemoteSessionInterfaceNamingConvention, StaticEJBFieldShouldBeFinal, UseProperClassLoader
+JavaBeans (rulesets/java/javabeans.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ + +JUnit (rulesets/java/junit.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ +JUnitAssertionsShouldIncludeMessage, JUnitSpelling, JUnitStaticSuite, JUnitTestContainsTooManyAsserts, JUnitTestsShouldIncludeAssert, SimplifyBooleanAssertion, TestClassWithoutTestCases, UnnecessaryBooleanAssertion, UseAssertEqualsInsteadOfAssertTrue, UseAssertNullInsteadOfAssertTrue, UseAssertSameInsteadOfAssertTrue, UseAssertTrueInsteadOfAssertEquals
+Metrics (rulesets/java/metrics.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ + +MigratingToJUnit4 (rulesets/java/migrating_to_junit4.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ +JUnit4SuitesShouldUseSuiteAnnotation, JUnit4TestShouldUseAfterAnnotation, JUnit4TestShouldUseBeforeAnnotation, JUnit4TestShouldUseTestAnnotation, JUnitUseExpected
+Migration (rulesets/java/migrating.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ +AvoidAssertAsIdentifier, AvoidEnumAsIdentifier, ByteInstantiation, ForLoopCanBeForeach, IntegerInstantiation, JUnit4SuitesShouldUseSuiteAnnotation, JUnit4TestShouldUseAfterAnnotation, JUnit4TestShouldUseBeforeAnnotation, JUnit4TestShouldUseTestAnnotation, JUnitUseExpected, LongInstantiation, ReplaceEnumerationWithIterator, ReplaceHashtableWithMap, ReplaceVectorWithList, ShortInstantiation
+Migration13 (rulesets/java/migrating_to_13.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ +ReplaceEnumerationWithIterator, ReplaceHashtableWithMap, ReplaceVectorWithList
+Migration14 (rulesets/java/migrating_to_14.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ + +Migration15 (rulesets/java/migrating_to_15.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ +AvoidEnumAsIdentifier, ByteInstantiation, IntegerInstantiation, LongInstantiation, ShortInstantiation
+Naming (rulesets/java/naming.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ +AbstractNaming, AvoidDollarSigns, AvoidFieldNameMatchingMethodName, AvoidFieldNameMatchingTypeName, BooleanGetMethodName, ClassNamingConventions, GenericsNaming, LongVariable, MethodNamingConventions, MethodWithSameNameAsEnclosingClass, MisleadingVariableName, MIsLeadingVariableName, NoPackage, PackageCase, ShortClassName, ShortMethodName, ShortVariable, SuspiciousConstantFieldName, SuspiciousEqualsMethodName, SuspiciousHashcodeMethodName, VariableNamingConventions
+Optimization (rulesets/java/optimizations.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ +AddEmptyString, AvoidArrayLoops, AvoidInstantiatingObjectsInLoops, LocalVariableCouldBeFinal, MethodArgumentCouldBeFinal, PrematureDeclaration, RedundantFieldInitializer, SimplifyStartsWith, UnnecessaryWrapperObjectCreation, UseArrayListInsteadOfVector, UseArraysAsList, UseStringBufferForStringAppends
+quickstart (rulesets/java/quickstart.xml
):
Quickstart configuration of PMD. Includes the rules that are most likely to apply everywhere.
+ +It contains the following rules:
+ +AbstractClassWithoutAnyMethod, AssignmentInOperand, AssignmentToNonFinalStatic, AvoidAccessibilityAlteration, AvoidBranchingStatementAsLastInLoop, AvoidCatchingThrowable, AvoidDecimalLiteralsInBigDecimalConstructor, AvoidDollarSigns, AvoidInstanceofChecksInCatchClause, AvoidMessageDigestField, AvoidMultipleUnaryOperators, AvoidProtectedFieldInFinalClass, AvoidProtectedMethodInFinalClassNotExtending, AvoidStringBufferField, AvoidThreadGroup, AvoidUsingHardCodedIP, AvoidUsingOctalValues, AvoidUsingVolatile, BadComparison, BigIntegerInstantiation, BooleanInstantiation, BrokenNullCheck, CheckResultSet, CheckSkipResult, ClassCastExceptionWithToArray, ClassNamingConventions, ClassWithOnlyPrivateConstructorsShouldBeFinal, CloneMethodMustBePublic, CloneMethodMustImplementCloneable, CloneMethodReturnTypeMustMatchClassName, CloneThrowsCloneNotSupportedException, CloseResource, CompareObjectsWithEquals, ConstantsInInterface, ControlStatementBraces, DefaultLabelNotLastInSwitchStmt, DoNotCallGarbageCollectionExplicitly, DoNotExtendJavaLangError, DoNotExtendJavaLangThrowable, DontCallThreadRun, DontImportJavaLang, DontUseFloatTypeForLoopIndices, DoubleBraceInitialization, DoubleCheckedLocking, DuplicateImports, EmptyCatchBlock, EmptyFinalizer, EmptyFinallyBlock, EmptyIfStmt, EmptyInitializer, EmptyStatementBlock, EmptyStatementNotInLoop, EmptySwitchStatements, EmptySynchronizedBlock, EmptyTryBlock, EmptyWhileStmt, EqualsNull, ExtendsObject, FinalFieldCouldBeStatic, ForLoopCanBeForeach, ForLoopShouldBeWhileLoop, FormalParameterNamingConventions, GenericsNaming, GuardLogStatement, IdempotentOperations, IdenticalCatchBranches, ImportFromSamePackage, InstantiationToGetClass, JumbledIncrementer, LiteralsFirstInComparisons, LocalVariableNamingConventions, LogicInversion, LooseCoupling, MethodNamingConventions, MisplacedNullCheck, MissingBreakInSwitch, MissingOverride, MissingStaticMethodInNonInstantiatableClass, NonCaseLabelInSwitchStatement, NonStaticInitializer, NonThreadSafeSingleton, NoPackage, OneDeclarationPerLine, OptimizableToArrayCall, OverrideBothEqualsAndHashcode, PackageCase, PreserveStackTrace, ProperCloneImplementation, ProperLogger, ReturnEmptyArrayRatherThanNull, ReturnFromFinallyBlock, SimplifiedTernary, SimplifyBooleanReturns, SimplifyConditional, SingleMethodSingleton, SingletonClassReturningNewInstance, SingularField, SuspiciousEqualsMethodName, SuspiciousHashcodeMethodName, SuspiciousOctalEscape, SwitchStmtsShouldHaveDefault, UncommentedEmptyConstructor, UncommentedEmptyMethodBody, UnconditionalIfStatement, UnnecessaryAnnotationValueElement, UnnecessaryConstructor, UnnecessaryConversionTemporary, UnnecessaryFullyQualifiedName, UnnecessaryLocalBeforeReturn, UnnecessaryModifier, UnnecessaryReturn, UnsynchronizedStaticFormatter, UnusedFormalParameter, UnusedImports, UnusedLocalVariable, UnusedNullCheckInEquals, UnusedPrivateField, UnusedPrivateMethod, UseAssertEqualsInsteadOfAssertTrue, UseAssertNullInsteadOfAssertTrue, UseAssertSameInsteadOfAssertTrue, UseAssertTrueInsteadOfAssertEquals, UseCollectionIsEmpty, UseEqualsToCompareStrings, UselessOperationOnImmutable, UselessOverridingMethod, UselessParentheses, UselessQualifiedThis, UseLocaleWithCaseConversions, UseNotifyAllInsteadOfNotify, UseUtilityClass
+Security Code Guidelines (rulesets/java/sunsecure.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ + +Strict Exceptions (rulesets/java/strictexception.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ +AvoidCatchingGenericException, AvoidCatchingNPE, AvoidCatchingThrowable, AvoidLosingExceptionInformation, AvoidRethrowingException, AvoidThrowingNewInstanceOfSameException, AvoidThrowingNullPointerException, AvoidThrowingRawExceptionTypes, DoNotExtendJavaLangError, DoNotThrowExceptionInFinally, ExceptionAsFlowControl, SignatureDeclareThrowsException
+String and StringBuffer (rulesets/java/strings.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ +AppendCharacterWithChar, AvoidDuplicateLiterals, AvoidStringBufferField, ConsecutiveAppendsShouldReuse, ConsecutiveLiteralAppends, InefficientEmptyStringCheck, InefficientStringBuffering, InsufficientStringBufferDeclaration, StringBufferInstantiationWithChar, StringInstantiation, StringToString, UnnecessaryCaseChange, UseEqualsToCompareStrings, UseIndexOfChar, UselessStringValueOf, UseStringBufferLength
+Type Resolution (rulesets/java/typeresolution.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ +CloneMethodMustImplementCloneable, LooseCoupling, SignatureDeclareThrowsException, UnusedImports
+Unnecessary (rulesets/java/unnecessary.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ +UnnecessaryConversionTemporary, UnnecessaryFinalModifier, UnnecessaryModifier, UnnecessaryReturn, UnusedNullCheckInEquals, UselessOperationOnImmutable, UselessOverridingMethod, UselessParentheses, UselessQualifiedThis
+Unused Code (rulesets/java/unusedcode.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ +UnusedFormalParameter, UnusedLocalVariable, UnusedPrivateField, UnusedPrivateMethod
+Since: PMD 3.0
+ +Priority: Medium (3)
+ +The abstract class does not contain any abstract methods. An abstract class suggests +an incomplete implementation, which is to be completed by subclasses implementing the +abstract methods. If the class is intended to be used as a base class only (not to be instantiated +directly) a protected constructor can be provided prevent direct instantiation.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.bestpractices.AbstractClassWithoutAbstractMethodRule
+ +Example(s):
+ +public abstract class Foo {
+ void int method1() { ... }
+ void int method2() { ... }
+ // consider using abstract methods or removing
+ // the abstract modifier and adding protected constructors
+}
+
Use this rule by referencing it:
+<rule ref="category/java/bestpractices.xml/AbstractClassWithoutAbstractMethod" />
+
Since: PMD 1.04
+ +Priority: Medium (3)
+ +Instantiation by way of private constructors from outside of the constructor’s class often causes the +generation of an accessor. A factory method, or non-privatization of the constructor can eliminate this +situation. The generated class file is actually an interface. It gives the accessing class the ability +to invoke a new hidden package scope constructor that takes the interface as a supplementary parameter. +This turns a private constructor effectively into one with package scope, and is challenging to discern.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.bestpractices.AccessorClassGenerationRule
+ +Example(s):
+ +public class Outer {
+ void method(){
+ Inner ic = new Inner();//Causes generation of accessor class
+ }
+ public class Inner {
+ private Inner(){}
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/bestpractices.xml/AccessorClassGeneration" />
+
Since: PMD 5.5.4
+ +Priority: Medium (3)
+ +When accessing a private field / method from another class, the Java compiler will generate a accessor methods +with package-private visibility. This adds overhead, and to the dex method count on Android. This situation can +be avoided by changing the visibility of the field / method from private to package-private.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.bestpractices.AccessorMethodGenerationRule
+ +Example(s):
+ +public class OuterClass {
+ private int counter;
+ /* package */ int id;
+
+ public class InnerClass {
+ InnerClass() {
+ OuterClass.this.counter++; // wrong accessor method will be generated
+ }
+
+ public int getOuterClassId() {
+ return OuterClass.this.id; // id is package-private, no accessor method needed
+ }
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/bestpractices.xml/AccessorMethodGeneration" />
+
Since: PMD 2.2
+ +Priority: Medium (3)
+ +Constructors and methods receiving arrays should clone objects and store the copy. +This prevents future changes from the user from affecting the original array.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.bestpractices.ArrayIsStoredDirectlyRule
+ +Example(s):
+ +public class Foo {
+ private String [] x;
+ public void foo (String [] param) {
+ // Don't do this, make a copy of the array at least
+ this.x=param;
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
allowPrivate | +true | +If true, allow private methods/constructors to store arrays directly | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/bestpractices.xml/ArrayIsStoredDirectly" />
+
Use this rule and customize it:
+<rule ref="category/java/bestpractices.xml/ArrayIsStoredDirectly">
+ <properties>
+ <property name="allowPrivate" value="true" />
+ </properties>
+</rule>
+
Since: PMD 6.18.0
+ +Priority: Medium (3)
+ +Declaring a MessageDigest instance as a field make this instance directly available to multiple threads. +Such sharing of MessageDigest instances should be avoided if possible since it leads to wrong results +if the access is not synchronized correctly. +Just create a new instance and use it locally, where you need it. +Creating a new instance is easier than synchronizing access to a shared instance.
+ +This rule is defined by the following XPath expression:
+//FieldDeclaration[pmd-java:typeIs('java.security.MessageDigest')]
+
Example(s):
+ +import java.security.MessageDigest;
+public class AvoidMessageDigestFieldExample {
+ private final MessageDigest sharedMd;
+ public AvoidMessageDigestFieldExample() throws Exception {
+ sharedMd = MessageDigest.getInstance("SHA-256");
+ }
+ public byte[] calculateHashShared(byte[] data) {
+ // sharing a MessageDigest like this without synchronizing access
+ // might lead to wrong results
+ sharedMd.reset();
+ sharedMd.update(data);
+ return sharedMd.digest();
+ }
+
+ // better
+ public byte[] calculateHash(byte[] data) throws Exception {
+ MessageDigest md = MessageDigest.getInstance("SHA-256");
+ md.update(data);
+ return md.digest();
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/bestpractices.xml/AvoidMessageDigestField" />
+
Since: PMD 3.2
+ +Priority: Medium (3)
+ +Avoid printStackTrace(); use a logger call instead.
+ +This rule is defined by the following XPath expression:
+//PrimaryExpression[
+ ( PrimaryPrefix[Name[contains(@Image,'printStackTrace')]]
+ | PrimarySuffix[@Image='printStackTrace']
+ )/following-sibling::*[1][self::PrimarySuffix/Arguments[@Size=0]]
+]
+
Example(s):
+ +class Foo {
+ void bar() {
+ try {
+ // do something
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/bestpractices.xml/AvoidPrintStackTrace" />
+
Since: PMD 6.27.0
+ +Priority: Medium (3)
+ +Reassigning exception variables caught in a catch statement should be avoided because of:
+ +1) If it is needed, multi catch can be easily added and code will still compile.
+ +2) Following the principle of least surprise we want to make sure that a variable caught in a catch statement +is always the one thrown in a try block.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.bestpractices.AvoidReassigningCatchVariablesRule
+ +Example(s):
+ +public class Foo {
+ public void foo() {
+ try {
+ // do something
+ } catch (Exception e) {
+ e = new NullPointerException(); // not recommended
+ }
+
+ try {
+ // do something
+ } catch (MyException | ServerException e) {
+ e = new RuntimeException(); // won't compile
+ }
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/bestpractices.xml/AvoidReassigningCatchVariables" />
+
Since: PMD 6.11.0
+ +Priority: Medium (3)
+ +Reassigning loop variables can lead to hard-to-find bugs. Prevent or limit how these variables can be changed.
+ +In foreach-loops, configured by the foreachReassign
property:
deny
: Report any reassignment of the loop variable in the loop body. This is the default.allow
: Don’t check the loop variable.firstOnly
: Report any reassignments of the loop variable, except as the first statement in the loop body.
+ This is useful if some kind of normalization or clean-up of the value before using is permitted, but any other change of the variable is not.In for-loops, configured by the forReassign
property:
deny
: Report any reassignment of the control variable in the loop body. This is the default.allow
: Don’t check the control variable.skip
: Report any reassignments of the control variable, except conditional increments/decrements (++
, --
, +=
, -=
).
+ This prevents accidental reassignments or unconditional increments of the control variable.This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.bestpractices.AvoidReassigningLoopVariablesRule
+ +Example(s):
+ +public class Foo {
+ private void foo() {
+ for (String s : listOfStrings()) {
+ s = s.trim(); // OK, when foreachReassign is "firstOnly" or "allow"
+ doSomethingWith(s);
+
+ s = s.toUpper(); // OK, when foreachReassign is "allow"
+ doSomethingElseWith(s);
+ }
+
+ for (int i=0; i < 10; i++) {
+ if (check(i)) {
+ i++; // OK, when forReassign is "skip" or "allow"
+ }
+
+ i = 5; // OK, when forReassign is "allow"
+
+ doSomethingWith(i);
+ }
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
foreachReassign | +deny | +how/if foreach control variables may be reassigned | +no | +
forReassign | +deny | +how/if for control variables may be reassigned | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/bestpractices.xml/AvoidReassigningLoopVariables" />
+
Use this rule and customize it:
+<rule ref="category/java/bestpractices.xml/AvoidReassigningLoopVariables">
+ <properties>
+ <property name="foreachReassign" value="deny" />
+ <property name="forReassign" value="deny" />
+ </properties>
+</rule>
+
Since: PMD 1.0
+ +Priority: Medium High (2)
+ +Reassigning values to incoming parameters is not recommended. Use temporary local variables instead.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.bestpractices.AvoidReassigningParametersRule
+ +Example(s):
+ +public class Foo {
+ private void foo(String bar) {
+ bar = "something else";
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/bestpractices.xml/AvoidReassigningParameters" />
+
Since: PMD 4.2
+ +Priority: Medium (3)
+ +StringBuffers/StringBuilders can grow considerably, and so may become a source of memory leaks +if held within objects with long lifetimes.
+ +This rule is defined by the following XPath expression:
+//FieldDeclaration/Type/ReferenceType/ClassOrInterfaceType[@Image = 'StringBuffer' or @Image = 'StringBuilder']
+
Example(s):
+ +public class Foo {
+ private StringBuffer buffer; // potential memory leak as an instance variable;
+}
+
Use this rule by referencing it:
+<rule ref="category/java/bestpractices.xml/AvoidStringBufferField" />
+
Since: PMD 4.1
+ +Priority: Medium (3)
+ +Application with hard-coded IP addresses can become impossible to deploy in some cases. +Externalizing IP adresses is preferable.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.bestpractices.AvoidUsingHardCodedIPRule
+ +Example(s):
+ +public class Foo {
+ private String ip = "127.0.0.1"; // not recommended
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
checkAddressTypes | +IPv4 mapped IPv6 | IPv6 | IPv4 | +Check for IP address types. | +yes. Delimiter is ‘|’. | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/bestpractices.xml/AvoidUsingHardCodedIP" />
+
Use this rule and customize it:
+<rule ref="category/java/bestpractices.xml/AvoidUsingHardCodedIP">
+ <properties>
+ <property name="checkAddressTypes" value="IPv4 mapped IPv6|IPv6|IPv4" />
+ </properties>
+</rule>
+
Since: PMD 4.1
+ +Priority: Medium (3)
+ +Always check the return values of navigation methods (next, previous, first, last) of a ResultSet. +If the value return is ‘false’, it should be handled properly.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.bestpractices.CheckResultSetRule
+ +Example(s):
+ +Statement stat = conn.createStatement();
+ResultSet rst = stat.executeQuery("SELECT name FROM person");
+rst.next(); // what if it returns false? bad form
+String firstName = rst.getString(1);
+
+Statement stat = conn.createStatement();
+ResultSet rst = stat.executeQuery("SELECT name FROM person");
+if (rst.next()) { // result is properly examined and used
+ String firstName = rst.getString(1);
+ } else {
+ // handle missing data
+}
+
Use this rule by referencing it:
+<rule ref="category/java/bestpractices.xml/CheckResultSet" />
+
Since: PMD 5.5
+ +Priority: Medium (3)
+ +Avoid constants in interfaces. Interfaces should define types, constants are implementation details +better placed in classes or enums. See Effective Java, item 19.
+ +This rule is defined by the following XPath expression:
+//ClassOrInterfaceDeclaration[@Interface= true()][$ignoreIfHasMethods= false() or not(.//MethodDeclaration)]//FieldDeclaration
+
Example(s):
+ +public interface ConstantInterface {
+ public static final int CONST1 = 1; // violation, no fields allowed in interface!
+ static final int CONST2 = 1; // violation, no fields allowed in interface!
+ final int CONST3 = 1; // violation, no fields allowed in interface!
+ int CONST4 = 1; // violation, no fields allowed in interface!
+}
+
+// with ignoreIfHasMethods = false
+public interface AnotherConstantInterface {
+ public static final int CONST1 = 1; // violation, no fields allowed in interface!
+
+ int anyMethod();
+}
+
+// with ignoreIfHasMethods = true
+public interface YetAnotherConstantInterface {
+ public static final int CONST1 = 1; // no violation
+
+ int anyMethod();
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
ignoreIfHasMethods | +true | +Whether to ignore constants in interfaces if the interface defines any methods | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/bestpractices.xml/ConstantsInInterface" />
+
Use this rule and customize it:
+<rule ref="category/java/bestpractices.xml/ConstantsInInterface">
+ <properties>
+ <property name="ignoreIfHasMethods" value="true" />
+ </properties>
+</rule>
+
Since: PMD 1.5
+ +Priority: Medium (3)
+ +By convention, the default label should be the last label in a switch statement.
+ +This rule is defined by the following XPath expression:
+//SwitchStatement
+ [not(SwitchLabel[position() = last()][@Default= true()])]
+ [SwitchLabel[@Default= true()]]
+
Example(s):
+ +public class Foo {
+ void bar(int a) {
+ switch (a) {
+ case 1: // do something
+ break;
+ default: // the default case should be last, by convention
+ break;
+ case 2:
+ break;
+ }
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/bestpractices.xml/DefaultLabelNotLastInSwitchStmt" />
+
Since: PMD 6.16.0
+ +Priority: Medium (3)
+ +Double brace initialisation is a pattern to initialise eg collections concisely. But it implicitly +generates a new .class file, and the object holds a strong reference to the enclosing object. For those +reasons, it is preferable to initialize the object normally, even though it’s verbose.
+ +This rule counts any anonymous class which only has a single initializer as an instance of double-brace +initialization. There is currently no way to find out whether a method called in the initializer is not +accessible from outside the anonymous class, and those legit cases should be suppressed for the time being.
+ +This rule is defined by the following XPath expression:
+//AllocationExpression/ClassOrInterfaceBody[count(*)=1]/*/Initializer[@Static=false()]
+
Example(s):
+ +// this is double-brace initialization
+return new ArrayList<String>(){{
+ add("a");
+ add("b");
+ add("c");
+}};
+
+// the better way is to not create an anonymous class:
+List<String> a = new ArrayList<>();
+a.add("a");
+a.add("b");
+a.add("c");
+return a;
+
Use this rule by referencing it:
+<rule ref="category/java/bestpractices.xml/DoubleBraceInitialization" />
+
Since: PMD 6.0.0
+ +Priority: Medium (3)
+ +Minimum Language Version: Java 1.5
+ +Reports loops that can be safely replaced with the foreach syntax. The rule considers loops over +lists, arrays and iterators. A loop is safe to replace if it only uses the index variable to +access an element of the list or array, only has one update statement, and loops through every +element of the list or array left to right.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.bestpractices.ForLoopCanBeForeachRule
+ +Example(s):
+ +public class MyClass {
+ void loop(List<String> l) {
+ for (int i = 0; i < l.size(); i++) { // pre Java 1.5
+ System.out.println(l.get(i));
+ }
+
+ for (String s : l) { // post Java 1.5
+ System.out.println(s);
+ }
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/bestpractices.xml/ForLoopCanBeForeach" />
+
Since: PMD 6.11.0
+ +Priority: Medium (3)
+ +Having a lot of control variables in a ‘for’ loop makes it harder to see what range of values +the loop iterates over. By default this rule allows a regular ‘for’ loop with only one variable.
+ +This rule is defined by the following XPath expression:
+//ForInit/LocalVariableDeclaration[count(VariableDeclarator) > $maximumVariables]
+
Example(s):
+ +// this will be reported with the default setting of at most one control variable in a for loop
+for (int i = 0, j = 0; i < 10; i++, j += 2) {
+ foo();
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
maximumVariables | +1 | +A regular for statement will have 1 control variable | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/bestpractices.xml/ForLoopVariableCount" />
+
Use this rule and customize it:
+<rule ref="category/java/bestpractices.xml/ForLoopVariableCount">
+ <properties>
+ <property name="maximumVariables" value="1" />
+ </properties>
+</rule>
+
Since: PMD 5.1.0
+ +Priority: Medium High (2)
+ +Whenever using a log level, one should check if the loglevel is actually enabled, or +otherwise skip the associate String creation and manipulation.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.bestpractices.GuardLogStatementRule
+ +Example(s):
+ +// Add this for performance
+ if (log.isDebugEnabled() { ...
+ log.debug("log something" + " and " + "concat strings");
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
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 with the default properties by just referencing it:
+<rule ref="category/java/bestpractices.xml/GuardLogStatement" />
+
Use this rule and customize it:
+<rule ref="category/java/bestpractices.xml/GuardLogStatement">
+ <properties>
+ <property name="logLevels" value="trace,debug,info,warn,error,log,finest,finer,fine,info,warning,severe" />
+ <property name="guardsMethods" value="isTraceEnabled,isDebugEnabled,isInfoEnabled,isWarnEnabled,isErrorEnabled,isLoggable" />
+ </properties>
+</rule>
+
Since: PMD 4.0
+ +Priority: Medium (3)
+ +In JUnit 3, test suites are indicated by the suite() method. In JUnit 4, suites are indicated +through the @RunWith(Suite.class) annotation.
+ +This rule is defined by the following XPath expression:
+//ClassOrInterfaceBodyDeclaration
+[MethodDeclaration[@Name='suite']/ResultType/Type/ReferenceType/ClassOrInterfaceType[pmd-java:typeIs('junit.framework.Test')]]
+[not(MethodDeclaration/Block/BlockStatement/Statement/ReturnStatement//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.JUnit4TestAdapter')])]
+
Example(s):
+ +public class BadExample extends TestCase{
+
+ public static Test suite(){
+ return new Suite();
+ }
+}
+
+@RunWith(Suite.class)
+@SuiteClasses( { TestOne.class, TestTwo.class })
+public class GoodTest {
+}
+
Use this rule by referencing it:
+<rule ref="category/java/bestpractices.xml/JUnit4SuitesShouldUseSuiteAnnotation" />
+
Since: PMD 4.0
+ +Priority: Medium (3)
+ +In JUnit 3, the tearDown method was used to clean up all data entities required in running tests. +JUnit 4 skips the tearDown method and executes all methods annotated with @After after running each test. +JUnit 5 introduced @AfterEach and @AfterAll annotations to execute methods after each test or after all tests in the class, respectively.
+ +This rule is defined by the following XPath expression:
+//ClassOrInterfaceBodyDeclaration
+ [MethodDeclaration[@Name='tearDown']]
+ [not(Annotation/*/Name[
+ pmd-java:typeIs('org.junit.After')
+ or pmd-java:typeIs('org.junit.jupiter.api.AfterEach')
+ or pmd-java:typeIs('org.junit.jupiter.api.AfterAll')
+ or pmd-java:typeIs('org.testng.annotations.AfterMethod')])]
+
Example(s):
+ +public class MyTest {
+ public void tearDown() {
+ bad();
+ }
+}
+public class MyTest2 {
+ @After public void tearDown() {
+ good();
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/bestpractices.xml/JUnit4TestShouldUseAfterAnnotation" />
+
Since: PMD 4.0
+ +Priority: Medium (3)
+ +In JUnit 3, the setUp method was used to set up all data entities required in running tests. +JUnit 4 skips the setUp method and executes all methods annotated with @Before before all tests. +JUnit 5 introduced @BeforeEach and @BeforeAll annotations to execute methods before each test or before all tests in the class, respectively.
+ +This rule is defined by the following XPath expression:
+//ClassOrInterfaceBodyDeclaration
+ [MethodDeclaration[@Name='setUp']]
+ [not(Annotation/*/Name[
+ pmd-java:typeIs('org.junit.Before')
+ or pmd-java:typeIs('org.junit.jupiter.api.BeforeEach')
+ or pmd-java:typeIs('org.junit.jupiter.api.BeforeAll')
+ or pmd-java:typeIs('org.testng.annotations.BeforeMethod')])]
+
Example(s):
+ +public class MyTest {
+ public void setUp() {
+ bad();
+ }
+}
+public class MyTest2 {
+ @Before public void setUp() {
+ good();
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/bestpractices.xml/JUnit4TestShouldUseBeforeAnnotation" />
+
Since: PMD 4.0
+ +Priority: Medium (3)
+ +In JUnit 3, the framework executed all methods which started with the word test as a unit test. +In JUnit 4, only methods annotated with the @Test annotation are executed. +In JUnit 5, one of the following annotations should be used for tests: @Test, @RepeatedTest, @TestFactory, @TestTemplate or @ParameterizedTest.
+ +This rule is defined by the following XPath expression:
+//ClassOrInterfaceDeclaration[
+ matches(@SimpleName, $testClassPattern)
+ or ExtendsList/ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')]]
+
+ /ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration[MethodDeclaration[@Public=true() and starts-with(@Name, 'test')]]
+ [not(Annotation//Name[
+ pmd-java:typeIs('org.junit.Test')
+ or pmd-java:typeIs('org.junit.jupiter.api.Test') or pmd-java:typeIs('org.junit.jupiter.api.RepeatedTest')
+ or pmd-java:typeIs('org.junit.jupiter.api.TestFactory') or pmd-java:typeIs('org.junit.jupiter.api.TestTemplate')
+ or pmd-java:typeIs('org.junit.jupiter.params.ParameterizedTest')
+ ])]
+
Example(s):
+ +public class MyTest {
+ public void testBad() {
+ doSomething();
+ }
+
+ @Test
+ public void testGood() {
+ doSomething();
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
testClassPattern | +Test | +The regex pattern used to identify test classes | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/bestpractices.xml/JUnit4TestShouldUseTestAnnotation" />
+
Use this rule and customize it:
+<rule ref="category/java/bestpractices.xml/JUnit4TestShouldUseTestAnnotation">
+ <properties>
+ <property name="testClassPattern" value="Test" />
+ </properties>
+</rule>
+
Since: PMD 1.04
+ +Priority: Medium (3)
+ +JUnit assertions should include an informative message - i.e., use the three-argument version of +assertEquals(), not the two-argument version.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.bestpractices.JUnitAssertionsShouldIncludeMessageRule
+ +Example(s):
+ +public class Foo extends TestCase {
+ public void testSomething() {
+ assertEquals("foo", "bar");
+ // Use the form:
+ // assertEquals("Foo does not equals bar", "foo", "bar");
+ // instead
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/bestpractices.xml/JUnitAssertionsShouldIncludeMessage" />
+
Since: PMD 5.0
+ +Priority: Medium (3)
+ +Unit tests should not contain too many asserts. Many asserts are indicative of a complex test, for which +it is harder to verify correctness. Consider breaking the test scenario into multiple, shorter test scenarios. +Customize the maximum number of assertions used by this Rule to suit your needs.
+ +This rule checks for JUnit4, JUnit5 and TestNG Tests, as well as methods starting with "test".
+ +This rule is defined by the following XPath expression:
+//MethodDeclaration[@Name[matches(.,'^test')] or ../Annotation/MarkerAnnotation/Name[
+ pmd-java:typeIs('org.junit.Test')
+ or pmd-java:typeIs('org.junit.jupiter.api.Test')
+ or pmd-java:typeIs('org.junit.jupiter.api.RepeatedTest')
+ or pmd-java:typeIs('org.junit.jupiter.api.TestFactory')
+ or pmd-java:typeIs('org.junit.jupiter.api.TestTemplate')
+ or pmd-java:typeIs('org.junit.jupiter.params.ParameterizedTest')
+ or pmd-java:typeIs('org.testng.annotations.Test')
+ ]]
+ [count(.//PrimaryPrefix/Name[@Image[matches(.,'^assert')]]) > $maximumAsserts]
+
Example(s):
+ +public class MyTestCase extends TestCase {
+ // Ok
+ public void testMyCaseWithOneAssert() {
+ boolean myVar = false;
+ assertFalse("should be false", myVar);
+ }
+
+ // Bad, too many asserts (assuming max=1)
+ public void testMyCaseWithMoreAsserts() {
+ boolean myVar = false;
+ assertFalse("myVar should be false", myVar);
+ assertEquals("should equals false", false, myVar);
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
maximumAsserts | +1 | +Maximum number of Asserts in a test method | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/bestpractices.xml/JUnitTestContainsTooManyAsserts" />
+
Use this rule and customize it:
+<rule ref="category/java/bestpractices.xml/JUnitTestContainsTooManyAsserts">
+ <properties>
+ <property name="maximumAsserts" value="1" />
+ </properties>
+</rule>
+
Since: PMD 2.0
+ +Priority: Medium (3)
+ +JUnit tests should include at least one assertion. This makes the tests more robust, and using assert +with messages provide the developer a clearer idea of what the test does.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.bestpractices.JUnitTestsShouldIncludeAssertRule
+ +Example(s):
+ +public class Foo extends TestCase {
+ public void testSomething() {
+ Bar b = findBar();
+ // This is better than having a NullPointerException
+ // assertNotNull("bar not found", b);
+ b.work();
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/bestpractices.xml/JUnitTestsShouldIncludeAssert" />
+
Since: PMD 4.0
+ +Priority: Medium (3)
+ +In JUnit4, use the @Test(expected) annotation to denote tests that should throw exceptions.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.bestpractices.JUnitUseExpectedRule
+ +Example(s):
+ +public class MyTest {
+ @Test
+ public void testBad() {
+ try {
+ doSomething();
+ fail("should have thrown an exception");
+ } catch (Exception e) {
+ }
+ }
+
+ @Test(expected=Exception.class)
+ public void testGood() {
+ doSomething();
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/bestpractices.xml/JUnitUseExpected" />
+
Since: PMD 6.24.0
+ +Priority: Medium (3)
+ +Position literals first in all String comparisons, if the second argument is null then NullPointerExceptions +can be avoided, they will just return false. Note that switching literal positions for compareTo and +compareToIgnoreCase may change the result, see examples.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.bestpractices.LiteralsFirstInComparisonsRule
+ +Example(s):
+ +class Foo {
+ boolean bar(String x) {
+ return x.equals("2"); // should be "2".equals(x)
+ }
+ boolean bar(String x) {
+ return x.equalsIgnoreCase("2"); // should be "2".equalsIgnoreCase(x)
+ }
+ boolean bar(String x) {
+ return (x.compareTo("bar") > 0); // should be: "bar".compareTo(x) < 0
+ }
+ boolean bar(String x) {
+ return (x.compareToIgnoreCase("bar") > 0); // should be: "bar".compareToIgnoreCase(x) < 0
+ }
+ boolean bar(String x) {
+ return x.contentEquals("bar"); // should be "bar".contentEquals(x)
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/bestpractices.xml/LiteralsFirstInComparisons" />
+
Since: PMD 0.7
+ +Priority: Medium (3)
+ +The use of implementation types (i.e., HashSet) as object references limits your ability to use alternate +implementations in the future as requirements change. Whenever available, referencing objects +by their interface types (i.e, Set) provides much more flexibility.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.bestpractices.LooseCouplingRule
+ +Example(s):
+ +import java.util.ArrayList;
+import java.util.HashSet;
+
+public class Bar {
+ // sub-optimal approach
+ private ArrayList<SomeType> list = new ArrayList<>();
+
+ public HashSet<SomeType> getFoo() {
+ return new HashSet<SomeType>();
+ }
+
+ // preferred approach
+ private List<SomeType> list = new ArrayList<>();
+
+ public Set<SomeType> getFoo() {
+ return new HashSet<SomeType>();
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/bestpractices.xml/LooseCoupling" />
+
Since: PMD 2.2
+ +Priority: Medium (3)
+ +Exposing internal arrays to the caller violates object encapsulation since elements can be +removed or replaced outside of the object that owns it. It is safer to return a copy of the array.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.bestpractices.MethodReturnsInternalArrayRule
+ +Example(s):
+ +public class SecureSystem {
+ UserData [] ud;
+ public UserData [] getUserData() {
+ // Don't return directly the internal array, return a copy
+ return ud;
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/bestpractices.xml/MethodReturnsInternalArray" />
+
Since: PMD 6.2.0
+ +Priority: Medium (3)
+ +Minimum Language Version: Java 1.5
+ +Annotating overridden methods with @Override ensures at compile time that +the method really overrides one, which helps refactoring and clarifies intent.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.bestpractices.MissingOverrideRule
+ +Example(s):
+ +public class Foo implements Runnable {
+ // This method is overridden, and should have an @Override annotation
+ public void run() {
+
+ }
+ }
+
Use this rule by referencing it:
+<rule ref="category/java/bestpractices.xml/MissingOverride" />
+
Since: PMD 5.0
+ +Priority: Medium Low (4)
+ +Java allows the use of several variables declaration of the same type on one line. However, it +can lead to quite messy code. This rule looks for several declarations on the same line.
+ +This rule is defined by the following XPath expression:
+//LocalVariableDeclaration
+ [not(parent::ForInit)]
+ [count(VariableDeclarator) > 1]
+ [$strictMode or count(distinct-values(VariableDeclarator/@BeginLine)) != count(VariableDeclarator)]
+|
+//FieldDeclaration
+ [count(VariableDeclarator) > 1]
+ [$strictMode or count(distinct-values(VariableDeclarator/@BeginLine)) != count(VariableDeclarator)]
+
Example(s):
+ +String name; // separate declarations
+String lastname;
+
+String name, lastname; // combined declaration, a violation
+
+String name,
+ lastname; // combined declaration on multiple lines, no violation by default.
+ // Set property strictMode to true to mark this as violation.
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
strictMode | +false | +If true, mark combined declaration even if the declarations are on separate lines. | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/bestpractices.xml/OneDeclarationPerLine" />
+
Use this rule and customize it:
+<rule ref="category/java/bestpractices.xml/OneDeclarationPerLine">
+ <properties>
+ <property name="strictMode" value="false" />
+ </properties>
+</rule>
+
Deprecated
+ +Since: PMD 5.1
+ +Priority: Medium (3)
+ +Position literals first in comparisons, if the second argument is null then NullPointerExceptions +can be avoided, they will just return false.
+ +This rule is replaced by the more general rule LiteralsFirstInComparisons
.
This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.bestpractices.PositionLiteralsFirstInCaseInsensitiveComparisonsRule
+ +Example(s):
+ +class Foo {
+ boolean bar(String x) {
+ return x.equalsIgnoreCase("2"); // should be "2".equalsIgnoreCase(x)
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/bestpractices.xml/PositionLiteralsFirstInCaseInsensitiveComparisons" />
+
Deprecated
+ +Since: PMD 3.3
+ +Priority: Medium (3)
+ +Position literals first in comparisons, if the second argument is null then NullPointerExceptions +can be avoided, they will just return false.
+ +This rule is replaced by the more general rule LiteralsFirstInComparisons
.
This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.bestpractices.PositionLiteralsFirstInComparisonsRule
+ +Example(s):
+ +class Foo {
+ boolean bar(String x) {
+ return x.equals("2"); // should be "2".equals(x)
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/bestpractices.xml/PositionLiteralsFirstInComparisons" />
+
Since: PMD 3.7
+ +Priority: Medium (3)
+ +Throwing a new exception from a catch block without passing the original exception into the +new exception will cause the original stack trace to be lost making it difficult to debug +effectively.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.bestpractices.PreserveStackTraceRule
+ +Example(s):
+ +public class Foo {
+ void good() {
+ try{
+ Integer.parseInt("a");
+ } catch (Exception e) {
+ throw new Exception(e); // first possibility to create exception chain
+ }
+ try {
+ Integer.parseInt("a");
+ } catch (Exception e) {
+ throw (IllegalStateException)new IllegalStateException().initCause(e); // second possibility to create exception chain.
+ }
+ }
+ void bad() {
+ try{
+ Integer.parseInt("a");
+ } catch (Exception e) {
+ throw new Exception(e.getMessage());
+ }
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/bestpractices.xml/PreserveStackTrace" />
+
Since: PMD 3.4
+ +Priority: Medium (3)
+ +Consider replacing Enumeration usages with the newer java.util.Iterator
+ +This rule is defined by the following XPath expression:
+//ImplementsList/ClassOrInterfaceType[@Image='Enumeration']
+
Example(s):
+ +public class Foo implements Enumeration {
+ private int x = 42;
+ public boolean hasMoreElements() {
+ return true;
+ }
+ public Object nextElement() {
+ return String.valueOf(i++);
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/bestpractices.xml/ReplaceEnumerationWithIterator" />
+
Since: PMD 3.4
+ +Priority: Medium (3)
+ +Consider replacing Hashtable usage with the newer java.util.Map if thread safety is not required.
+ +This rule is defined by the following XPath expression:
+//Type/ReferenceType/ClassOrInterfaceType[@Image='Hashtable']
+
Example(s):
+ +public class Foo {
+ void bar() {
+ Hashtable h = new Hashtable();
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/bestpractices.xml/ReplaceHashtableWithMap" />
+
Since: PMD 3.4
+ +Priority: Medium (3)
+ +Consider replacing Vector usages with the newer java.util.ArrayList if expensive thread-safe operations are not required.
+ +This rule is defined by the following XPath expression:
+//Type/ReferenceType/ClassOrInterfaceType[@Image='Vector']
+
Example(s):
+ +public class Foo {
+ void bar() {
+ Vector v = new Vector();
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/bestpractices.xml/ReplaceVectorWithList" />
+
Since: PMD 1.0
+ +Priority: Medium (3)
+ +All switch statements should include a default option to catch any unspecified values.
+ +This rule is defined by the following XPath expression:
+//SwitchStatement[@DefaultCase = false() and @ExhaustiveEnumSwitch = false()]
+
Example(s):
+ +public void bar() {
+ int x = 2;
+ switch (x) {
+ case 1: int j = 6;
+ case 2: int j = 8;
+ // missing default: here
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/bestpractices.xml/SwitchStmtsShouldHaveDefault" />
+
Since: PMD 2.1
+ +Priority: Medium High (2)
+ +References to System.(out|err).print are usually intended for debugging purposes and can remain in +the codebase even in production code. By using a logger one can enable/disable this behaviour at +will (and by priority) and avoid clogging the Standard out log.
+ +This rule is defined by the following XPath expression:
+//Name[
+ starts-with(@Image, 'System.out.print')
+ or
+ starts-with(@Image, 'System.err.print')
+ ]
+
Example(s):
+ +class Foo{
+ Logger log = Logger.getLogger(Foo.class.getName());
+ public void testA () {
+ System.out.println("Entering test");
+ // Better use this
+ log.fine("Entering test");
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/bestpractices.xml/SystemPrintln" />
+
Since: PMD 6.26.0
+ +Priority: Medium (3)
+ +Reports assignments to variables that are never used before the variable is overwritten, +or goes out of scope. Unused assignments are those for which
+The rule doesn’t consider assignments to fields except for those of this
in a constructor,
+or static fields of the current class in static initializers.
The rule may be suppressed with the standard @SuppressWarnings("unused")
tag.
The rule subsumes UnusedLocalVariable
, and UnusedFormalParameter
.
+Those violations are filtered
+out by default, in case you already have enabled those rules, but may be enabled with the property
+reportUnusedVariables
. Variables whose name starts with ignored
are filtered out, as
+is standard practice for exceptions.
Limitations:
+throw
statement, in particular,
+things like assert
statements, or NullPointerExceptions on dereference are ignored.this(...)
syntax. This may cause false-negatives.Both of those limitations may be partly relaxed in PMD 7.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.bestpractices.UnusedAssignmentRule
+ +Example(s):
+ +class A {
+ // this field initializer is redundant,
+ // it is always overwritten in the constructor
+ int f = 1;
+
+ A(int f) {
+ this.f = f;
+ }
+ }
+
class B {
+
+ int method(int i, int j) {
+ // this initializer is redundant,
+ // it is overwritten in all branches of the `if`
+ int k = 0;
+
+ // Both the assignments to k are unused, because k is
+ // not read after the if/else
+ // This may hide a bug: the programmer probably wanted to return k
+ if (i < j)
+ k = i;
+ else
+ k = j;
+
+ return j;
+ }
+
+}
+
class C {
+
+ int method() {
+ int i = 0;
+
+ checkSomething(++i);
+ checkSomething(++i);
+ checkSomething(++i);
+ checkSomething(++i);
+
+ // That last increment is not reported unless
+ // the property `checkUnusedPrefixIncrement` is
+ // set to `true`
+ // Technically it could be written (i+1), but it
+ // is not very important
+ }
+
+}
+
class C {
+
+ // variables that are truly unused (at most assigned to, but never accessed)
+ // are only reported if property `reportUnusedVariables` is true
+
+ void method(int param) { } // for example this method parameter
+
+ // even then, you can suppress the violation with an annotation:
+
+ void method(@SuppressWarning("unused") int param) { } // no violation, even if `reportUnusedVariables` is true
+
+ // For catch parameters, or for resources which don't need to be used explicitly,
+ // you can give a name that starts with "ignored" to ignore such warnings
+
+ {
+ try (Something ignored = Something.create()) {
+ // even if ignored is unused, it won't be flagged
+ // its purpose might be to side-effect in the create/close routines
+
+ } catch (Exception e) { // this is unused and will cause a warning if `reportUnusedVariables` is true
+ // you should choose a name that starts with "ignored"
+ return;
+ }
+ }
+
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
checkUnusedPrefixIncrement | +false | +Report expressions like ++i that may be replaced with (i + 1) | +no | +
reportUnusedVariables | +false | +Report variables that are only initialized, and never read at all. The rule UnusedVariable already cares for that, but you can enable it if needed | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/bestpractices.xml/UnusedAssignment" />
+
Use this rule and customize it:
+<rule ref="category/java/bestpractices.xml/UnusedAssignment">
+ <properties>
+ <property name="checkUnusedPrefixIncrement" value="false" />
+ <property name="reportUnusedVariables" value="false" />
+ </properties>
+</rule>
+
Since: PMD 0.8
+ +Priority: Medium (3)
+ +Avoid passing parameters to methods or constructors without actually referencing them in the method body.
+Removing unused formal parameters from public methods could cause a ripple effect through the code base.
+Hence, by default, this rule only considers private methods. To include non-private methods, set the
+checkAll
property to true
.
This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.bestpractices.UnusedFormalParameterRule
+ +Example(s):
+ +public class Foo {
+ private void bar(String howdy) {
+ // howdy is not used
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
checkAll | +false | +Check all methods, including non-private ones | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/bestpractices.xml/UnusedFormalParameter" />
+
Use this rule and customize it:
+<rule ref="category/java/bestpractices.xml/UnusedFormalParameter">
+ <properties>
+ <property name="checkAll" value="false" />
+ </properties>
+</rule>
+
Since: PMD 1.0
+ +Priority: Medium Low (4)
+ +Avoid unused import statements to prevent unwanted dependencies. +This rule will also find unused on demand imports, i.e. import com.foo.*.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.bestpractices.UnusedImportsRule
+ +Example(s):
+ +import java.io.File; // not referenced or required
+import java.util.*; // not referenced or required
+
+public class Foo {}
+
Use this rule by referencing it:
+<rule ref="category/java/bestpractices.xml/UnusedImports" />
+
Since: PMD 0.1
+ +Priority: Medium (3)
+ +Detects when a local variable is declared and/or assigned, but not used.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.bestpractices.UnusedLocalVariableRule
+ +Example(s):
+ +public class Foo {
+ public void doSomething() {
+ int i = 5; // Unused
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/bestpractices.xml/UnusedLocalVariable" />
+
Since: PMD 0.1
+ +Priority: Medium (3)
+ +Detects when a private field is declared and/or assigned a value, but not used.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.bestpractices.UnusedPrivateFieldRule
+ +Example(s):
+ +public class Something {
+ private static int FOO = 2; // Unused
+ private int i = 5; // Unused
+ private int j = 6;
+ public int addOne() {
+ return j++;
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
ignoredAnnotations | +lombok.Setter | lombok.Getter | lombok.Builder | lombok.Data | lombok.RequiredArgsConstructor | lombok.AllArgsConstructor | lombok.Value | lombok.NoArgsConstructor | java.lang.Deprecated | javafx.fxml.FXML | lombok.experimental.Delegate | lombok.EqualsAndHashCode | +Fully qualified names of the annotation types that should be ignored by this rule | +yes. Delimiter is ‘|’. | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/bestpractices.xml/UnusedPrivateField" />
+
Use this rule and customize it:
+<rule ref="category/java/bestpractices.xml/UnusedPrivateField">
+ <properties>
+ <property name="ignoredAnnotations" value="lombok.Setter|lombok.Getter|lombok.Builder|lombok.Data|lombok.RequiredArgsConstructor|lombok.AllArgsConstructor|lombok.Value|lombok.NoArgsConstructor|java.lang.Deprecated|javafx.fxml.FXML|lombok.experimental.Delegate|lombok.EqualsAndHashCode" />
+ </properties>
+</rule>
+
Since: PMD 0.7
+ +Priority: Medium (3)
+ +Unused Private Method detects when a private method is declared but is unused.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.bestpractices.UnusedPrivateMethodRule
+ +Example(s):
+ +public class Something {
+ private void foo() {} // unused
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
ignoredAnnotations | +java.lang.Deprecated | +Fully qualified names of the annotation types that should be ignored by this rule | +yes. Delimiter is ‘|’. | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/bestpractices.xml/UnusedPrivateMethod" />
+
Use this rule and customize it:
+<rule ref="category/java/bestpractices.xml/UnusedPrivateMethod">
+ <properties>
+ <property name="ignoredAnnotations" value="java.lang.Deprecated" />
+ </properties>
+</rule>
+
Since: PMD 3.1
+ +Priority: Medium (3)
+ +This rule detects JUnit assertions in object equality. These assertions should be made by more specific methods, like assertEquals.
+ +This rule is defined by the following XPath expression:
+//ClassOrInterfaceDeclaration[
+ pmd-java:typeIs('junit.framework.TestCase')
+ or .//MarkerAnnotation/Name[
+ pmd-java:typeIs('org.junit.Test')
+ or pmd-java:typeIs('org.junit.jupiter.api.Test')
+ or pmd-java:typeIs('org.junit.jupiter.api.RepeatedTest')
+ or pmd-java:typeIs('org.junit.jupiter.api.TestFactory')
+ or pmd-java:typeIs('org.junit.jupiter.api.TestTemplate')
+ or pmd-java:typeIs('org.junit.jupiter.params.ParameterizedTest')
+ ]
+ ]
+//PrimaryExpression[
+ PrimaryPrefix/Name[@Image = 'assertTrue']
+][
+ PrimarySuffix/Arguments/ArgumentList/Expression/PrimaryExpression/PrimaryPrefix/Name
+ [ends-with(@Image, '.equals')]
+]
+
Example(s):
+ +public class FooTest extends TestCase {
+ void testCode() {
+ Object a, b;
+ assertTrue(a.equals(b)); // bad usage
+ assertEquals("a should equals b", a, b); // good usage
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/bestpractices.xml/UseAssertEqualsInsteadOfAssertTrue" />
+
Since: PMD 3.5
+ +Priority: Medium (3)
+ +This rule detects JUnit assertions in object references equality. These assertions should be made by +more specific methods, like assertNull, assertNotNull.
+ +This rule is defined by the following XPath expression:
+//ClassOrInterfaceDeclaration[
+ pmd-java:typeIs('junit.framework.TestCase')
+ or .//MarkerAnnotation/Name[
+ pmd-java:typeIs('org.junit.Test')
+ or pmd-java:typeIs('org.junit.jupiter.api.Test')
+ or pmd-java:typeIs('org.junit.jupiter.api.RepeatedTest')
+ or pmd-java:typeIs('org.junit.jupiter.api.TestFactory')
+ or pmd-java:typeIs('org.junit.jupiter.api.TestTemplate')
+ or pmd-java:typeIs('org.junit.jupiter.params.ParameterizedTest')
+ ]
+ ]
+//PrimaryExpression[
+ PrimaryPrefix/Name[@Image = 'assertTrue' or @Image = 'assertFalse']
+][
+ PrimarySuffix/Arguments/ArgumentList[
+ Expression/EqualityExpression/PrimaryExpression/PrimaryPrefix/Literal/NullLiteral
+ ]
+]
+
Example(s):
+ +public class FooTest extends TestCase {
+ void testCode() {
+ Object a = doSomething();
+ assertTrue(a==null); // bad usage
+ assertNull(a); // good usage
+ assertTrue(a != null); // bad usage
+ assertNotNull(a); // good usage
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/bestpractices.xml/UseAssertNullInsteadOfAssertTrue" />
+
Since: PMD 3.1
+ +Priority: Medium (3)
+ +This rule detects JUnit assertions in object references equality. These assertions should be made +by more specific methods, like assertSame, assertNotSame.
+ +This rule is defined by the following XPath expression:
+//ClassOrInterfaceDeclaration[
+ pmd-java:typeIs('junit.framework.TestCase')
+ or .//MarkerAnnotation/Name[
+ pmd-java:typeIs('org.junit.Test')
+ or pmd-java:typeIs('org.junit.jupiter.api.Test')
+ or pmd-java:typeIs('org.junit.jupiter.api.RepeatedTest')
+ or pmd-java:typeIs('org.junit.jupiter.api.TestFactory')
+ or pmd-java:typeIs('org.junit.jupiter.api.TestTemplate')
+ or pmd-java:typeIs('org.junit.jupiter.params.ParameterizedTest')
+ ]
+ ]
+//PrimaryExpression[
+ PrimaryPrefix/Name[@Image = 'assertTrue' or @Image = 'assertFalse']
+]
+[
+ PrimarySuffix/Arguments/ArgumentList/Expression/EqualityExpression
+ [not(.//NullLiteral)]
+]
+
Example(s):
+ +public class FooTest extends TestCase {
+ void testCode() {
+ Object a, b;
+ assertTrue(a == b); // bad usage
+ assertSame(a, b); // good usage
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/bestpractices.xml/UseAssertSameInsteadOfAssertTrue" />
+
Since: PMD 5.0
+ +Priority: Medium (3)
+ +When asserting a value is the same as a literal or Boxed boolean, use assertTrue/assertFalse, instead of assertEquals.
+ +This rule is defined by the following XPath expression:
+//PrimaryExpression[PrimaryPrefix/Name[@Image = 'assertEquals']]
+[
+ PrimarySuffix/Arguments/ArgumentList/Expression/PrimaryExpression/PrimaryPrefix/Literal/BooleanLiteral
+ or
+ PrimarySuffix/Arguments/ArgumentList/Expression/PrimaryExpression/PrimaryPrefix
+ /Name[(@Image = 'Boolean.TRUE' or @Image = 'Boolean.FALSE')]
+]
+
Example(s):
+ +public class MyTestCase extends TestCase {
+ public void testMyCase() {
+ boolean myVar = true;
+ // Ok
+ assertTrue("myVar is true", myVar);
+ // Bad
+ assertEquals("myVar is true", true, myVar);
+ // Bad
+ assertEquals("myVar is false", false, myVar);
+ // Bad
+ assertEquals("myVar is true", Boolean.TRUE, myVar);
+ // Bad
+ assertEquals("myVar is false", Boolean.FALSE, myVar);
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/bestpractices.xml/UseAssertTrueInsteadOfAssertEquals" />
+
Since: PMD 3.9
+ +Priority: Medium (3)
+ +The isEmpty() method on java.util.Collection is provided to determine if a collection has any elements. +Comparing the value of size() to 0 does not convey intent as well as the isEmpty() method.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.bestpractices.UseCollectionIsEmptyRule
+ +Example(s):
+ +public class Foo {
+ void good() {
+ List foo = getList();
+ if (foo.isEmpty()) {
+ // blah
+ }
+ }
+
+ void bad() {
+ List foo = getList();
+ if (foo.size() == 0) {
+ // blah
+ }
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/bestpractices.xml/UseCollectionIsEmpty" />
+
Since: PMD 6.12.0
+ +Priority: Medium (3)
+ +Minimum Language Version: Java 1.7
+ +Java 7 introduced the try-with-resources statement. This statement ensures that each resource is closed at the end
+of the statement. It avoids the need of explicitly closing the resources in a finally block. Additionally exceptions
+are better handled: If an exception occurred both in the try
block and finally
block, then the exception from
+the try block was suppressed. With the try
-with-resources statement, the exception thrown from the try-block is
+preserved.
This rule is defined by the following XPath expression:
+//TryStatement[FinallyStatement//Name[
+ tokenize(@Image, '\.')[last()] = $closeMethods
+][
+ pmd-java:typeIs('java.lang.AutoCloseable')
+ or
+ ../../PrimarySuffix/Arguments//PrimaryPrefix[pmd-java:typeIs('java.lang.AutoCloseable')]
+]]
+
Example(s):
+ +public class TryWithResources {
+ public void run() {
+ InputStream in = null;
+ try {
+ in = openInputStream();
+ int i = in.read();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ try {
+ if (in != null) in.close();
+ } catch (IOException ignored) {
+ // ignored
+ }
+ }
+
+ // better use try-with-resources
+ try (InputStream in2 = openInputStream()) {
+ int i = in2.read();
+ }
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
closeMethods | +close , closeQuietly | +Method names in finally block, which trigger this rule | +yes. Delimiter is ‘,’. | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/bestpractices.xml/UseTryWithResources" />
+
Use this rule and customize it:
+<rule ref="category/java/bestpractices.xml/UseTryWithResources">
+ <properties>
+ <property name="closeMethods" value="close,closeQuietly" />
+ </properties>
+</rule>
+
Since: PMD 5.0
+ +Priority: Medium Low (4)
+ +Minimum Language Version: Java 1.5
+ +Java 5 introduced the varargs parameter declaration for methods and constructors. This syntactic +sugar provides flexibility for users of these methods and constructors, allowing them to avoid +having to deal with the creation of an array.
+ +This rule is defined by the following XPath expression:
+//FormalParameters/FormalParameter
+ [position()=last()]
+ [VariableDeclaratorId/@ArrayType=true()]
+ [@Varargs=false()]
+ [not (./Type[@ArrayType=true()]/ReferenceType[PrimitiveType[@Image='byte']])]
+ [not (./Type/ReferenceType[ClassOrInterfaceType[@Image='Byte']])]
+ [not (./Type/PrimitiveType[@Image='byte'])]
+ [not (ancestor::MethodDeclaration/preceding-sibling::Annotation/*/Name[@Image='Override'])]
+ [not(
+ ancestor::MethodDeclaration
+ [ @Public=true()
+ and @Static=true()
+ and child::ResultType[@Void=true()]
+ and @Name = 'main'
+ and @Arity = 1
+ ]
+ (: Type of the formal parameter here. :)
+ and pmd-java:typeIs('java.lang.String[]')
+ )]
+
Example(s):
+ +public class Foo {
+ public void foo(String s, Object[] args) {
+ // Do something here...
+ }
+
+ public void bar(String s, Object... args) {
+ // Ahh, varargs tastes much better...
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/bestpractices.xml/UseVarargs" />
+
Since: PMD 6.13.0
+ +Priority: Medium (3)
+ +do {} while (true);
requires reading the end of the statement before it is
+apparent that it loops forever, whereas while (true) {}
is easier to understand.
do {} while (false);
is redundant, and if an inner variable scope is required,
+a block {}
is sufficient.
while (false) {}
will never execute the block and can be removed in its entirety.
This rule is defined by the following XPath expression:
+//DoStatement[Expression/PrimaryExpression/PrimaryPrefix/Literal/BooleanLiteral] |
+//WhileStatement[Expression/PrimaryExpression/PrimaryPrefix/Literal/BooleanLiteral[@True = false()]]
+
Example(s):
+ +public class Example {
+ {
+ while (true) { } // allowed
+ while (false) { } // disallowed
+ do { } while (true); // disallowed
+ do { } while (false); // disallowed
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/bestpractices.xml/WhileLoopWithLiteralBoolean" />
+
Deprecated
+ +Since: PMD 1.4
+ +Priority: Medium (3)
+ +Abstract classes should be named ‘AbstractXXX’.
+ +This rule is deprecated and will be removed with PMD 7.0.0. The rule is replaced
+by ClassNamingConventions
.
This rule is defined by the following XPath expression:
+//ClassOrInterfaceDeclaration
+ [@Abstract= true() and @Interface= false()]
+ [not (starts-with(@SimpleName,'Abstract'))]
+|
+//ClassOrInterfaceDeclaration
+ [@Abstract= false()]
+ [$strict= true()]
+ [starts-with(@SimpleName, 'Abstract')]
+
Example(s):
+ +public abstract class Foo { // should be AbstractFoo
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
strict | +true | +Also flag classes, that are named Abstract, but are not abstract. | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/codestyle.xml/AbstractNaming" />
+
Use this rule and customize it:
+<rule ref="category/java/codestyle.xml/AbstractNaming">
+ <properties>
+ <property name="strict" value="true" />
+ </properties>
+</rule>
+
Since: PMD 1.04
+ +Priority: Medium (3)
+ +Each non-static class should declare at least one constructor. +Classes with solely static members are ignored, refer to UseUtilityClassRule to detect those.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.codestyle.AtLeastOneConstructorRule
+ +Example(s):
+ +public class Foo {
+ // missing constructor
+ public void doSomething() { ... }
+ public void doOtherThing { ... }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
ignoredAnnotations | +lombok.Data | lombok.Value | lombok.Builder | lombok.NoArgsConstructor | lombok.RequiredArgsConstructor | lombok.AllArgsConstructor | +Fully qualified names of the annotation types that should be ignored by this rule | +yes. Delimiter is ‘|’. | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/codestyle.xml/AtLeastOneConstructor" />
+
Use this rule and customize it:
+<rule ref="category/java/codestyle.xml/AtLeastOneConstructor">
+ <properties>
+ <property name="ignoredAnnotations" value="lombok.Data|lombok.Value|lombok.Builder|lombok.NoArgsConstructor|lombok.RequiredArgsConstructor|lombok.AllArgsConstructor" />
+ </properties>
+</rule>
+
Since: PMD 1.5
+ +Priority: Medium (3)
+ +Avoid using dollar signs in variable/method/class/interface names.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.codestyle.AvoidDollarSignsRule
+ +Example(s):
+ +public class Fo$o { // not a recommended name
+}
+
Use this rule by referencing it:
+<rule ref="category/java/codestyle.xml/AvoidDollarSigns" />
+
Deprecated
+ +Since: PMD 4.1
+ +Priority: Medium (3)
+ +Avoid using final local variables, turn them into fields.
+ +Note that this is a controversial rule which is merely useful to enforce a certain code style +(which is contradictory to good coding practices in most of the cases it’s applied to) and +avoid local literals being declared in a scope smaller than the class.
+ +Also note, that this rule is the opposite of LocalVariableCouldBeFinal
.
+Having both rules enabled results in contradictory violations being reported.
This rule is deprecated and will be removed with PMD 7.0.0. There is no replacement planned.
+If the goal is to avoid defining constants in a scope smaller than the class, then the rule
+AvoidDuplicateLiterals
should be used instead.
This rule is defined by the following XPath expression:
+//LocalVariableDeclaration[
+ @Final = true()
+ and not(../../ForStatement)
+ and
+ (
+ (count(VariableDeclarator/VariableInitializer) = 0)
+ or
+ (VariableDeclarator/VariableInitializer/Expression/PrimaryExpression/PrimaryPrefix/Literal)
+ )
+]
+
Example(s):
+ +public class MyClass {
+ public void foo() {
+ final String finalLocalVariable;
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/codestyle.xml/AvoidFinalLocalVariable" />
+
Deprecated
+ +Since: PMD 5.0
+ +Priority: Medium Low (4)
+ +Prefixing parameters by ‘in’ or ‘out’ pollutes the name of the parameters and reduces code readability. +To indicate whether or not a parameter will be modify in a method, its better to document method +behavior with Javadoc.
+ +This rule is deprecated and will be removed with PMD 7.0.0. The rule is replaced
+by the more general rule FormalParameterNamingConventions
.
This rule is defined by the following XPath expression:
+//MethodDeclaration/MethodDeclarator/FormalParameters/FormalParameter/VariableDeclaratorId[
+ pmd:matches(@Name,'^in[A-Z].*','^out[A-Z].*','^in$','^out$')
+]
+
Example(s):
+ +// Not really clear
+public class Foo {
+ public void bar(
+ int inLeftOperand,
+ Result outRightOperand) {
+ outRightOperand.setValue(inLeftOperand * outRightOperand.getValue());
+ }
+}
+
// Far more useful
+public class Foo {
+ /**
+ *
+ * @param leftOperand, (purpose), not modified by method.
+ * @param rightOperand (purpose), will be modified by the method: contains the result.
+ */
+ public void bar(
+ int leftOperand,
+ Result rightOperand) {
+ rightOperand.setValue(leftOperand * rightOperand.getValue());
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/codestyle.xml/AvoidPrefixingMethodParameters" />
+
Since: PMD 2.1
+ +Priority: Medium (3)
+ +Do not use protected fields in final classes since they cannot be subclassed. +Clarify your intent by using private or package access modifiers instead.
+ +This rule is defined by the following XPath expression:
+//ClassOrInterfaceDeclaration[@Final= true()]
+/ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration
+/FieldDeclaration[@Protected= true()]
+
Example(s):
+ +public final class Bar {
+ private int x;
+ protected int y; // bar cannot be subclassed, so is y really private or package visible?
+ Bar() {}
+}
+
Use this rule by referencing it:
+<rule ref="category/java/codestyle.xml/AvoidProtectedFieldInFinalClass" />
+
Since: PMD 5.1
+ +Priority: Medium (3)
+ +Do not use protected methods in most final classes since they cannot be subclassed. This should +only be allowed in final classes that extend other classes with protected methods (whose +visibility cannot be reduced). Clarify your intent by using private or package access modifiers instead.
+ +This rule is defined by the following XPath expression:
+//ClassOrInterfaceDeclaration[@Final= true() and not(ExtendsList)]
+/ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration
+/MethodDeclaration[@Protected=true() and @Name != 'finalize']
+
Example(s):
+ +public final class Foo {
+ private int bar() {}
+ protected int baz() {} // Foo cannot be subclassed, and doesn't extend anything, so is baz() really private or package visible?
+}
+
Use this rule by referencing it:
+<rule ref="category/java/codestyle.xml/AvoidProtectedMethodInFinalClassNotExtending" />
+
Since: PMD 4.1
+ +Priority: Medium High (2)
+ +Unnecessary reliance on Java Native Interface (JNI) calls directly reduces application portability +and increases the maintenance burden.
+ +This rule is defined by the following XPath expression:
+//Name[starts-with(@Image,'System.loadLibrary')]
+
Example(s):
+ +public class SomeJNIClass {
+
+ public SomeJNIClass() {
+ System.loadLibrary("nativelib");
+ }
+
+ static {
+ System.loadLibrary("nativelib");
+ }
+
+ public void invalidCallsInMethod() throws SecurityException, NoSuchMethodException {
+ System.loadLibrary("nativelib");
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/codestyle.xml/AvoidUsingNativeCode" />
+
Since: PMD 4.0
+ +Priority: Medium Low (4)
+ +Methods that return boolean results should be named as predicate statements to denote this. +I.e, ‘isReady()’, ‘hasValues()’, ‘canCommit()’, ‘willFail()’, etc. Avoid the use of the ‘get’ +prefix for these methods.
+ +This rule is defined by the following XPath expression:
+//MethodDeclaration
+ [starts-with(@Name, 'get')]
+ [@Arity = 0 or $checkParameterizedMethods = true()]
+ [
+ ResultType/Type/PrimitiveType[@Image = 'boolean']
+ and not(../Annotation//Name[@Image = 'Override'])
+ ]
+
Example(s):
+ +public boolean getFoo(); // bad
+public boolean isFoo(); // ok
+public boolean getFoo(boolean bar); // ok, unless checkParameterizedMethods=true
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
checkParameterizedMethods | +false | +Check parameterized methods | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/codestyle.xml/BooleanGetMethodName" />
+
Use this rule and customize it:
+<rule ref="category/java/codestyle.xml/BooleanGetMethodName">
+ <properties>
+ <property name="checkParameterizedMethods" value="false" />
+ </properties>
+</rule>
+
Since: PMD 3.0
+ +Priority: Medium (3)
+ +It is a good practice to call super() in a constructor. If super() is not called but +another constructor (such as an overloaded constructor) is called, this rule will not report it.
+ +This rule is defined by the following XPath expression:
+//ClassOrInterfaceDeclaration[ExtendsList/*]
+/ClassOrInterfaceBody
+ /ClassOrInterfaceBodyDeclaration
+ /ConstructorDeclaration[ not(.//ExplicitConstructorInvocation) ]
+
Example(s):
+ +public class Foo extends Bar{
+ public Foo() {
+ // call the constructor of Bar
+ super();
+ }
+ public Foo(int code) {
+ // do something with code
+ this();
+ // no problem with this
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/codestyle.xml/CallSuperInConstructor" />
+
Since: PMD 1.2
+ +Priority: High (1)
+ +Configurable naming conventions for type declarations. This rule reports +type declarations which do not match the regex that applies to their +specific kind (e.g. enum or interface). Each regex can be configured through +properties.
+ +By default this rule uses the standard Java naming convention (Pascal case), +and reports utility class names not ending with ‘Util’.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.codestyle.ClassNamingConventionsRule
+ +Example(s):
+ +// This is Pascal case, the recommended naming convention in Java
+// Note that the default values of this rule don't allow underscores
+// or accented characters in type names
+public class FooBar {}
+
+// You may want abstract classes to be named 'AbstractXXX',
+// in which case you can customize the regex for abstract
+// classes to 'Abstract[A-Z]\w+'
+public abstract class Thing {}
+
+// This class doesn't respect the convention, and will be flagged
+public class Éléphant {}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
classPattern | +[A-Z][a-zA-Z0-9]* | +Regex which applies to concrete class names | +no | +
abstractClassPattern | +[A-Z][a-zA-Z0-9]* | +Regex which applies to abstract class names | +no | +
interfacePattern | +[A-Z][a-zA-Z0-9]* | +Regex which applies to interface names | +no | +
enumPattern | +[A-Z][a-zA-Z0-9]* | +Regex which applies to enum names | +no | +
annotationPattern | +[A-Z][a-zA-Z0-9]* | +Regex which applies to annotation names | +no | +
utilityClassPattern | +[A-Z][a-zA-Z0-9]+(Utils?|Helper|Constants) | +Regex which applies to utility class names | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/codestyle.xml/ClassNamingConventions" />
+
Use this rule and customize it:
+<rule ref="category/java/codestyle.xml/ClassNamingConventions">
+ <properties>
+ <property name="classPattern" value="[A-Z][a-zA-Z0-9]*" />
+ <property name="abstractClassPattern" value="[A-Z][a-zA-Z0-9]*" />
+ <property name="interfacePattern" value="[A-Z][a-zA-Z0-9]*" />
+ <property name="enumPattern" value="[A-Z][a-zA-Z0-9]*" />
+ <property name="annotationPattern" value="[A-Z][a-zA-Z0-9]*" />
+ <property name="utilityClassPattern" value="[A-Z][a-zA-Z0-9]+(Utils?|Helper|Constants)" />
+ </properties>
+</rule>
+
Since: PMD 5.4.0
+ +Priority: Medium (3)
+ +To avoid mistakes if we want that an Annotation, Class, Enum, Method, Constructor or Field have a default access modifier
+we must add a comment at the beginning of it’s declaration.
+By default the comment must be /* default */
or /* package */
, if you want another, you have to provide a regular expression.
+This rule ignores by default all cases that have a @VisibleForTesting annotation. Use the
+property "ignoredAnnotations" to customize the recognized annotations.
This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.codestyle.CommentDefaultAccessModifierRule
+ +Example(s):
+ +public class Foo {
+ final String stringValue = "some string";
+ String getString() {
+ return stringValue;
+ }
+
+ class NestedFoo {
+ }
+}
+
+// should be
+public class Foo {
+ /* default */ final String stringValue = "some string";
+ /* default */ String getString() {
+ return stringValue;
+ }
+
+ /* default */ class NestedFoo {
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
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 | +
checkTopLevelTypes | +false | +Check for default access modifier in top-level classes, annotations, and enums | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/codestyle.xml/CommentDefaultAccessModifier" />
+
Use this rule and customize it:
+<rule ref="category/java/codestyle.xml/CommentDefaultAccessModifier">
+ <properties>
+ <property name="ignoredAnnotations" value="com.google.common.annotations.VisibleForTesting|android.support.annotation.VisibleForTesting" />
+ <property name="regex" value="\/\*\s+(default|package)\s+\*\/" />
+ <property name="checkTopLevelTypes" value="false" />
+ </properties>
+</rule>
+
Since: PMD 1.9
+ +Priority: Medium (3)
+ +Avoid negation within an "if" expression with an "else" clause. For example, rephrase:
+if (x != y) diff(); else same();
as: if (x == y) same(); else diff();
.
Most "if (x != y)" cases without an "else" are often return cases, so consistent use of this +rule makes the code easier to read. Also, this resolves trivial ordering problems, such +as "does the error case go first?" or "does the common case go first?".
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.codestyle.ConfusingTernaryRule
+ +Example(s):
+ +boolean bar(int x, int y) {
+ return (x != y) ? diff : same;
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
ignoreElseIf | +false | +Ignore conditions with an else-if case | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/codestyle.xml/ConfusingTernary" />
+
Use this rule and customize it:
+<rule ref="category/java/codestyle.xml/ConfusingTernary">
+ <properties>
+ <property name="ignoreElseIf" value="false" />
+ </properties>
+</rule>
+
Since: PMD 6.2.0
+ +Priority: Medium (3)
+ +Enforce a policy for braces on control statements. It is recommended to use braces on ‘if … else’ +statements and loop statements, even if they are optional. This usually makes the code clearer, and +helps prepare the future when you need to add another statement. That said, this rule lets you control +which statements are required to have braces via properties.
+ +From 6.2.0 on, this rule supersedes WhileLoopMustUseBraces, ForLoopMustUseBraces, IfStmtMustUseBraces, +and IfElseStmtMustUseBraces.
+ +This rule is defined by the following XPath expression:
+//WhileStatement[$checkWhileStmt and not(Statement/Block) and not($allowEmptyLoop and Statement/EmptyStatement)]
+ |
+ //ForStatement[$checkForStmt and not(Statement/Block) and not($allowEmptyLoop and Statement/EmptyStatement)]
+ |
+ //DoStatement[$checkDoWhileStmt and not(Statement/Block) and not($allowEmptyLoop and Statement/EmptyStatement)]
+ |
+ (: The violation is reported on the sub statement -- not the if statement :)
+ //Statement[$checkIfElseStmt and parent::IfStatement and not(child::Block or child::IfStatement)
+ (: Whitelists single if statements :)
+ and ($checkSingleIfStmt
+ (: Inside this not(...) is the definition of a "single if statement" :)
+ or not(count(../Statement) = 1 (: No else stmt :)
+ (: Not the last branch of an 'if ... else if' chain :)
+ and not(parent::IfStatement[parent::Statement[parent::IfStatement]])))]
+ |
+ (: Reports case labels if one of their subordinate statements is not braced :)
+ //SwitchLabel[$checkCaseStmt]
+ [count(following-sibling::BlockStatement except following-sibling::SwitchLabel[1]/following-sibling::BlockStatement) > 1
+ or (some $stmt (: in only the block statements until the next label :)
+ in following-sibling::BlockStatement except following-sibling::SwitchLabel[1]/following-sibling::BlockStatement
+ satisfies not($stmt/Statement/Block))]
+
Example(s):
+ +while (true) // not recommended
+ x++;
+
+while (true) { // preferred approach
+ x++;
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
checkIfElseStmt | +true | +Require that ‘if … else’ statements use braces | +no | +
checkSingleIfStmt | +true | +Require that ‘if’ statements with a single branch use braces | +no | +
checkWhileStmt | +true | +Require that ‘while’ loops use braces | +no | +
checkForStmt | +true | +Require that ‘for’ loops should use braces | +no | +
checkDoWhileStmt | +true | +Require that ‘do … while’ loops use braces | +no | +
checkCaseStmt | +false | +Require that cases of a switch have braces | +no | +
allowEmptyLoop | +false | +Allow loops with an empty statement, e.g. ‘while(true);’ | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/codestyle.xml/ControlStatementBraces" />
+
Use this rule and customize it:
+<rule ref="category/java/codestyle.xml/ControlStatementBraces">
+ <properties>
+ <property name="checkIfElseStmt" value="true" />
+ <property name="checkSingleIfStmt" value="true" />
+ <property name="checkWhileStmt" value="true" />
+ <property name="checkForStmt" value="true" />
+ <property name="checkDoWhileStmt" value="true" />
+ <property name="checkCaseStmt" value="false" />
+ <property name="allowEmptyLoop" value="false" />
+ </properties>
+</rule>
+
Since: PMD 3.4
+ +Priority: Medium (3)
+ +Use explicit scoping instead of accidental usage of default package private level. +The rule allows methods and fields annotated with Guava’s @VisibleForTesting and JUnit 5’s annotations.
+ +This rule is defined by the following XPath expression:
+//ClassOrInterfaceDeclaration[@Interface= false()]
+/ClassOrInterfaceBody
+/ClassOrInterfaceBodyDeclaration
+[not(Annotation//Name[
+ pmd-java:typeIs('org.junit.jupiter.api.Test')
+ or pmd-java:typeIs('org.junit.jupiter.api.RepeatedTest')
+ or pmd-java:typeIs('org.junit.jupiter.api.ParameterizedTest')
+ or pmd-java:typeIs('org.junit.jupiter.api.TestFactory')
+ or pmd-java:typeIs('org.junit.jupiter.api.TestTemplate')
+ or pmd-java:typeIs('org.junit.jupiter.api.BeforeAll')
+ or pmd-java:typeIs('org.junit.jupiter.api.AfterAll')
+ or pmd-java:typeIs('org.junit.jupiter.api.BeforeEach')
+ or pmd-java:typeIs('org.junit.jupiter.api.AfterEach')
+ or ends-with(@Image, 'VisibleForTesting')])]
+[
+FieldDeclaration[@PackagePrivate= true()]
+or MethodDeclaration[@PackagePrivate= true()]
+]
+
Use this rule by referencing it:
+<rule ref="category/java/codestyle.xml/DefaultPackage" />
+
Since: PMD 0.5
+ +Priority: Medium Low (4)
+ +Avoid importing anything from the package ‘java.lang’. These classes are automatically imported (JLS 7.5.3).
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.codestyle.DontImportJavaLangRule
+ +Example(s):
+ +import java.lang.String; // this is unnecessary
+
+public class Foo {}
+
+// --- in another source code file...
+
+import java.lang.*; // this is bad
+
+public class Foo {}
+
Use this rule by referencing it:
+<rule ref="category/java/codestyle.xml/DontImportJavaLang" />
+
Since: PMD 0.5
+ +Priority: Medium Low (4)
+ +Duplicate or overlapping import statements should be avoided.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.codestyle.DuplicateImportsRule
+ +Example(s):
+ +import java.lang.String;
+import java.lang.*;
+public class Foo {}
+
Use this rule by referencing it:
+<rule ref="category/java/codestyle.xml/DuplicateImports" />
+
Since: PMD 4.1
+ +Priority: High (1)
+ +Empty or auto-generated methods in an abstract class should be tagged as abstract. This helps to remove their inapproprate +usage by developers who should be implementing their own versions in the concrete subclasses.
+ +This rule is defined by the following XPath expression:
+//ClassOrInterfaceDeclaration[@Abstract = true()]
+ /ClassOrInterfaceBody
+ /ClassOrInterfaceBodyDeclaration
+ /MethodDeclaration[@Abstract = false() and @Native = false()]
+ [
+ ( boolean(./Block[count(./BlockStatement) = 1]/BlockStatement/Statement/ReturnStatement/Expression/PrimaryExpression/PrimaryPrefix/Literal/NullLiteral) = true() )
+ or
+ ( boolean(./Block[count(./BlockStatement) = 1]/BlockStatement/Statement/ReturnStatement/Expression/PrimaryExpression/PrimaryPrefix/Literal[@Image = '0']) = true() )
+ or
+ ( boolean(./Block[count(./BlockStatement) = 1]/BlockStatement/Statement/ReturnStatement/Expression/PrimaryExpression/PrimaryPrefix/Literal[string-length(@Image) = 2]) = true() )
+ or
+ (./Block[count(./BlockStatement) = 1]/BlockStatement/Statement/EmptyStatement)
+ or
+ ( not (./Block/*) )
+ ]
+
Example(s):
+ +public abstract class ShouldBeAbstract {
+ public Object couldBeAbstract() {
+ // Should be abstract method ?
+ return null;
+ }
+
+ public void couldBeAbstract() {
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/codestyle.xml/EmptyMethodInAbstractClassShouldBeAbstract" />
+
Since: PMD 5.0
+ +Priority: Medium Low (4)
+ +No need to explicitly extend Object.
+ +This rule is defined by the following XPath expression:
+//ExtendsList/ClassOrInterfaceType[@Image='Object' or @Image='java.lang.Object']
+
Example(s):
+ +public class Foo extends Object { // not required
+}
+
Use this rule by referencing it:
+<rule ref="category/java/codestyle.xml/ExtendsObject" />
+
Since: PMD 5.0
+ +Priority: Medium (3)
+ +Fields should be declared at the top of the class, before any method declarations, constructors, initializers or inner classes.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.codestyle.FieldDeclarationsShouldBeAtStartOfClassRule
+ +Example(s):
+ +public class HelloWorldBean {
+
+ // Field declared before methods / inner classes - OK
+ private String _thing;
+
+ public String getMessage() {
+ return "Hello World!";
+ }
+
+ // Field declared after methods / inner classes - avoid this
+ private String _fieldInWrongLocation;
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
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 with the default properties by just referencing it:
+<rule ref="category/java/codestyle.xml/FieldDeclarationsShouldBeAtStartOfClass" />
+
Use this rule and customize it:
+<rule ref="category/java/codestyle.xml/FieldDeclarationsShouldBeAtStartOfClass">
+ <properties>
+ <property name="ignoreEnumDeclarations" value="true" />
+ <property name="ignoreAnonymousClassDeclarations" value="true" />
+ <property name="ignoreInterfaceDeclarations" value="false" />
+ </properties>
+</rule>
+
Since: PMD 6.7.0
+ +Priority: High (1)
+ +Configurable naming conventions for field declarations. This rule reports variable declarations +which do not match the regex that applies to their specific kind —e.g. constants (static final), +enum constant, final field. Each regex can be configured through properties.
+ +By default this rule uses the standard Java naming convention (Camel case), and uses the ALL_UPPER +convention for constants and enum constants.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.codestyle.FieldNamingConventionsRule
+ +Example(s):
+ +class Foo {
+ int myField = 1; // This is in camel case, so it's ok
+ int my_Field = 1; // This contains an underscore, it's not ok by default
+ // but you may allow it, or even require the "my_" prefix
+
+ final int FinalField = 1; // you may configure a different convention for final fields,
+ // e.g. here PascalCase: [A-Z][a-zA-Z0-9]*
+
+ interface Interface {
+ double PI = 3.14; // interface "fields" use the constantPattern property
+ }
+
+ enum AnEnum {
+ ORG, NET, COM; // These use a separate property but are set to ALL_UPPER by default
+ }
+ }
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
publicConstantPattern | +[A-Z][A-Z_0-9]* | +Regex which applies to public constant names | +no | +
constantPattern | +[A-Z][A-Z_0-9]* | +Regex which applies to non-public static final field names | +no | +
enumConstantPattern | +[A-Z][A-Z_0-9]* | +Regex which applies to enum constant names | +no | +
finalFieldPattern | +[a-z][a-zA-Z0-9]* | +Regex which applies to final field names | +no | +
staticFieldPattern | +[a-z][a-zA-Z0-9]* | +Regex which applies to static field names | +no | +
defaultFieldPattern | +[a-z][a-zA-Z0-9]* | +Regex which applies to field names | +no | +
exclusions | +serialVersionUID | serialPersistentFields | +Names of fields to whitelist. | +yes. Delimiter is ‘|’. | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/codestyle.xml/FieldNamingConventions" />
+
Use this rule and customize it:
+<rule ref="category/java/codestyle.xml/FieldNamingConventions">
+ <properties>
+ <property name="publicConstantPattern" value="[A-Z][A-Z_0-9]*" />
+ <property name="constantPattern" value="[A-Z][A-Z_0-9]*" />
+ <property name="enumConstantPattern" value="[A-Z][A-Z_0-9]*" />
+ <property name="finalFieldPattern" value="[a-z][a-zA-Z0-9]*" />
+ <property name="staticFieldPattern" value="[a-z][a-zA-Z0-9]*" />
+ <property name="defaultFieldPattern" value="[a-z][a-zA-Z0-9]*" />
+ <property name="exclusions" value="serialVersionUID|serialPersistentFields" />
+ </properties>
+</rule>
+
Since: PMD 1.02
+ +Priority: Medium (3)
+ +Some for loops can be simplified to while loops, this makes them more concise.
+ +This rule is defined by the following XPath expression:
+//ForStatement
+ [not(LocalVariableDeclaration)]
+ [not(ForInit)]
+ [not(ForUpdate)]
+ [Expression]
+
Example(s):
+ +public class Foo {
+ void bar() {
+ for (;true;) true; // No Init or Update part, may as well be: while (true)
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/codestyle.xml/ForLoopShouldBeWhileLoop" />
+
Deprecated
+ +Since: PMD 0.7
+ +Priority: Medium (3)
+ +Avoid using ‘for’ statements without using curly braces. If the code formatting or +indentation is lost then it becomes difficult to separate the code being controlled +from the rest.
+ +This rule is deprecated and will be removed with PMD 7.0.0. The rule is replaced
+by the rule ControlStatementBraces
.
This rule is defined by the following XPath expression:
+//ForStatement[not(Statement/Block)]
+
Example(s):
+ +for (int i = 0; i < 42; i++)
+ foo();
+
Use this rule by referencing it:
+<rule ref="category/java/codestyle.xml/ForLoopsMustUseBraces" />
+
Since: PMD 6.6.0
+ +Priority: High (1)
+ +Configurable naming conventions for formal parameters of methods and lambdas. +This rule reports formal parameters which do not match the regex that applies to their +specific kind (e.g. lambda parameter, or final formal parameter). Each regex can be +configured through properties.
+ +By default this rule uses the standard Java naming convention (Camel case).
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.codestyle.FormalParameterNamingConventionsRule
+ +Example(s):
+ +class Foo {
+
+ abstract void bar(int myInt); // This is Camel case, so it's ok
+
+ void bar(int my_i) { // this will be reported
+
+ }
+
+ void lambdas() {
+
+ // lambdas parameters can be configured separately
+ Consumer<String> lambda1 = s_str -> { };
+
+ // lambda parameters with an explicit type can be configured separately
+ Consumer<String> lambda1 = (String str) -> { };
+
+ }
+
+ }
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
methodParameterPattern | +[a-z][a-zA-Z0-9]* | +Regex which applies to formal parameter names | +no | +
finalMethodParameterPattern | +[a-z][a-zA-Z0-9]* | +Regex which applies to final formal parameter names | +no | +
lambdaParameterPattern | +[a-z][a-zA-Z0-9]* | +Regex which applies to inferred-type lambda parameter names | +no | +
explicitLambdaParameterPattern | +[a-z][a-zA-Z0-9]* | +Regex which applies to explicitly-typed lambda parameter names | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/codestyle.xml/FormalParameterNamingConventions" />
+
Use this rule and customize it:
+<rule ref="category/java/codestyle.xml/FormalParameterNamingConventions">
+ <properties>
+ <property name="methodParameterPattern" value="[a-z][a-zA-Z0-9]*" />
+ <property name="finalMethodParameterPattern" value="[a-z][a-zA-Z0-9]*" />
+ <property name="lambdaParameterPattern" value="[a-z][a-zA-Z0-9]*" />
+ <property name="explicitLambdaParameterPattern" value="[a-z][a-zA-Z0-9]*" />
+ </properties>
+</rule>
+
Since: PMD 4.2.6
+ +Priority: Medium Low (4)
+ +Names for references to generic values should be limited to a single uppercase letter.
+ +This rule is defined by the following XPath expression:
+//TypeDeclaration/ClassOrInterfaceDeclaration/TypeParameters/TypeParameter[
+ string-length(@Image) > 1
+ or
+ upper-case(@Image) != @Image
+]
+
Example(s):
+ +public interface GenericDao<E extends BaseModel, K extends Serializable> extends BaseDao {
+ // This is ok...
+}
+
+public interface GenericDao<E extends BaseModel, K extends Serializable> {
+ // Also this
+}
+
+public interface GenericDao<e extends BaseModel, K extends Serializable> {
+ // 'e' should be an 'E'
+}
+
+public interface GenericDao<EF extends BaseModel, K extends Serializable> {
+ // 'EF' is not ok.
+}
+
Use this rule by referencing it:
+<rule ref="category/java/codestyle.xml/GenericsNaming" />
+
Since: PMD 6.4.0
+ +Priority: Medium (3)
+ +Minimum Language Version: Java 1.7
+ +Identical catch
branches use up vertical space and increase the complexity of code without
+adding functionality. It’s better style to collapse identical branches into a single multi-catch
+branch.
This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.codestyle.IdenticalCatchBranchesRule
+ +Example(s):
+ +try {
+ // do something
+} catch (IllegalArgumentException e) {
+ throw e;
+} catch (IllegalStateException e) { // Can be collapsed into the previous block
+ throw e;
+}
+
+try {
+ // do something
+} catch (IllegalArgumentException | IllegalStateException e) { // This is better
+ throw e;
+}
+
Use this rule by referencing it:
+<rule ref="category/java/codestyle.xml/IdenticalCatchBranches" />
+
Deprecated
+ +Since: PMD 0.2
+ +Priority: Medium (3)
+ +Avoid using if..else statements without using surrounding braces. If the code formatting +or indentation is lost then it becomes difficult to separate the code being controlled +from the rest.
+ +This rule is deprecated and will be removed with PMD 7.0.0. The rule is replaced
+by the rule ControlStatementBraces
.
This rule is defined by the following XPath expression:
+//Statement
+ [parent::IfStatement[@Else= true()]]
+ [not(child::Block)]
+ [not(child::IfStatement)]
+
Example(s):
+ +// this is OK
+if (foo) x++;
+
+ // but this is not
+if (foo)
+ x = x+1;
+ else
+ x = x-1;
+
Use this rule by referencing it:
+<rule ref="category/java/codestyle.xml/IfElseStmtsMustUseBraces" />
+
Deprecated
+ +Since: PMD 1.0
+ +Priority: Medium (3)
+ +Avoid using if statements without using braces to surround the code block. If the code +formatting or indentation is lost then it becomes difficult to separate the code being +controlled from the rest.
+ +This rule is deprecated and will be removed with PMD 7.0.0. The rule is replaced
+by the rule ControlStatementBraces
.
This rule is defined by the following XPath expression:
+//IfStatement[count(*) < 3][not(Statement/Block)]
+
Example(s):
+ +if (foo) // not recommended
+ x++;
+
+if (foo) { // preferred approach
+ x++;
+}
+
Use this rule by referencing it:
+<rule ref="category/java/codestyle.xml/IfStmtsMustUseBraces" />
+
Since: PMD 6.7.0
+ +Priority: Medium (3)
+ +This rule finds Linguistic Naming Antipatterns. It checks for fields, that are named, as if they should +be boolean but have a different type. It also checks for methods, that according to their name, should +return a boolean, but don’t. Further, it checks, that getters return something and setters won’t. +Finally, it checks that methods, that start with "to" - so called transform methods - actually return +something, since according to their name, they should convert or transform one object into another. +There is additionally an option, to check for methods that contain "To" in their name - which are +also transform methods. However, this is disabled by default, since this detection is prone to +false positives.
+ +For more information, see Linguistic Antipatterns - What They Are and How +Developers Perceive Them.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.codestyle.LinguisticNamingRule
+ +Example(s):
+ +public class LinguisticNaming {
+ int isValid; // the field name indicates a boolean, but it is an int.
+ boolean isTrue; // correct type of the field
+
+ void myMethod() {
+ int hasMoneyLocal; // the local variable name indicates a boolean, but it is an int.
+ boolean hasSalaryLocal; // correct naming and type
+ }
+
+ // the name of the method indicates, it is a boolean, but the method returns an int.
+ int isValid() {
+ return 1;
+ }
+ // correct naming and return type
+ boolean isSmall() {
+ return true;
+ }
+
+ // the name indicates, this is a setter, but it returns something
+ int setName() {
+ return 1;
+ }
+
+ // the name indicates, this is a getter, but it doesn't return anything
+ void getName() {
+ // nothing to return?
+ }
+
+ // the name indicates, it transforms an object and should return the result
+ void toDataType() {
+ // nothing to return?
+ }
+ // the name indicates, it transforms an object and should return the result
+ void grapeToWine() {
+ // nothing to return?
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
ignoredAnnotations | +java.lang.Override | +Fully qualified names of the annotation types that should be ignored by this rule | +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 | +
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 with the default properties by just referencing it:
+<rule ref="category/java/codestyle.xml/LinguisticNaming" />
+
Use this rule and customize it:
+<rule ref="category/java/codestyle.xml/LinguisticNaming">
+ <properties>
+ <property name="ignoredAnnotations" value="java.lang.Override" />
+ <property name="checkBooleanMethod" value="true" />
+ <property name="checkGetters" value="true" />
+ <property name="checkSetters" value="true" />
+ <property name="checkPrefixedTransformMethods" value="true" />
+ <property name="checkTransformMethods" value="false" />
+ <property name="booleanMethodPrefixes" value="is|has|can|have|will|should" />
+ <property name="transformMethodNames" value="to|as" />
+ <property name="checkFields" value="true" />
+ <property name="checkVariables" value="true" />
+ <property name="booleanFieldPrefixes" value="is|has|can|have|will|should" />
+ </properties>
+</rule>
+
Since: PMD 4.0
+ +Priority: Medium Low (4)
+ +The Local Home interface of a Session EJB should be suffixed by ‘LocalHome’.
+ +This rule is defined by the following XPath expression:
+//ClassOrInterfaceDeclaration
+[
+ (
+ (./ExtendsList/ClassOrInterfaceType[ends-with(@Image,'EJBLocalHome')])
+ )
+ and
+ not
+ (
+ ends-with(@SimpleName,'LocalHome')
+ )
+]
+
Example(s):
+ +public interface MyBeautifulLocalHome extends javax.ejb.EJBLocalHome {} // proper name
+
+public interface MissingProperSuffix extends javax.ejb.EJBLocalHome {} // non-standard name
+
Use this rule by referencing it:
+<rule ref="category/java/codestyle.xml/LocalHomeNamingConvention" />
+
Since: PMD 4.0
+ +Priority: Medium Low (4)
+ +The Local Interface of a Session EJB should be suffixed by ‘Local’.
+ +This rule is defined by the following XPath expression:
+//ClassOrInterfaceDeclaration
+[
+ (
+ (./ExtendsList/ClassOrInterfaceType[ends-with(@Image,'EJBLocalObject')])
+ )
+ and
+ not
+ (
+ ends-with(@SimpleName,'Local')
+ )
+]
+
Example(s):
+ +public interface MyLocal extends javax.ejb.EJBLocalObject {} // proper name
+
+public interface MissingProperSuffix extends javax.ejb.EJBLocalObject {} // non-standard name
+
Use this rule by referencing it:
+<rule ref="category/java/codestyle.xml/LocalInterfaceSessionNamingConvention" />
+
Since: PMD 2.2
+ +Priority: Medium (3)
+ +A local variable assigned only once can be declared final.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.codestyle.LocalVariableCouldBeFinalRule
+ +Example(s):
+ +public class Bar {
+ public void foo () {
+ String txtA = "a"; // if txtA will not be assigned again it is better to do this:
+ final String txtB = "b";
+ }
+}
+
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 with the default properties by just referencing it:
+<rule ref="category/java/codestyle.xml/LocalVariableCouldBeFinal" />
+
Use this rule and customize it:
+<rule ref="category/java/codestyle.xml/LocalVariableCouldBeFinal">
+ <properties>
+ <property name="ignoreForEachDecl" value="false" />
+ </properties>
+</rule>
+
Since: PMD 6.6.0
+ +Priority: High (1)
+ +Configurable naming conventions for local variable declarations and other locally-scoped +variables. This rule reports variable declarations which do not match the regex that applies to their +specific kind (e.g. final variable, or catch-clause parameter). Each regex can be configured through +properties.
+ +By default this rule uses the standard Java naming convention (Camel case).
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.codestyle.LocalVariableNamingConventionsRule
+ +Example(s):
+ +class Foo {
+ void bar() {
+ int localVariable = 1; // This is in camel case, so it's ok
+ int local_variable = 1; // This will be reported unless you change the regex
+
+ final int i_var = 1; // final local variables can be configured separately
+
+ try {
+ foo();
+ } catch (IllegalArgumentException e_illegal) {
+ // exception block parameters can be configured separately
+ }
+
+ }
+ }
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
localVarPattern | +[a-z][a-zA-Z0-9]* | +Regex which applies to non-final local variable names | +no | +
finalVarPattern | +[a-z][a-zA-Z0-9]* | +Regex which applies to final local variable names | +no | +
catchParameterPattern | +[a-z][a-zA-Z0-9]* | +Regex which applies to exception block parameter names | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/codestyle.xml/LocalVariableNamingConventions" />
+
Use this rule and customize it:
+<rule ref="category/java/codestyle.xml/LocalVariableNamingConventions">
+ <properties>
+ <property name="localVarPattern" value="[a-z][a-zA-Z0-9]*" />
+ <property name="finalVarPattern" value="[a-z][a-zA-Z0-9]*" />
+ <property name="catchParameterPattern" value="[a-z][a-zA-Z0-9]*" />
+ </properties>
+</rule>
+
Since: PMD 0.3
+ +Priority: Medium (3)
+ +Fields, formal arguments, or local variable names that are too long can make the code difficult to follow.
+ +This rule is defined by the following XPath expression:
+//VariableDeclaratorId[string-length(@Name) > $minimum]
+
Example(s):
+ +public class Something {
+ int reallyLongIntName = -3; // VIOLATION - Field
+ public static void main( String argumentsList[] ) { // VIOLATION - Formal
+ int otherReallyLongName = -5; // VIOLATION - Local
+ for (int interestingIntIndex = 0; // VIOLATION - For
+ interestingIntIndex < 10;
+ interestingIntIndex ++ ) {
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
minimum | +17 | +The variable length reporting threshold | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/codestyle.xml/LongVariable" />
+
Use this rule and customize it:
+<rule ref="category/java/codestyle.xml/LongVariable">
+ <properties>
+ <property name="minimum" value="17" />
+ </properties>
+</rule>
+
Since: PMD 4.0
+ +Priority: Medium Low (4)
+ +The EJB Specification states that any MessageDrivenBean or SessionBean should be suffixed by ‘Bean’.
+ +This rule is defined by the following XPath expression:
+//TypeDeclaration/ClassOrInterfaceDeclaration
+[
+ (
+ (./ImplementsList/ClassOrInterfaceType[ends-with(@Image,'SessionBean')])
+ or
+ (./ImplementsList/ClassOrInterfaceType[ends-with(@Image,'MessageDrivenBean')])
+ )
+ and
+ not
+ (
+ ends-with(@SimpleName,'Bean')
+ )
+]
+
Example(s):
+ +public class SomeBean implements SessionBean{} // proper name
+
+public class MissingTheProperSuffix implements SessionBean {} // non-standard name
+
Use this rule by referencing it:
+<rule ref="category/java/codestyle.xml/MDBAndSessionBeanNamingConvention" />
+
Since: PMD 2.2
+ +Priority: Medium (3)
+ +A method argument that is never re-assigned within the method can be declared final.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.codestyle.MethodArgumentCouldBeFinalRule
+ +Example(s):
+ +public void foo1 (String param) { // do stuff with param never assigning it
+
+}
+
+public void foo2 (final String param) { // better, do stuff with param never assigning it
+
+}
+
Use this rule by referencing it:
+<rule ref="category/java/codestyle.xml/MethodArgumentCouldBeFinal" />
+
Since: PMD 1.2
+ +Priority: High (1)
+ +Configurable naming conventions for method declarations. This rule reports +method declarations which do not match the regex that applies to their +specific kind (e.g. JUnit test or native method). Each regex can be +configured through properties.
+ +By default this rule uses the standard Java naming convention (Camel case).
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.codestyle.MethodNamingConventionsRule
+ +Example(s):
+ +public class Foo {
+ public void fooStuff() {
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
checkNativeMethods | +true | +Deprecated Check native methods | +no | +
methodPattern | +[a-z][a-zA-Z0-9]* | +Regex which applies to instance method names | +no | +
staticPattern | +[a-z][a-zA-Z0-9]* | +Regex which applies to static method names | +no | +
nativePattern | +[a-z][a-zA-Z0-9]* | +Regex which applies to native method names | +no | +
junit3TestPattern | +test[A-Z0-9][a-zA-Z0-9]* | +Regex which applies to JUnit 3 test method names | +no | +
junit4TestPattern | +[a-z][a-zA-Z0-9]* | +Regex which applies to JUnit 4 test method names | +no | +
junit5TestPattern | +[a-z][a-zA-Z0-9]* | +Regex which applies to JUnit 5 test method names | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/codestyle.xml/MethodNamingConventions" />
+
Use this rule and customize it:
+<rule ref="category/java/codestyle.xml/MethodNamingConventions">
+ <properties>
+ <property name="methodPattern" value="[a-z][a-zA-Z0-9]*" />
+ <property name="staticPattern" value="[a-z][a-zA-Z0-9]*" />
+ <property name="nativePattern" value="[a-z][a-zA-Z0-9]*" />
+ <property name="junit3TestPattern" value="test[A-Z0-9][a-zA-Z0-9]*" />
+ <property name="junit4TestPattern" value="[a-z][a-zA-Z0-9]*" />
+ <property name="junit5TestPattern" value="[a-z][a-zA-Z0-9]*" />
+ </properties>
+</rule>
+
Deprecated
+ +Since: PMD 3.4
+ +Priority: Medium (3)
+ +Detects when a non-field has a name starting with ‘m_’. This usually denotes a field and could be confusing.
+ +This rule is deprecated and will be removed with PMD 7.0.0. The rule is replaced
+by the more general rule
+LocalVariableNamingConventions
.
This rule is defined by the following XPath expression:
+//VariableDeclaratorId
+[starts-with(@Name, 'm_')]
+[not (../../../FieldDeclaration)]
+
Example(s):
+ +public class Foo {
+ private int m_foo; // OK
+ public void bar(String m_baz) { // Bad
+ int m_boz = 42; // Bad
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/codestyle.xml/MIsLeadingVariableName" />
+
Since: PMD 3.3
+ +Priority: Medium (3)
+ +Detects when a class, interface, enum or annotation does not have a package definition.
+ +This rule is defined by the following XPath expression:
+/CompilationUnit[not(./PackageDeclaration)]/TypeDeclaration[1]
+
Example(s):
+ +// no package declaration
+public class ClassInDefaultPackage {
+}
+
Use this rule by referencing it:
+<rule ref="category/java/codestyle.xml/NoPackage" />
+
Since: PMD 1.0
+ +Priority: Medium (3)
+ +A method should have only one exit point, and that should be the last statement in the method.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.codestyle.OnlyOneReturnRule
+ +Example(s):
+ +public class OneReturnOnly1 {
+ public String foo(int x) {
+ if (x > 0) {
+ return "hey"; // first exit
+ }
+ return "hi"; // second exit
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/codestyle.xml/OnlyOneReturn" />
+
Since: PMD 3.3
+ +Priority: Medium (3)
+ +Detects when a package definition contains uppercase characters.
+ +This rule is defined by the following XPath expression:
+//PackageDeclaration/Name[lower-case(@Image)!=@Image]
+
Example(s):
+ +package com.MyCompany; // should be lowercase name
+
+public class SomeClass {
+}
+
Use this rule by referencing it:
+<rule ref="category/java/codestyle.xml/PackageCase" />
+
Since: PMD 5.0
+ +Priority: Medium (3)
+ +Checks for variables that are defined before they might be used. A reference is deemed to be premature if it is created right before a block of code that doesn’t use it that also has the ability to return or throw an exception.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.codestyle.PrematureDeclarationRule
+ +Example(s):
+ +public int getLength(String[] strings) {
+
+ int length = 0; // declared prematurely
+
+ if (strings == null || strings.length == 0) return 0;
+
+ for (String str : strings) {
+ length += str.length();
+ }
+
+ return length;
+}
+
Use this rule by referencing it:
+<rule ref="category/java/codestyle.xml/PrematureDeclaration" />
+
Since: PMD 4.0
+ +Priority: Medium Low (4)
+ +Remote Interface of a Session EJB should not have a suffix.
+ +This rule is defined by the following XPath expression:
+//ClassOrInterfaceDeclaration
+[
+ (
+ (./ExtendsList/ClassOrInterfaceType[ends-with(@Image,'EJBObject')])
+ )
+ and
+ (
+ ends-with(@SimpleName,'Session')
+ or
+ ends-with(@SimpleName,'EJB')
+ or
+ ends-with(@SimpleName,'Bean')
+ )
+]
+
Example(s):
+ +/* Poor Session suffix */
+public interface BadSuffixSession extends javax.ejb.EJBObject {}
+
+/* Poor EJB suffix */
+public interface BadSuffixEJB extends javax.ejb.EJBObject {}
+
+/* Poor Bean suffix */
+public interface BadSuffixBean extends javax.ejb.EJBObject {}
+
Use this rule by referencing it:
+<rule ref="category/java/codestyle.xml/RemoteInterfaceNamingConvention" />
+
Since: PMD 4.0
+ +Priority: Medium Low (4)
+ +A Remote Home interface type of a Session EJB should be suffixed by ‘Home’.
+ +This rule is defined by the following XPath expression:
+//ClassOrInterfaceDeclaration
+[
+ (
+ (./ExtendsList/ClassOrInterfaceType[ends-with(@Image,'EJBHome')])
+ )
+ and
+ not
+ (
+ ends-with(@SimpleName,'Home')
+ )
+]
+
Example(s):
+ +public interface MyBeautifulHome extends javax.ejb.EJBHome {} // proper name
+
+public interface MissingProperSuffix extends javax.ejb.EJBHome {} // non-standard name
+
Use this rule by referencing it:
+<rule ref="category/java/codestyle.xml/RemoteSessionInterfaceNamingConvention" />
+
Since: PMD 5.0
+ +Priority: Medium Low (4)
+ +Short Classnames with fewer than e.g. five characters are not recommended.
+ +This rule is defined by the following XPath expression:
+//ClassOrInterfaceDeclaration[string-length(@SimpleName) < $minimum]
+
Example(s):
+ +public class Foo {
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
minimum | +5 | +Number of characters that are required as a minimum for a class name. | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/codestyle.xml/ShortClassName" />
+
Use this rule and customize it:
+<rule ref="category/java/codestyle.xml/ShortClassName">
+ <properties>
+ <property name="minimum" value="5" />
+ </properties>
+</rule>
+
Since: PMD 0.3
+ +Priority: Medium (3)
+ +Method names that are very short are not helpful to the reader.
+ +This rule is defined by the following XPath expression:
+//MethodDeclaration[string-length(@Name) < $minimum]
+
Example(s):
+ +public class ShortMethod {
+ public void a( int i ) { // Violation
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
minimum | +3 | +Number of characters that are required as a minimum for a method name. | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/codestyle.xml/ShortMethodName" />
+
Use this rule and customize it:
+<rule ref="category/java/codestyle.xml/ShortMethodName">
+ <properties>
+ <property name="minimum" value="3" />
+ </properties>
+</rule>
+
Since: PMD 0.3
+ +Priority: Medium (3)
+ +Fields, local variables, or parameter names that are very short are not helpful to the reader.
+ +This rule is defined by the following XPath expression:
+//VariableDeclaratorId[string-length(@Name) < $minimum]
+ (: ForStatement :)
+ [not(../../..[self::ForInit])]
+ (: Foreach statement :)
+ [not(../../..[self::ForStatement])]
+ (: Catch statement parameter :)
+ [not(../..[self::CatchStatement])]
+ (: Lambda expression parameter :)
+ [not(parent::LambdaExpression or ../../..[self::LambdaExpression])]
+
Example(s):
+ +public class Something {
+ private int q = 15; // field - too short
+ public static void main( String as[] ) { // formal arg - too short
+ int r = 20 + q; // local var - too short
+ for (int i = 0; i < 10; i++) { // not a violation (inside 'for' loop)
+ r += q;
+ }
+ for (Integer i : numbers) { // not a violation (inside 'for-each' loop)
+ r += q;
+ }
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
minimum | +3 | +Number of characters that are required as a minimum for a variable name. | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/codestyle.xml/ShortVariable" />
+
Use this rule and customize it:
+<rule ref="category/java/codestyle.xml/ShortVariable">
+ <properties>
+ <property name="minimum" value="3" />
+ </properties>
+</rule>
+
Deprecated
+ +Since: PMD 2.0
+ +Priority: Medium (3)
+ +Field names using all uppercase characters - Sun’s Java naming conventions indicating constants - should +be declared as final.
+ +This rule is deprecated and will be removed with PMD 7.0.0. The rule is replaced
+by the more general rule FieldNamingConventions
.
This rule is defined by the following XPath expression:
+//ClassOrInterfaceDeclaration[@Interface= false()]
+ /ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/FieldDeclaration
+ [@Final= false()]
+ [VariableDeclarator/VariableDeclaratorId[upper-case(@Name)=@Name]]
+
Example(s):
+ +public class Foo {
+ // this is bad, since someone could accidentally
+ // do PI = 2.71828; which is actually e
+ // final double PI = 3.16; is ok
+ double PI = 3.16;
+}
+
Use this rule by referencing it:
+<rule ref="category/java/codestyle.xml/SuspiciousConstantFieldName" />
+
Since: PMD 4.1
+ +Priority: Medium (3)
+ +If you overuse the static import feature, it can make your program unreadable and +unmaintainable, polluting its namespace with all the static members you import. +Readers of your code (including you, a few months after you wrote it) will not know +which class a static member comes from (Sun 1.5 Language Guide).
+ +This rule is defined by the following XPath expression:
+.[count(ImportDeclaration[@Static = true()]) > $maximumStaticImports]
+
Example(s):
+ +import static Lennon;
+import static Ringo;
+import static George;
+import static Paul;
+import static Yoko; // Too much !
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
maximumStaticImports | +4 | +All static imports can be disallowed by setting this to 0 | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/codestyle.xml/TooManyStaticImports" />
+
Use this rule and customize it:
+<rule ref="category/java/codestyle.xml/TooManyStaticImports">
+ <properties>
+ <property name="maximumStaticImports" value="4" />
+ </properties>
+</rule>
+
Since: PMD 6.2.0
+ +Priority: Medium (3)
+ +Avoid the use of value in annotations when it’s the only element.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.codestyle.UnnecessaryAnnotationValueElementRule
+ +Example(s):
+ +@TestClassAnnotation(value = "TEST")
+public class Foo {
+
+ @TestMemberAnnotation(value = "TEST")
+ private String y;
+
+ @TestMethodAnnotation(value = "TEST")
+ public void bar() {
+ int x = 42;
+ return;
+ }
+}
+
+// should be
+
+@TestClassAnnotation("TEST")
+public class Foo {
+
+ @TestMemberAnnotation("TEST")
+ private String y;
+
+ @TestMethodAnnotation("TEST")
+ public void bar() {
+ int x = 42;
+ return;
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/codestyle.xml/UnnecessaryAnnotationValueElement" />
+
Since: PMD 6.24.0
+ +Priority: Medium (3)
+ +Minimum Language Version: Java 1.5
+ +This rule detects when a cast is unnecessary while accessing collection elements. This rule is mostly useful +for old java code before generics where introduced with java 1.5.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.codestyle.UnnecessaryCastRule
+ +Example(s):
+ +public class UnnecessaryCastSample {
+ public void method() {
+ List<String> stringList = Arrays.asList("a", "b");
+ String element = (String) stringList.get(0); // this cast is unnecessary
+ String element2 = stringList.get(0);
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/codestyle.xml/UnnecessaryCast" />
+
Since: PMD 1.0
+ +Priority: Medium (3)
+ +This rule detects when a constructor is not necessary; i.e., when there is only one constructor and the +constructor is identical to the default constructor. The default constructor should has same access +modifier as the declaring class. In an enum type, the default constructor is implicitly private.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.codestyle.UnnecessaryConstructorRule
+ +Example(s):
+ +public class Foo {
+ public Foo() {}
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
ignoredAnnotations | +javax.inject.Inject | +Fully qualified names of the annotation types that should be ignored by this rule | +yes. Delimiter is ‘|’. | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/codestyle.xml/UnnecessaryConstructor" />
+
Use this rule and customize it:
+<rule ref="category/java/codestyle.xml/UnnecessaryConstructor">
+ <properties>
+ <property name="ignoredAnnotations" value="javax.inject.Inject" />
+ </properties>
+</rule>
+
Since: PMD 5.0
+ +Priority: Medium Low (4)
+ +Import statements allow the use of non-fully qualified names. The use of a fully qualified name +which is covered by an import statement is redundant. Consider using the non-fully qualified name.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.codestyle.UnnecessaryFullyQualifiedNameRule
+ +Example(s):
+ +import java.util.List;
+
+public class Foo {
+ private java.util.List list1; // Unnecessary FQN
+ private List list2; // More appropriate given import of 'java.util.List'
+}
+
Use this rule by referencing it:
+<rule ref="category/java/codestyle.xml/UnnecessaryFullyQualifiedName" />
+
Since: PMD 3.3
+ +Priority: Medium (3)
+ +Avoid the creation of unnecessary local variables
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.codestyle.UnnecessaryLocalBeforeReturnRule
+ +Example(s):
+ +public class Foo {
+ public int foo() {
+ int x = doSomething();
+ return x; // instead, just 'return doSomething();'
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
statementOrderMatters | +true | +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. | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/codestyle.xml/UnnecessaryLocalBeforeReturn" />
+
Use this rule and customize it:
+<rule ref="category/java/codestyle.xml/UnnecessaryLocalBeforeReturn">
+ <properties>
+ <property name="statementOrderMatters" value="true" />
+ </properties>
+</rule>
+
Since: PMD 1.02
+ +Priority: Medium (3)
+ +Fields in interfaces and annotations are automatically public static final
, and methods are public abstract
.
+Classes, interfaces or annotations nested in an interface or annotation are automatically public static
+(all nested interfaces and annotations are automatically static).
+Nested enums are automatically static
.
+For historical reasons, modifiers which are implied by the context are accepted by the compiler, but are superfluous.
This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.codestyle.UnnecessaryModifierRule
+ +Example(s):
+ +public @interface Annotation {
+ public abstract void bar(); // both abstract and public are ignored by the compiler
+ public static final int X = 0; // public, static, and final all ignored
+ public static class Bar {} // public, static ignored
+ public static interface Baz {} // ditto
+}
+public interface Foo {
+ public abstract void bar(); // both abstract and public are ignored by the compiler
+ public static final int X = 0; // public, static, and final all ignored
+ public static class Bar {} // public, static ignored
+ public static interface Baz {} // ditto
+}
+public class Bar {
+ public static interface Baz {} // static ignored
+ public static enum FoorBar { // static ignored
+ FOO;
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/codestyle.xml/UnnecessaryModifier" />
+
Since: PMD 1.3
+ +Priority: Medium (3)
+ +Avoid the use of unnecessary return statements.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.codestyle.UnnecessaryReturnRule
+ +Example(s):
+ +public class Foo {
+ public void bar() {
+ int x = 42;
+ return;
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/codestyle.xml/UnnecessaryReturn" />
+
Since: PMD 6.11.0
+ +Priority: Medium (3)
+ +Minimum Language Version: Java 1.7
+ +Use the diamond operator to let the type be inferred automatically. With the Diamond operator it is possible +to avoid duplication of the type parameters. +Instead, the compiler is now able to infer the parameter types for constructor calls, +which makes the code also more readable.
+ +The diamond operator has been introduced with java 7. However, type inference has been improved further
+with java8, rendering more type parameters unnecessary. This is only possible with java8 and the resulting
+code won’t compile with java7. If you use java7, make sure to enable java7Compatibility
for this rule to avoid
+false positives.
This rule is defined by the following XPath expression:
+(
+//VariableInitializer[preceding-sibling::VariableDeclaratorId[1]/@TypeInferred=false()]
+|
+//StatementExpression[AssignmentOperator and PrimaryExpression/PrimaryPrefix[not(Expression)]]
+)
+/(Expression | Expression[$java7Compatibility = false()]/ConditionalExpression | Expression[$java7Compatibility = false()]/ConditionalExpression/Expression)
+/PrimaryExpression[not(PrimarySuffix) and not(ancestor::ArgumentList)]
+/PrimaryPrefix
+/AllocationExpression
+ [@AnonymousClass=false()]
+ [ClassOrInterfaceType/TypeArguments[@Diamond=false() and not($java7Compatibility = true() and .//TypeArgument[@Wildcard=true()])]]
+ [not(ArrayDimsAndInits)]
+
Example(s):
+ +List<String> strings = new ArrayList<String>(); // unnecessary duplication of type parameters
+List<String> stringsWithDiamond = new ArrayList<>(); // using the diamond operator is more concise
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
java7Compatibility | +false | +If disabled, the rule shows also violations that are applicable for java8+ | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/codestyle.xml/UseDiamondOperator" />
+
Use this rule and customize it:
+<rule ref="category/java/codestyle.xml/UseDiamondOperator">
+ <properties>
+ <property name="java7Compatibility" value="false" />
+ </properties>
+</rule>
+
Since: PMD 5.0
+ +Priority: Medium Low (4)
+ +Useless parentheses should be removed.
+ +This rule is defined by the following XPath expression:
+//Expression[not(parent::PrimaryPrefix)]/PrimaryExpression[count(*)>1]
+ /PrimaryPrefix/Expression
+ [not(./CastExpression)]
+ [not(./ConditionalExpression)]
+ [not(./AdditiveExpression)]
+ [not(./AssignmentOperator)]
+|
+//Expression[not(parent::PrimaryPrefix)]/PrimaryExpression[count(*)=1]
+ /PrimaryPrefix/Expression
+|
+//Expression/ConditionalAndExpression/PrimaryExpression/PrimaryPrefix/Expression[
+ count(*)=1 and
+ not(./CastExpression) and
+ not(./EqualityExpression/MultiplicativeExpression) and
+ not(./ConditionalExpression) and
+ not(./ConditionalOrExpression)]
+|
+//Expression/ConditionalOrExpression/PrimaryExpression/PrimaryPrefix/Expression[
+ count(*)=1 and
+ not(./CastExpression) and
+ not(./ConditionalExpression) and
+ not(./EqualityExpression/MultiplicativeExpression)]
+|
+//Expression/ConditionalExpression/PrimaryExpression/PrimaryPrefix/Expression[
+ count(*)=1 and
+ not(./CastExpression) and
+ not(./EqualityExpression)]
+|
+//Expression/AdditiveExpression[not(./PrimaryExpression/PrimaryPrefix/Literal[@StringLiteral= true()])]
+ /PrimaryExpression[1]/PrimaryPrefix/Expression[
+ count(*)=1 and
+ not(./CastExpression) and
+ not(./AdditiveExpression[@Operator = '-']) and
+ not(./ShiftExpression) and
+ not(./RelationalExpression) and
+ not(./InstanceOfExpression) and
+ not(./EqualityExpression) and
+ not(./AndExpression) and
+ not(./ExclusiveOrExpression) and
+ not(./InclusiveOrExpression) and
+ not(./ConditionalAndExpression) and
+ not(./ConditionalOrExpression) and
+ not(./ConditionalExpression)]
+|
+//Expression/EqualityExpression/PrimaryExpression/PrimaryPrefix/Expression[
+ count(*)=1 and
+ not(./CastExpression) and
+ not(./AndExpression) and
+ not(./InclusiveOrExpression) and
+ not(./ExclusiveOrExpression) and
+ not(./ConditionalExpression) and
+ not(./ConditionalAndExpression) and
+ not(./ConditionalOrExpression) and
+ not(./EqualityExpression)]
+
Example(s):
+ +public class Foo {
+
+ private int _bar1;
+ private Integer _bar2;
+
+ public void setBar(int n) {
+ _bar1 = Integer.valueOf((n)); // here
+ _bar2 = (n); // and here
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/codestyle.xml/UselessParentheses" />
+
Since: PMD 5.4.0
+ +Priority: Medium (3)
+ +Reports qualified this usages in the same class.
+ +This rule is defined by the following XPath expression:
+//PrimaryExpression
+[PrimaryPrefix/Name[@Image]]
+[PrimarySuffix[@Arguments= false() and @ArrayDereference = false()]]
+[not(PrimarySuffix/MemberSelector)]
+[ancestor::ClassOrInterfaceBodyDeclaration[1][@AnonymousInnerClass= false()]]
+/PrimaryPrefix/Name[@Image = ancestor::ClassOrInterfaceDeclaration[1]/@SimpleName]
+
Example(s):
+ +public class Foo {
+ final Foo otherFoo = Foo.this; // use "this" directly
+
+ public void doSomething() {
+ final Foo anotherFoo = Foo.this; // use "this" directly
+ }
+
+ private ActionListener returnListener() {
+ return new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ doSomethingWithQualifiedThis(Foo.this); // This is fine
+ }
+ };
+ }
+
+ private class Foo3 {
+ final Foo myFoo = Foo.this; // This is fine
+ }
+
+ private class Foo2 {
+ final Foo2 myFoo2 = Foo2.this; // Use "this" direclty
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/codestyle.xml/UselessQualifiedThis" />
+
Since: PMD 6.15.0
+ +Priority: Medium (3)
+ +When declaring and initializing array fields or variables, it is not necessary to explicitly create a new array
+using new
. Instead one can simply define the initial content of the array as a expression in curly braces.
E.g. int[] x = new int[] { 1, 2, 3 };
can be written as int[] x = { 1, 2, 3 };
.
This rule is defined by the following XPath expression:
+//VariableDeclarator
+ [VariableDeclaratorId[@ArrayType = true() and @TypeInferred = false()]]
+ [VariableInitializer/Expression/PrimaryExpression/PrimaryPrefix/AllocationExpression/ArrayDimsAndInits/ArrayInitializer]
+
Example(s):
+ +Foo[] x = new Foo[] { ... }; // Overly verbose
+Foo[] x = { ... }; //Equivalent to above line
+
Use this rule by referencing it:
+<rule ref="category/java/codestyle.xml/UseShortArrayInitializer" />
+
Since: PMD 6.10.0
+ +Priority: Medium (3)
+ +Minimum Language Version: Java 1.7
+ +Since Java 1.7, numeric literals can use underscores to separate digits. This rule enforces that +numeric literals above a certain length use these underscores to increase readability.
+ +The rule only supports decimal (base 10) literals for now. The acceptable length under which literals +are not required to have underscores is configurable via a property. Even under that length, underscores +that are misplaced (not making groups of 3 digits) are reported.
+ +This rule is defined by the following XPath expression:
+//Literal[
+ @IntLiteral = true()
+ or @LongLiteral = true()
+ or @DoubleLiteral = true()
+ or @FloatLiteral = true()
+]
+ (: Filter out literals in base other than 10 :)
+ [not(matches(@Image, "^0[^.]"))]
+ (: Filter out ignored field name :)
+ [not(ancestor::VariableDeclarator[1][@Name = 'serialVersionUID'])]
+ [
+ some $num in tokenize(@Image, "[dDfFlLeE+\-]")
+ satisfies not(
+ ( contains($num, ".")
+ and string-length(substring-before($num, ".")) <= $acceptableDecimalLength
+ and string-length(substring-after($num, ".")) <= $acceptableDecimalLength
+ or string-length($num) <= $acceptableDecimalLength
+ )
+ and not(contains($num,"_"))
+ or matches($num, "^[0-9]{1,3}(_[0-9]{3})*(\.([0-9]{3}_)*[0-9]{1,3})?$")
+ )
+ ]
+
Example(s):
+ +public class Foo {
+ private int num = 1000000; // should be 1_000_000
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
acceptableDecimalLength | +4 | +Length under which literals in base 10 are not required to have underscores | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/codestyle.xml/UseUnderscoresInNumericLiterals" />
+
Use this rule and customize it:
+<rule ref="category/java/codestyle.xml/UseUnderscoresInNumericLiterals">
+ <properties>
+ <property name="acceptableDecimalLength" value="4" />
+ </properties>
+</rule>
+
Deprecated
+ +Since: PMD 1.2
+ +Priority: High (1)
+ +A variable naming conventions rule - customize this to your liking. Currently, it +checks for final variables that should be fully capitalized and non-final variables +that should not include underscores.
+ +This rule is deprecated and will be removed with PMD 7.0.0. The rule is replaced
+by the more general rules FieldNamingConventions
,
+FormalParameterNamingConventions
, and
+LocalVariableNamingConventions
.
This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.codestyle.VariableNamingConventionsRule
+ +Example(s):
+ +public class Foo {
+ public static final int MY_NUM = 0;
+ public String myTest = "";
+ DataModule dmTest = new DataModule();
+}
+
This rule has the following properties:
+ +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 ‘,’. | +
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 | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/codestyle.xml/VariableNamingConventions" />
+
Use this rule and customize it:
+<rule ref="category/java/codestyle.xml/VariableNamingConventions">
+ <properties>
+ <property name="parameterSuffix" value="" />
+ <property name="parameterPrefix" value="" />
+ <property name="localSuffix" value="" />
+ <property name="localPrefix" value="" />
+ <property name="memberSuffix" value="" />
+ <property name="memberPrefix" value="" />
+ <property name="staticSuffix" value="" />
+ <property name="staticPrefix" value="" />
+ <property name="checkMembers" value="true" />
+ <property name="checkLocals" value="true" />
+ <property name="checkParameters" value="true" />
+ <property name="checkNativeMethodParameters" value="true" />
+ </properties>
+</rule>
+
Deprecated
+ +Since: PMD 0.7
+ +Priority: Medium (3)
+ +Avoid using ‘while’ statements without using braces to surround the code block. If the code +formatting or indentation is lost then it becomes difficult to separate the code being +controlled from the rest.
+ +This rule is deprecated and will be removed with PMD 7.0.0. The rule is replaced
+by the rule ControlStatementBraces
.
This rule is defined by the following XPath expression:
+//WhileStatement[not(Statement/Block)]
+
Example(s):
+ +while (true) // not recommended
+ x++;
+
+while (true) { // preferred approach
+ x++;
+}
+
Use this rule by referencing it:
+<rule ref="category/java/codestyle.xml/WhileLoopsMustUseBraces" />
+
Since: PMD 4.2
+ +Priority: High (1)
+ +If an abstract class does not provides any methods, it may be acting as a simple data container +that is not meant to be instantiated. In this case, it is probably better to use a private or +protected constructor in order to prevent instantiation than make the class misleadingly abstract.
+ +This rule is defined by the following XPath expression:
+//ClassOrInterfaceDeclaration
+ [@Abstract = true()]
+ [not(./ClassOrInterfaceBody/*/ConstructorDeclaration)]
+ [not(./ClassOrInterfaceBody/*/MethodDeclaration)]
+ [not(../Annotation/MarkerAnnotation/Name[pmd-java:typeIs('com.google.auto.value.AutoValue')])]
+
Example(s):
+ +public abstract class Example {
+ String field;
+ int otherField;
+}
+
Use this rule by referencing it:
+<rule ref="category/java/design.xml/AbstractClassWithoutAnyMethod" />
+
Since: PMD 4.2.6
+ +Priority: Medium (3)
+ +Avoid catching generic exceptions such as NullPointerException, RuntimeException, Exception in try-catch block
+ +This rule is defined by the following XPath expression:
+//CatchStatement/FormalParameter/Type/ReferenceType/ClassOrInterfaceType[
+ @Image='NullPointerException' or
+ @Image='Exception' or
+ @Image='RuntimeException']
+
Example(s):
+ +package com.igate.primitive;
+
+public class PrimitiveType {
+
+ public void downCastPrimitiveType() {
+ try {
+ System.out.println(" i [" + i + "]");
+ } catch(Exception e) {
+ e.printStackTrace();
+ } catch(RuntimeException e) {
+ e.printStackTrace();
+ } catch(NullPointerException e) {
+ e.printStackTrace();
+ }
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/design.xml/AvoidCatchingGenericException" />
+
Since: PMD 1.0
+ +Priority: Medium (3)
+ +Avoid creating deeply nested if-then statements since they are harder to read and error-prone to maintain.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.design.AvoidDeeplyNestedIfStmtsRule
+ +Example(s):
+ +public class Foo {
+ public void bar(int x, int y, int z) {
+ if (x>y) {
+ if (y>z) {
+ if (z==x) {
+ // !! too deep
+ }
+ }
+ }
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
problemDepth | +3 | +The if statement depth reporting threshold | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/design.xml/AvoidDeeplyNestedIfStmts" />
+
Use this rule and customize it:
+<rule ref="category/java/design.xml/AvoidDeeplyNestedIfStmts">
+ <properties>
+ <property name="problemDepth" value="3" />
+ </properties>
+</rule>
+
Since: PMD 3.8
+ +Priority: Medium (3)
+ +Catch blocks that merely rethrow a caught exception only add to code size and runtime complexity.
+ +This rule is defined by the following XPath expression:
+//CatchStatement[FormalParameter
+ /VariableDeclaratorId/@Name = Block/BlockStatement/Statement
+ /ThrowStatement/Expression/PrimaryExpression[count(PrimarySuffix)=0]/PrimaryPrefix/Name/@Image
+ and count(Block/BlockStatement/Statement) =1]
+
Example(s):
+ +public void bar() {
+ try {
+ // do something
+ } catch (SomeException se) {
+ throw se;
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/design.xml/AvoidRethrowingException" />
+
Since: PMD 4.2.5
+ +Priority: Medium (3)
+ +Catch blocks that merely rethrow a caught exception wrapped inside a new instance of the same type only add to +code size and runtime complexity.
+ +This rule is defined by the following XPath expression:
+//CatchStatement[
+ count(Block/BlockStatement/Statement) = 1
+ and
+ FormalParameter/Type/ReferenceType/ClassOrInterfaceType/@Image = Block/BlockStatement/Statement/ThrowStatement/Expression/PrimaryExpression/PrimaryPrefix/AllocationExpression/ClassOrInterfaceType/@Image
+ and
+ count(Block/BlockStatement/Statement/ThrowStatement/Expression/PrimaryExpression/PrimaryPrefix/AllocationExpression/Arguments/ArgumentList/Expression) = 1
+ and
+ FormalParameter/VariableDeclaratorId = Block/BlockStatement/Statement/ThrowStatement/Expression/PrimaryExpression/PrimaryPrefix/AllocationExpression/Arguments/ArgumentList/Expression/PrimaryExpression/PrimaryPrefix/Name
+ ]
+
Example(s):
+ +public void bar() {
+ try {
+ // do something
+ } catch (SomeException se) {
+ // harmless comment
+ throw new SomeException(se);
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/design.xml/AvoidThrowingNewInstanceOfSameException" />
+
Since: PMD 1.8
+ +Priority: High (1)
+ +Avoid throwing NullPointerExceptions manually. These are confusing because most people will assume that the +virtual machine threw it. To avoid a method being called with a null parameter, you may consider +using an IllegalArgumentException instead, making it clearly seen as a programmer-initiated exception. +However, there are better ways to handle this:
+ +++ +Effective Java, 3rd Edition, Item 72: Favor the use of standard exceptions
+ +Arguably, every erroneous method invocation boils down to an illegal argument or state, +but other exceptions are standardly used for certain kinds of illegal arguments and states. +If a caller passes null in some parameter for which null values are prohibited, convention dictates that +NullPointerException be thrown rather than IllegalArgumentException.
+
To implement that, you are encouraged to use java.util.Objects.requireNonNull()
+(introduced in Java 1.7). This method is designed primarily for doing parameter
+validation in methods and constructors with multiple parameters.
Your parameter validation could thus look like the following:
+public class Foo {
+ private String exampleValue;
+
+ void setExampleValue(String exampleValue) {
+ // check, throw and assignment in a single standard call
+ this.exampleValue = Objects.requireNonNull(exampleValue, "exampleValue must not be null!");
+ }
+ }
+
This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.design.AvoidThrowingNullPointerExceptionRule
+ +Example(s):
+ +public class Foo {
+ void bar() {
+ throw new NullPointerException();
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/design.xml/AvoidThrowingNullPointerException" />
+
Since: PMD 1.8
+ +Priority: High (1)
+ +Avoid throwing certain exception types. Rather than throw a raw RuntimeException, Throwable, +Exception, or Error, use a subclassed exception or error instead.
+ +This rule is defined by the following XPath expression:
+//ThrowStatement//AllocationExpression
+ /ClassOrInterfaceType[
+ pmd-java:typeIsExactly('java.lang.Throwable')
+or
+ pmd-java:typeIsExactly('java.lang.Exception')
+or
+ pmd-java:typeIsExactly('java.lang.Error')
+or
+ pmd-java:typeIsExactly('java.lang.RuntimeException')
+]
+
Example(s):
+ +public class Foo {
+ public void bar() throws Exception {
+ throw new Exception();
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/design.xml/AvoidThrowingRawExceptionTypes" />
+
Since: PMD 6.13.0
+ +Priority: Medium (3)
+ +A method or constructor should not explicitly declare unchecked exceptions in its
+throws
clause. Java doesn’t force the caller to handle an unchecked exception,
+so it’s unnecessary except for documentation. A better practice is to document the
+exceptional cases with a @throws
Javadoc tag, which allows being more descriptive.
This rule is defined by the following XPath expression:
+//MethodDeclaration/NameList/Name[pmd-java:typeIs("java.lang.RuntimeException")]
+|
+//ConstructorDeclaration/NameList/Name[pmd-java:typeIs("java.lang.RuntimeException")]
+
Example(s):
+ +public void foo() throws RuntimeException {
+}
+
Use this rule by referencing it:
+<rule ref="category/java/design.xml/AvoidUncheckedExceptionsInSignatures" />
+
Since: PMD 4.1
+ +Priority: High (1)
+ +A class with only private constructors should be final, unless the private constructor +is invoked by a inner class.
+ +This rule is defined by the following XPath expression:
+//TypeDeclaration[count(../TypeDeclaration) = 1]/ClassOrInterfaceDeclaration
+[@Final = false()]
+[ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/ConstructorDeclaration[@Private = true()]]
+[not(./ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/ConstructorDeclaration[(@Public = true()) or (@Protected = true()) or (@PackagePrivate = true())])]
+[not(.//ClassOrInterfaceDeclaration)]
+
Example(s):
+ +public class Foo { //Should be final
+ private Foo() { }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/design.xml/ClassWithOnlyPrivateConstructorsShouldBeFinal" />
+
Since: PMD 3.1
+ +Priority: Medium (3)
+ +Sometimes two consecutive ‘if’ statements can be consolidated by separating their conditions with a boolean short-circuit operator.
+ +This rule is defined by the following XPath expression:
+//IfStatement[@Else= false()]/Statement
+ /IfStatement[@Else= false()]
+ |
+//IfStatement[@Else= false()]/Statement
+ /Block[count(BlockStatement)=1]/BlockStatement
+ /Statement/IfStatement[@Else= false()]
+
Example(s):
+ +void bar() {
+ if (x) { // original implementation
+ if (y) {
+ // do stuff
+ }
+ }
+}
+
+void bar() {
+ if (x && y) { // optimized implementation
+ // do stuff
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/design.xml/CollapsibleIfStatements" />
+
Since: PMD 1.04
+ +Priority: Medium (3)
+ +This rule counts the number of unique attributes, local variables, and return types within an object. +A number higher than the specified threshold can indicate a high degree of coupling.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.design.CouplingBetweenObjectsRule
+ +Example(s):
+ +import com.Blah;
+import org.Bar;
+import org.Bardo;
+
+public class Foo {
+ private Blah var1;
+ private Bar var2;
+
+ //followed by many imports of unique objects
+ ObjectC doWork() {
+ Bardo var55;
+ ObjectA var44;
+ ObjectZ var93;
+ return something();
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
threshold | +20 | +Unique type reporting threshold | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/design.xml/CouplingBetweenObjects" />
+
Use this rule and customize it:
+<rule ref="category/java/design.xml/CouplingBetweenObjects">
+ <properties>
+ <property name="threshold" value="20" />
+ </properties>
+</rule>
+
Since: PMD 1.03
+ +Priority: Medium (3)
+ +The complexity of methods directly affects maintenance costs and readability. Concentrating too much decisional logic +in a single method makes its behaviour hard to read and change.
+ +Cyclomatic complexity assesses the complexity of a method by counting the number of decision points in a method,
+plus one for the method entry. Decision points are places where the control flow jumps to another place in the
+program. As such, they include all control flow statements, such as if
, while
, for
, and case
. For more
+details on the calculation, see the documentation of the Cyclo metric.
Generally, numbers ranging from 1-4 denote low complexity, 5-7 denote moderate complexity, 8-10 denote +high complexity, and 11+ is very high complexity. By default, this rule reports methods with a complexity >= 10. +Additionally, classes with many methods of moderate complexity get reported as well once the total of their +methods’ complexities reaches 80, even if none of the methods was directly reported.
+ +Reported methods should be broken down into several smaller methods. Reported classes should probably be broken down +into subcomponents.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.design.CyclomaticComplexityRule
+ +Example(s):
+ +class Foo {
+ void baseCyclo() { // Cyclo = 1
+ highCyclo();
+ }
+
+ void highCyclo() { // Cyclo = 10: reported!
+ int x = 0, y = 2;
+ boolean a = false, b = true;
+
+ if (a && (y == 1 ? b : true)) { // +3
+ if (y == x) { // +1
+ while (true) { // +1
+ if (x++ < 20) { // +1
+ break; // +1
+ }
+ }
+ } else if (y == t && !d) { // +2
+ x = a ? y : x; // +1
+ } else {
+ x = 2;
+ }
+ }
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
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 with the default properties by just referencing it:
+<rule ref="category/java/design.xml/CyclomaticComplexity" />
+
Use this rule and customize it:
+<rule ref="category/java/design.xml/CyclomaticComplexity">
+ <properties>
+ <property name="classReportLevel" value="80" />
+ <property name="methodReportLevel" value="10" />
+ <property name="cycloOptions" value="" />
+ </properties>
+</rule>
+
Since: PMD 6.0.0
+ +Priority: Medium (3)
+ +Data Classes are simple data holders, which reveal most of their state, and +without complex functionality. The lack of functionality may indicate that +their behaviour is defined elsewhere, which is a sign of poor data-behaviour +proximity. By directly exposing their internals, Data Classes break encapsulation, +and therefore reduce the system’s maintainability and understandability. Moreover, +classes tend to strongly rely on their data representation, which makes for a brittle +design.
+ +Refactoring a Data Class should focus on restoring a good data-behaviour proximity. In +most cases, that means moving the operations defined on the data back into the class. +In some other cases it may make sense to remove entirely the class and move the data +into the former client classes.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.design.DataClassRule
+ +Example(s):
+ +public class DataClass {
+
+ public int bar = 0;
+ public int na = 0;
+ private int bee = 0;
+
+ public void setBee(int n) {
+ bee = n;
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/design.xml/DataClass" />
+
Since: PMD 4.0
+ +Priority: Medium (3)
+ +Errors are system exceptions. Do not extend them.
+ +This rule is defined by the following XPath expression:
+//ClassOrInterfaceDeclaration/ExtendsList/ClassOrInterfaceType
+ [pmd-java:typeIs('java.lang.Error')]
+
Example(s):
+ +public class Foo extends Error { }
+
Use this rule by referencing it:
+<rule ref="category/java/design.xml/DoNotExtendJavaLangError" />
+
Since: PMD 1.8
+ +Priority: Medium (3)
+ +Using Exceptions as form of flow control is not recommended as they obscure true exceptions when debugging. +Either add the necessary validation or use an alternate control structure.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.design.ExceptionAsFlowControlRule
+ +Example(s):
+ +public void bar() {
+ try {
+ try {
+ } catch (Exception e) {
+ throw new WrapperException(e);
+ // this is essentially a GOTO to the WrapperException catch block
+ }
+ } catch (WrapperException e) {
+ // do some more stuff
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/design.xml/ExceptionAsFlowControl" />
+
Since: PMD 0.6
+ +Priority: Medium (3)
+ +Excessive class file lengths are usually indications that the class may be burdened with excessive +responsibilities that could be provided by external classes or functions. In breaking these methods +apart the code becomes more manageable and ripe for reuse.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.design.ExcessiveClassLengthRule
+ +Example(s):
+ +public class Foo {
+ public void bar1() {
+ // 1000 lines of code
+ }
+ public void bar2() {
+ // 1000 lines of code
+ }
+ public void bar3() {
+ // 1000 lines of code
+ }
+
+ public void barN() {
+ // 1000 lines of code
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
topscore | ++ | Deprecated Top score value | +no | +
minimum | +1000.0 | +Minimum reporting threshold | +no | +
sigma | ++ | Deprecated Sigma value | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/design.xml/ExcessiveClassLength" />
+
Use this rule and customize it:
+<rule ref="category/java/design.xml/ExcessiveClassLength">
+ <properties>
+ <property name="minimum" value="1000.0" />
+ </properties>
+</rule>
+
Since: PMD 1.04
+ +Priority: Medium (3)
+ +A high number of imports can indicate a high degree of coupling within an object. This rule +counts the number of unique imports and reports a violation if the count is above the +user-specified threshold.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.design.ExcessiveImportsRule
+ +Example(s):
+ +import blah.blah.Baz;
+import blah.blah.Bif;
+// 28 others from the same package elided
+public class Foo {
+ public void doWork() {}
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
topscore | ++ | Deprecated Top score value | +no | +
minimum | +30.0 | +Minimum reporting threshold | +no | +
sigma | ++ | Deprecated Sigma value | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/design.xml/ExcessiveImports" />
+
Use this rule and customize it:
+<rule ref="category/java/design.xml/ExcessiveImports">
+ <properties>
+ <property name="minimum" value="30.0" />
+ </properties>
+</rule>
+
Since: PMD 0.6
+ +Priority: Medium (3)
+ +When methods are excessively long this usually indicates that the method is doing more than its +name/signature might suggest. They also become challenging for others to digest since excessive +scrolling causes readers to lose focus. +Try to reduce the method length by creating helper methods and removing any copy/pasted code.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.design.ExcessiveMethodLengthRule
+ +Example(s):
+ +public void doSomething() {
+ System.out.println("Hello world!");
+ System.out.println("Hello world!");
+ // 98 copies omitted for brevity.
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
topscore | ++ | Deprecated Top score value | +no | +
minimum | +100.0 | +Minimum reporting threshold | +no | +
sigma | ++ | Deprecated Sigma value | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/design.xml/ExcessiveMethodLength" />
+
Use this rule and customize it:
+<rule ref="category/java/design.xml/ExcessiveMethodLength">
+ <properties>
+ <property name="minimum" value="100.0" />
+ </properties>
+</rule>
+
Since: PMD 0.9
+ +Priority: Medium (3)
+ +Methods with numerous parameters are a challenge to maintain, especially if most of them share the +same datatype. These situations usually denote the need for new objects to wrap the numerous parameters.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.design.ExcessiveParameterListRule
+ +Example(s):
+ +public void addPerson( // too many arguments liable to be mixed up
+ int birthYear, int birthMonth, int birthDate, int height, int weight, int ssn) {
+
+ . . . .
+}
+
+public void addPerson( // preferred approach
+ Date birthdate, BodyMeasurements measurements, int ssn) {
+
+ . . . .
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
topscore | ++ | Deprecated Top score value | +no | +
minimum | +10.0 | +Minimum reporting threshold | +no | +
sigma | ++ | Deprecated Sigma value | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/design.xml/ExcessiveParameterList" />
+
Use this rule and customize it:
+<rule ref="category/java/design.xml/ExcessiveParameterList">
+ <properties>
+ <property name="minimum" value="10.0" />
+ </properties>
+</rule>
+
Since: PMD 1.04
+ +Priority: Medium (3)
+ +Classes with large numbers of public methods and attributes require disproportionate testing efforts +since combinational side effects grow rapidly and increase risk. Refactoring these classes into +smaller ones not only increases testability and reliability but also allows new variations to be +developed easily.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.design.ExcessivePublicCountRule
+ +Example(s):
+ +public class Foo {
+ public String value;
+ public Bar something;
+ public Variable var;
+ // [... more more public attributes ...]
+
+ public void doWork() {}
+ public void doMoreWork() {}
+ public void doWorkAgain() {}
+ // [... more more public methods ...]
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
topscore | ++ | Deprecated Top score value | +no | +
minimum | +45.0 | +Minimum reporting threshold | +no | +
sigma | ++ | Deprecated Sigma value | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/design.xml/ExcessivePublicCount" />
+
Use this rule and customize it:
+<rule ref="category/java/design.xml/ExcessivePublicCount">
+ <properties>
+ <property name="minimum" value="45.0" />
+ </properties>
+</rule>
+
Since: PMD 1.1
+ +Priority: Medium (3)
+ +If a final field is assigned to a compile-time constant, it could be made static, thus saving overhead +in each object at runtime.
+ +This rule is defined by the following XPath expression:
+//FieldDeclaration
+ [@Final= true() and @Static= false()]
+ [not(preceding-sibling::Annotation/MarkerAnnotation/Name[@Image="Builder.Default"]
+ and //ImportDeclaration/Name[@Image="lombok.Builder"])]
+/VariableDeclarator
+ [VariableInitializer/Expression/PrimaryExpression[not(PrimarySuffix)]/PrimaryPrefix/Literal]
+/VariableDeclaratorId
+
Example(s):
+ +public class Foo {
+ public final int BAR = 42; // this could be static and save some space
+}
+
Use this rule by referencing it:
+<rule ref="category/java/design.xml/FinalFieldCouldBeStatic" />
+
Since: PMD 5.0
+ +Priority: Medium (3)
+ +The God Class rule detects the God Class design flaw using metrics. God classes do too many things, +are very big and overly complex. They should be split apart to be more object-oriented. +The rule uses the detection strategy described in "Object-Oriented Metrics in Practice". +The violations are reported against the entire class.
+ +See also the references:
+ +Michele Lanza and Radu Marinescu. Object-Oriented Metrics in Practice: +Using Software Metrics to Characterize, Evaluate, and Improve the Design +of Object-Oriented Systems. Springer, Berlin, 1 edition, October 2006. Page 80.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.design.GodClassRule
+ +Use this rule by referencing it:
+<rule ref="category/java/design.xml/GodClass" />
+
Since: PMD 2.0
+ +Priority: Medium (3)
+ +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. +Note that this rule does not enforce referenced object to be immutable itself. A class can still be mutable, even +if all its member fields are declared final. This is referred to as shallow immutability. For more information on +mutability, see Effective Java, 3rd Edition, Item 17: Minimize mutability.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.design.ImmutableFieldRule
+ +Example(s):
+ +public class Foo {
+ private int x; // could be final
+ public Foo() {
+ x = 7;
+ }
+ public void foo() {
+ int a = x + 2;
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
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 ‘|’. | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/design.xml/ImmutableField" />
+
Use this rule and customize it:
+<rule ref="category/java/design.xml/ImmutableField">
+ <properties>
+ <property name="ignoredAnnotations" value="lombok.Setter|lombok.Getter|lombok.Builder|lombok.Data|lombok.RequiredArgsConstructor|lombok.AllArgsConstructor|lombok.Value|lombok.NoArgsConstructor" />
+ </properties>
+</rule>
+
Since: PMD 5.0
+ +Priority: Medium (3)
+ +The Law of Demeter is a simple rule, that says "only talk to friends". It helps to reduce coupling between classes +or objects.
+ +See also the references:
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.design.LawOfDemeterRule
+ +Example(s):
+ +public class Foo {
+ /**
+ * This example will result in two violations.
+ */
+ public void example(Bar b) {
+ // this method call is ok, as b is a parameter of "example"
+ C c = b.getC();
+
+ // this method call is a violation, as we are using c, which we got from B.
+ // We should ask b directly instead, e.g. "b.doItOnC();"
+ c.doIt();
+
+ // this is also a violation, just expressed differently as a method chain without temporary variables.
+ b.getC().doIt();
+
+ // a constructor call, not a method call.
+ D d = new D();
+ // this method call is ok, because we have create the new instance of D locally.
+ d.doSomethingElse();
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/design.xml/LawOfDemeter" />
+
Since: PMD 5.0
+ +Priority: Medium (3)
+ +Use opposite operator instead of negating the whole expression with a logic complement operator.
+ +This rule is defined by the following XPath expression:
+//UnaryExpressionNotPlusMinus[@Image='!']/PrimaryExpression/PrimaryPrefix/Expression[EqualityExpression or RelationalExpression]
+
Example(s):
+ +public boolean bar(int a, int b) {
+
+ if (!(a == b)) { // use !=
+ return false;
+ }
+
+ if (!(a < b)) { // use >=
+ return false;
+ }
+
+ return true;
+}
+
Use this rule by referencing it:
+<rule ref="category/java/design.xml/LogicInversion" />
+
Since: PMD 5.0
+ +Priority: Medium (3)
+ +Avoid using classes from the configured package hierarchy outside of the package hierarchy, +except when using one of the configured allowed classes.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.design.LoosePackageCouplingRule
+ +Example(s):
+ +package some.package;
+
+import some.other.package.subpackage.subsubpackage.DontUseThisClass;
+
+public class Bar {
+ DontUseThisClass boo = new DontUseThisClass();
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
packages | ++ | Restricted packages | +yes. Delimiter is ‘,’. | +
classes | ++ | Allowed classes | +yes. Delimiter is ‘,’. | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/design.xml/LoosePackageCoupling" />
+
Use this rule and customize it:
+<rule ref="category/java/design.xml/LoosePackageCoupling">
+ <properties>
+ <property name="packages" value="" />
+ <property name="classes" value="" />
+ </properties>
+</rule>
+
Deprecated
+ +Since: PMD 5.1.2
+ +Priority: Medium (3)
+ +Complexity directly affects maintenance costs is determined by the number of decision points in a method +plus one for the method entry. The decision points include ‘if’, ‘while’, ‘for’, and ‘case labels’ calls. +Generally, numbers ranging from 1-4 denote low complexity, 5-7 denote moderate complexity, 8-10 denote +high complexity, and 11+ is very high complexity. Modified complexity treats switch statements as a single +decision point.
+ +This rule is deprecated and will be removed with PMD 7.0.0. The rule is replaced
+by the rule CyclomaticComplexity
.
This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.design.ModifiedCyclomaticComplexityRule
+ +Example(s):
+ +public class Foo { // This has a Cyclomatic Complexity = 9
+1 public void example() {
+2 if (a == b) {
+3 if (a1 == b1) {
+ fiddle();
+4 } else if a2 == b2) {
+ fiddle();
+ } else {
+ fiddle();
+ }
+5 } else if (c == d) {
+6 while (c == d) {
+ fiddle();
+ }
+7 } else if (e == f) {
+8 for (int n = 0; n < h; n++) {
+ fiddle();
+ }
+ } else{
+9 switch (z) {
+ case 1:
+ fiddle();
+ break;
+ case 2:
+ fiddle();
+ break;
+ case 3:
+ fiddle();
+ break;
+ default:
+ fiddle();
+ break;
+ }
+ }
+ }
+}
+
This rule has the following properties:
+ +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 | +
reportLevel | +10 | +Cyclomatic Complexity reporting threshold | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/design.xml/ModifiedCyclomaticComplexity" />
+
Use this rule and customize it:
+<rule ref="category/java/design.xml/ModifiedCyclomaticComplexity">
+ <properties>
+ <property name="showMethodsComplexity" value="true" />
+ <property name="showClassesComplexity" value="true" />
+ <property name="reportLevel" value="10" />
+ </properties>
+</rule>
+
Deprecated
+ +Since: PMD 3.9
+ +Priority: Medium (3)
+ +This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of lines +of code for a given constructor. NCSS ignores comments, and counts actual statements. Using this algorithm, +lines of code that are split are counted as one.
+ +This rule is deprecated and will be removed with PMD 7.0.0. The rule is replaced
+by the rule NcssCount
.
This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.design.NcssConstructorCountRule
+ +Example(s):
+ +public class Foo extends Bar {
+ public Foo() {
+ super();
+
+
+
+
+
+ //this constructor only has 1 NCSS lines
+ super.foo();
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
topscore | ++ | Deprecated Top score value | +no | +
minimum | +100.0 | +Minimum reporting threshold | +no | +
sigma | ++ | Deprecated Sigma value | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/design.xml/NcssConstructorCount" />
+
Use this rule and customize it:
+<rule ref="category/java/design.xml/NcssConstructorCount">
+ <properties>
+ <property name="minimum" value="100.0" />
+ </properties>
+</rule>
+
Since: PMD 6.0.0
+ +Priority: Medium (3)
+ +This rule uses the NCSS (Non-Commenting Source Statements) metric to determine the number of lines +of code in a class, method or constructor. NCSS ignores comments, blank lines, and only counts actual +statements. For more details on the calculation, see the documentation of +the NCSS metric.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.design.NcssCountRule
+ +Example(s):
+ +import java.util.Collections; // +0
+import java.io.IOException; // +0
+
+class Foo { // +1, total Ncss = 12
+
+ public void bigMethod() // +1
+ throws IOException {
+ int x = 0, y = 2; // +1
+ boolean a = false, b = true; // +1
+
+ if (a || b) { // +1
+ try { // +1
+ do { // +1
+ x += 2; // +1
+ } while (x < 12);
+
+ System.exit(0); // +1
+ } catch (IOException ioe) { // +1
+ throw new PatheticFailException(ioe); // +1
+ }
+ } else {
+ assert false; // +1
+ }
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
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 with the default properties by just referencing it:
+<rule ref="category/java/design.xml/NcssCount" />
+
Use this rule and customize it:
+<rule ref="category/java/design.xml/NcssCount">
+ <properties>
+ <property name="methodReportLevel" value="60" />
+ <property name="classReportLevel" value="1500" />
+ <property name="ncssOptions" value="" />
+ </properties>
+</rule>
+
Deprecated
+ +Since: PMD 3.9
+ +Priority: Medium (3)
+ +This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of lines +of code for a given method. NCSS ignores comments, and counts actual statements. Using this algorithm, +lines of code that are split are counted as one.
+ +This rule is deprecated and will be removed with PMD 7.0.0. The rule is replaced
+by the rule NcssCount
.
This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.design.NcssMethodCountRule
+ +Example(s):
+ +public class Foo extends Bar {
+ public int methd() {
+ super.methd();
+
+
+
+
+
+
+ //this method only has 1 NCSS lines
+ return 1;
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
topscore | ++ | Deprecated Top score value | +no | +
minimum | +100.0 | +Minimum reporting threshold | +no | +
sigma | ++ | Deprecated Sigma value | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/design.xml/NcssMethodCount" />
+
Use this rule and customize it:
+<rule ref="category/java/design.xml/NcssMethodCount">
+ <properties>
+ <property name="minimum" value="100.0" />
+ </properties>
+</rule>
+
Deprecated
+ +Since: PMD 3.9
+ +Priority: Medium (3)
+ +This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of lines +of code for a given type. NCSS ignores comments, and counts actual statements. Using this algorithm, +lines of code that are split are counted as one.
+ +This rule is deprecated and will be removed with PMD 7.0.0. The rule is replaced
+by the rule NcssCount
.
This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.design.NcssTypeCountRule
+ +Example(s):
+ +public class Foo extends Bar {
+ public Foo() {
+ //this class only has 6 NCSS lines
+ super();
+
+
+
+
+
+ super.foo();
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
topscore | ++ | Deprecated Top score value | +no | +
minimum | +1500.0 | +Minimum reporting threshold | +no | +
sigma | ++ | Deprecated Sigma value | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/design.xml/NcssTypeCount" />
+
Use this rule and customize it:
+<rule ref="category/java/design.xml/NcssTypeCount">
+ <properties>
+ <property name="minimum" value="1500.0" />
+ </properties>
+</rule>
+
Since: PMD 3.9
+ +Priority: Medium (3)
+ +The NPath complexity of a method is the number of acyclic execution paths through that method. +While cyclomatic complexity counts the number of decision points in a method, NPath counts the number of +full paths from the beginning to the end of the block of the method. That metric grows exponentially, as +it multiplies the complexity of statements in the same block. For more details on the calculation, see the +documentation of the NPath metric.
+ +A threshold of 200 is generally considered the point where measures should be taken to reduce +complexity and increase readability.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.design.NPathComplexityRule
+ +Example(s):
+ +public class Foo {
+ public static void bar() { // Ncss = 252: reported!
+ boolean a, b = true;
+ try { // 2 * 2 + 2 = 6
+ if (true) { // 2
+ List buz = new ArrayList();
+ }
+
+ for(int i = 0; i < 19; i++) { // * 2
+ List buz = new ArrayList();
+ }
+ } catch(Exception e) {
+ if (true) { // 2
+ e.printStackTrace();
+ }
+ }
+
+ while (j++ < 20) { // * 2
+ List buz = new ArrayList();
+ }
+
+ switch(j) { // * 7
+ case 1:
+ case 2: break;
+ case 3: j = 5; break;
+ case 4: if (b && a) { bar(); } break;
+ default: break;
+ }
+
+ do { // * 3
+ List buz = new ArrayList();
+ } while (a && j++ < 30);
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
reportLevel | +200 | +N-Path Complexity reporting threshold | +no | +
minimum | +200.0 | +Deprecated Minimum reporting threshold | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/design.xml/NPathComplexity" />
+
Use this rule and customize it:
+<rule ref="category/java/design.xml/NPathComplexity">
+ <properties>
+ <property name="reportLevel" value="200" />
+ </properties>
+</rule>
+
Since: PMD 1.2
+ +Priority: Medium (3)
+ +A method/constructor shouldn’t explicitly throw the generic java.lang.Exception, since it +is unclear which exceptions that can be thrown from the methods. It might be +difficult to document and understand such vague interfaces. Use either a class +derived from RuntimeException or a checked exception.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.design.SignatureDeclareThrowsExceptionRule
+ +Example(s):
+ +public void foo() throws Exception {
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
IgnoreJUnitCompletely | +false | +Allow all methods in a JUnit testcase to throw Exceptions | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/design.xml/SignatureDeclareThrowsException" />
+
Use this rule and customize it:
+<rule ref="category/java/design.xml/SignatureDeclareThrowsException">
+ <properties>
+ <property name="IgnoreJUnitCompletely" value="false" />
+ </properties>
+</rule>
+
Since: PMD 5.4.0
+ +Priority: Medium (3)
+ +Look for ternary operators with the form condition ? literalBoolean : foo
+or condition ? foo : literalBoolean
.
These expressions can be simplified respectively to
+condition || foo
when the literalBoolean is true
+!condition && foo
when the literalBoolean is false
+or
+!condition || foo
when the literalBoolean is true
+condition && foo
when the literalBoolean is false
This rule is defined by the following XPath expression:
+//ConditionalExpression[not(PrimaryExpression/*/Literal) and (Expression/PrimaryExpression/*/Literal/BooleanLiteral)]
+|
+//ConditionalExpression[not(Expression/PrimaryExpression/*/Literal) and (PrimaryExpression/*/Literal/BooleanLiteral)]
+
Example(s):
+ +public class Foo {
+ public boolean test() {
+ return condition ? true : something(); // can be as simple as return condition || something();
+ }
+
+ public void test2() {
+ final boolean value = condition ? false : something(); // can be as simple as value = !condition && something();
+ }
+
+ public boolean test3() {
+ return condition ? something() : true; // can be as simple as return !condition || something();
+ }
+
+ public void test4() {
+ final boolean otherValue = condition ? something() : false; // can be as simple as condition && something();
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/design.xml/SimplifiedTernary" />
+
Since: PMD 3.6
+ +Priority: Medium (3)
+ +Avoid negation in an assertTrue or assertFalse test.
+ +For example, rephrase:
+ +assertTrue(!expr);
+
as:
+ +assertFalse(expr);
+
This rule is defined by the following XPath expression:
+//ClassOrInterfaceDeclaration[
+ pmd-java:typeIs('junit.framework.TestCase')
+ or .//MarkerAnnotation/Name[
+ pmd-java:typeIs('org.junit.Test')
+ or pmd-java:typeIs('org.junit.jupiter.api.Test')
+ or pmd-java:typeIs('org.junit.jupiter.api.RepeatedTest')
+ or pmd-java:typeIs('org.junit.jupiter.api.TestFactory')
+ or pmd-java:typeIs('org.junit.jupiter.api.TestTemplate')
+ or pmd-java:typeIs('org.junit.jupiter.params.ParameterizedTest')
+ ]
+ ]
+//StatementExpression
+[
+ .//Name[@Image='assertTrue' or @Image='assertFalse']
+ and
+ PrimaryExpression/PrimarySuffix/Arguments/ArgumentList/Expression/UnaryExpressionNotPlusMinus[@Image='!']
+ /PrimaryExpression/PrimaryPrefix
+]
+
Example(s):
+ +public class SimpleTest extends TestCase {
+ public void testX() {
+ assertTrue("not empty", !r.isEmpty()); // replace with assertFalse("not empty", r.isEmpty())
+ assertFalse(!r.isEmpty()); // replace with assertTrue(r.isEmpty())
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/design.xml/SimplifyBooleanAssertion" />
+
Since: PMD 1.05
+ +Priority: Medium (3)
+ +Avoid unnecessary comparisons in boolean expressions, they serve no purpose and impacts readability.
+ +This rule is defined by the following XPath expression:
+//EqualityExpression/PrimaryExpression
+ /PrimaryPrefix/Literal/BooleanLiteral
+
Example(s):
+ +public class Bar {
+ // can be simplified to
+ // bar = isFoo();
+ private boolean bar = (isFoo() == true);
+
+ public isFoo() { return false;}
+}
+
Use this rule by referencing it:
+<rule ref="category/java/design.xml/SimplifyBooleanExpressions" />
+
Since: PMD 0.9
+ +Priority: Medium (3)
+ +Avoid unnecessary if-then-else statements when returning a boolean. The result of +the conditional test can be returned instead.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.design.SimplifyBooleanReturnsRule
+ +Example(s):
+ +public boolean isBarEqualTo(int x) {
+ if (bar == x) { // this bit of code...
+ return true;
+ } else {
+ return false;
+ }
+}
+
+public boolean isBarEqualTo(int x) {
+ return bar == x; // can be replaced with this
+}
+
Use this rule by referencing it:
+<rule ref="category/java/design.xml/SimplifyBooleanReturns" />
+
Since: PMD 3.1
+ +Priority: Medium (3)
+ +No need to check for null before an instanceof; the instanceof keyword returns false when given a null argument.
+ +This rule is defined by the following XPath expression:
+//Expression
+ [ConditionalOrExpression
+ [EqualityExpression[@Image='==']
+ //NullLiteral
+ and
+ UnaryExpressionNotPlusMinus
+ [@Image='!']//InstanceOfExpression[PrimaryExpression
+ //Name/@Image = ancestor::ConditionalOrExpression/EqualityExpression
+ /PrimaryExpression/PrimaryPrefix/Name/@Image]
+ and
+ (count(UnaryExpressionNotPlusMinus) + 1 = count(*))
+ ]
+or
+ConditionalAndExpression
+ [EqualityExpression[@Image='!=']//NullLiteral
+ and
+InstanceOfExpression
+ [PrimaryExpression[not(PrimarySuffix[@ArrayDereference= true()])]
+ //Name[not(contains(@Image,'.'))]/@Image = ancestor::ConditionalAndExpression
+ /EqualityExpression/PrimaryExpression/PrimaryPrefix/Name/@Image]
+ and
+(count(InstanceOfExpression) + 1 = count(*))
+ ]
+]
+
Example(s):
+ +class Foo {
+ void bar(Object x) {
+ if (x != null && x instanceof Bar) {
+ // just drop the "x != null" check
+ }
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/design.xml/SimplifyConditional" />
+
Since: PMD 3.1
+ +Priority: Medium (3)
+ +Fields whose scopes are limited to just single methods do not rely on the containing +object to provide them to other methods. They may be better implemented as local variables +within those methods.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.design.SingularFieldRule
+ +Example(s):
+ +public class Foo {
+ private int x; // no reason to exist at the Foo instance level
+ public void foo(int y) {
+ x = y + 5;
+ return x;
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
ignoredAnnotations | +lombok.Setter | lombok.Getter | lombok.Builder | lombok.Data | lombok.RequiredArgsConstructor | lombok.AllArgsConstructor | lombok.Value | lombok.NoArgsConstructor | lombok.experimental.Delegate | lombok.EqualsAndHashCode | +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 with the default properties by just referencing it:
+<rule ref="category/java/design.xml/SingularField" />
+
Use this rule and customize it:
+<rule ref="category/java/design.xml/SingularField">
+ <properties>
+ <property name="ignoredAnnotations" value="lombok.Setter|lombok.Getter|lombok.Builder|lombok.Data|lombok.RequiredArgsConstructor|lombok.AllArgsConstructor|lombok.Value|lombok.NoArgsConstructor|lombok.experimental.Delegate|lombok.EqualsAndHashCode" />
+ <property name="checkInnerClasses" value="false" />
+ <property name="disallowNotAssignment" value="false" />
+ </properties>
+</rule>
+
Deprecated
+ +Since: PMD 5.1.2
+ +Priority: Medium (3)
+ +Complexity directly affects maintenance costs is determined by the number of decision points in a method +plus one for the method entry. The decision points include ‘if’, ‘while’, ‘for’, and ‘case labels’ calls. +Generally, numbers ranging from 1-4 denote low complexity, 5-7 denote moderate complexity, 8-10 denote +high complexity, and 11+ is very high complexity.
+ +This rule is deprecated and will be removed with PMD 7.0.0. The rule is replaced
+by the rule CyclomaticComplexity
.
This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.design.StdCyclomaticComplexityRule
+ +Example(s):
+ +public class Foo { // This has a Cyclomatic Complexity = 12
+1 public void example() {
+2 if (a == b || (c == d && e == f)) { // Only one
+3 if (a1 == b1) {
+ fiddle();
+4 } else if a2 == b2) {
+ fiddle();
+ } else {
+ fiddle();
+ }
+5 } else if (c == d) {
+6 while (c == d) {
+ fiddle();
+ }
+7 } else if (e == f) {
+8 for (int n = 0; n < h; n++) {
+ fiddle();
+ }
+ } else{
+ switch (z) {
+9 case 1:
+ fiddle();
+ break;
+10 case 2:
+ fiddle();
+ break;
+11 case 3:
+ fiddle();
+ break;
+12 default:
+ fiddle();
+ break;
+ }
+ }
+ }
+}
+
This rule has the following properties:
+ +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 | +
reportLevel | +10 | +Cyclomatic Complexity reporting threshold | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/design.xml/StdCyclomaticComplexity" />
+
Use this rule and customize it:
+<rule ref="category/java/design.xml/StdCyclomaticComplexity">
+ <properties>
+ <property name="showMethodsComplexity" value="true" />
+ <property name="showClassesComplexity" value="true" />
+ <property name="reportLevel" value="10" />
+ </properties>
+</rule>
+
Since: PMD 1.02
+ +Priority: Medium (3)
+ +A high ratio of statements to labels in a switch statement implies that the switch statement +is overloaded. Consider moving the statements into new methods or creating subclasses based +on the switch variable.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.design.SwitchDensityRule
+ +Example(s):
+ +public class Foo {
+ public void bar(int x) {
+ switch (x) {
+ case 1: {
+ // lots of statements
+ break;
+ } case 2: {
+ // lots of statements
+ break;
+ }
+ }
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
topscore | ++ | Deprecated Top score value | +no | +
minimum | +10.0 | +Minimum reporting threshold | +no | +
sigma | ++ | Deprecated Sigma value | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/design.xml/SwitchDensity" />
+
Use this rule and customize it:
+<rule ref="category/java/design.xml/SwitchDensity">
+ <properties>
+ <property name="minimum" value="10.0" />
+ </properties>
+</rule>
+
Since: PMD 3.0
+ +Priority: Medium (3)
+ +Classes that have too many fields can become unwieldy and could be redesigned to have fewer fields, +possibly through grouping related fields in new objects. For example, a class with individual +city/state/zip fields could park them within a single Address field.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.design.TooManyFieldsRule
+ +Example(s):
+ +public class Person { // too many separate fields
+ int birthYear;
+ int birthMonth;
+ int birthDate;
+ float height;
+ float weight;
+}
+
+public class Person { // this is more manageable
+ Date birthDate;
+ BodyMeasurements measurements;
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
maxfields | +15 | +Max allowable fields | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/design.xml/TooManyFields" />
+
Use this rule and customize it:
+<rule ref="category/java/design.xml/TooManyFields">
+ <properties>
+ <property name="maxfields" value="15" />
+ </properties>
+</rule>
+
Since: PMD 4.2
+ +Priority: Medium (3)
+ +A class with too many methods is probably a good suspect for refactoring, in order to reduce its +complexity and find a way to have more fine grained objects.
+ +This rule is defined by the following XPath expression:
+//ClassOrInterfaceDeclaration/ClassOrInterfaceBody
+ [
+ count(./ClassOrInterfaceBodyDeclaration/MethodDeclaration[
+ not (
+ starts-with(@Name,'get')
+ or
+ starts-with(@Name,'set')
+ or
+ starts-with(@Name,'is')
+ )
+ ]) > $maxmethods
+ ]
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
maxmethods | +10 | +The method count reporting threshold | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/design.xml/TooManyMethods" />
+
Use this rule and customize it:
+<rule ref="category/java/design.xml/TooManyMethods">
+ <properties>
+ <property name="maxmethods" value="10" />
+ </properties>
+</rule>
+
Since: PMD 3.3
+ +Priority: Medium (3)
+ +The overriding method merely calls the same method defined in a superclass.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.design.UselessOverridingMethodRule
+ +Example(s):
+ +public void foo(String bar) {
+ super.foo(bar); // why bother overriding?
+}
+
+public String foo() {
+ return super.foo(); // why bother overriding?
+}
+
+@Id
+public Long getId() {
+ return super.getId(); // OK if 'ignoreAnnotations' is false, which is the default behavior
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
ignoreAnnotations | +false | +Ignore annotations | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/design.xml/UselessOverridingMethod" />
+
Use this rule and customize it:
+<rule ref="category/java/design.xml/UselessOverridingMethod">
+ <properties>
+ <property name="ignoreAnnotations" value="false" />
+ </properties>
+</rule>
+
Since: PMD 4.2.6
+ +Priority: Medium (3)
+ +When you write a public method, you should be thinking in terms of an API. If your method is public, it means other class +will use it, therefore, you want (or need) to offer a comprehensive and evolutive API. If you pass a lot of information +as a simple series of Strings, you may think of using an Object to represent all those information. You’ll get a simpler +API (such as doWork(Workload workload), rather than a tedious series of Strings) and more importantly, if you need at some +point to pass extra data, you’ll be able to do so by simply modifying or extending Workload without any modification to +your API.
+ +This rule is defined by the following XPath expression:
+//MethodDeclaration[@Public=true()]/MethodDeclarator/FormalParameters[
+ count(FormalParameter/Type/ReferenceType/ClassOrInterfaceType[@Image = 'String' and @Array=false()]) > 3
+]
+
Example(s):
+ +public class MyClass {
+ public void connect(String username,
+ String pssd,
+ String databaseName,
+ String databaseAdress)
+ // Instead of those parameters object
+ // would ensure a cleaner API and permit
+ // to add extra data transparently (no code change):
+ // void connect(UserData data);
+ {
+
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/design.xml/UseObjectForClearerAPI" />
+
Since: PMD 0.3
+ +Priority: Medium (3)
+ +For classes that only have static methods, consider making them utility classes. +Note that this doesn’t apply to abstract classes, since their subclasses may +well include non-static methods. Also, if you want this class to be a utility class, +remember to add a private constructor to prevent instantiation. +(Note, that this use was known before PMD 5.1.0 as UseSingleton).
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.design.UseUtilityClassRule
+ +Example(s):
+ +public class MaybeAUtility {
+ public static void foo() {}
+ public static void bar() {}
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
ignoredAnnotations | +lombok.experimental.UtilityClass | +Fully qualified names of the annotation types that should be ignored by this rule | +yes. Delimiter is ‘|’. | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/design.xml/UseUtilityClass" />
+
Use this rule and customize it:
+<rule ref="category/java/design.xml/UseUtilityClass">
+ <properties>
+ <property name="ignoredAnnotations" value="lombok.experimental.UtilityClass" />
+ </properties>
+</rule>
+
Since: PMD 5.0
+ +Priority: Medium (3)
+ +A rule for the politically correct… we don’t want to offend anyone.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.documentation.CommentContentRule
+ +Example(s):
+ +//OMG, this is horrible, Bob is an idiot !!!
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
caseSensitive | +false | +Case sensitive | +no | +
disallowedTerms | +idiot | jerk | +Illegal terms or phrases | +yes. Delimiter is ‘|’. | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/documentation.xml/CommentContent" />
+
Use this rule and customize it:
+<rule ref="category/java/documentation.xml/CommentContent">
+ <properties>
+ <property name="caseSensitive" value="false" />
+ <property name="disallowedTerms" value="idiot|jerk" />
+ </properties>
+</rule>
+
Since: PMD 5.1
+ +Priority: Medium (3)
+ +Denotes whether javadoc (formal) comments are required (or unwanted) for specific language elements.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.documentation.CommentRequiredRule
+ +Example(s):
+ +/**
+*
+*
+* @author Jon Doe
+*/
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
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 | +
classCommentRequirement | +Required | +Class comments. Possible values: [Required, Ignored, Unwanted] | +no | +
headerCommentRequirement | +Required | +Deprecated Header comments. Please use the property "classCommentRequired" instead.. 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 | +
serialPersistentFieldsCommentRequired | +Ignored | +Serial persistent fields comments. Possible values: [Required, Ignored, Unwanted] | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/documentation.xml/CommentRequired" />
+
Use this rule and customize it:
+<rule ref="category/java/documentation.xml/CommentRequired">
+ <properties>
+ <property name="methodWithOverrideCommentRequirement" value="Ignored" />
+ <property name="accessorCommentRequirement" value="Ignored" />
+ <property name="classCommentRequirement" value="Required" />
+ <property name="fieldCommentRequirement" value="Required" />
+ <property name="publicMethodCommentRequirement" value="Required" />
+ <property name="protectedMethodCommentRequirement" value="Required" />
+ <property name="enumCommentRequirement" value="Required" />
+ <property name="serialVersionUIDCommentRequired" value="Ignored" />
+ <property name="serialPersistentFieldsCommentRequired" value="Ignored" />
+ </properties>
+</rule>
+
Since: PMD 5.0
+ +Priority: Medium (3)
+ +Determines whether the dimensions of non-header comments found are within the specified limits.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.documentation.CommentSizeRule
+ +Example(s):
+ +/**
+*
+* too many lines!
+*
+*
+*
+*
+*
+*
+*
+*
+*
+*
+*
+*
+*/
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
maxLines | +6 | +Maximum lines | +no | +
maxLineLength | +80 | +Maximum line length | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/documentation.xml/CommentSize" />
+
Use this rule and customize it:
+<rule ref="category/java/documentation.xml/CommentSize">
+ <properties>
+ <property name="maxLines" value="6" />
+ <property name="maxLineLength" value="80" />
+ </properties>
+</rule>
+
Since: PMD 3.4
+ +Priority: Medium (3)
+ +Uncommented Empty Constructor finds instances where a constructor does not +contain statements, but there is no comment. By explicitly commenting empty +constructors it is easier to distinguish between intentional (commented) +and unintentional empty constructors.
+ +This rule is defined by the following XPath expression:
+//ConstructorDeclaration[@Private= false()]
+ [@containsComment = false()]
+ [not(BlockStatement)]
+ [$ignoreExplicitConstructorInvocation = true() or not(ExplicitConstructorInvocation)]
+ [not(../Annotation/MarkerAnnotation/Name[pmd-java:typeIs('javax.inject.Inject')])]
+
Example(s):
+ +public Foo() {
+ // This constructor is intentionally empty. Nothing special is needed here.
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
ignoreExplicitConstructorInvocation | +false | +Ignore explicit constructor invocation when deciding whether constructor is empty or not | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/documentation.xml/UncommentedEmptyConstructor" />
+
Use this rule and customize it:
+<rule ref="category/java/documentation.xml/UncommentedEmptyConstructor">
+ <properties>
+ <property name="ignoreExplicitConstructorInvocation" value="false" />
+ </properties>
+</rule>
+
Since: PMD 3.4
+ +Priority: Medium (3)
+ +Uncommented Empty Method Body finds instances where a method body does not contain +statements, but there is no comment. By explicitly commenting empty method bodies +it is easier to distinguish between intentional (commented) and unintentional +empty methods.
+ +This rule is defined by the following XPath expression:
+//MethodDeclaration/Block[count(BlockStatement) = 0 and @containsComment = false()]
+
Example(s):
+ +public void doSomething() {
+}
+
Use this rule by referencing it:
+<rule ref="category/java/documentation.xml/UncommentedEmptyMethodBody" />
+
Since: PMD 1.03
+ +Priority: Medium (3)
+ +Avoid assignments in operands; this can make code more complicated and harder to read.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.errorprone.AssignmentInOperandRule
+ +Example(s):
+ +public void bar() {
+ int x = 2;
+ if ((x = getX()) == 3) {
+ System.out.println("3!");
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
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 with the default properties by just referencing it:
+<rule ref="category/java/errorprone.xml/AssignmentInOperand" />
+
Use this rule and customize it:
+<rule ref="category/java/errorprone.xml/AssignmentInOperand">
+ <properties>
+ <property name="allowIf" value="false" />
+ <property name="allowFor" value="false" />
+ <property name="allowWhile" value="false" />
+ <property name="allowIncrementDecrement" value="false" />
+ </properties>
+</rule>
+
Since: PMD 2.2
+ +Priority: Medium (3)
+ +Identifies a possible unsafe usage of a static field.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.errorprone.AssignmentToNonFinalStaticRule
+ +Example(s):
+ +public class StaticField {
+ static int x;
+ public FinalFields(int y) {
+ x = y; // unsafe
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/AssignmentToNonFinalStatic" />
+
Since: PMD 4.1
+ +Priority: Medium (3)
+ +Methods such as getDeclaredConstructors(), getDeclaredConstructor(Class[]) and setAccessible(), +as the interface PrivilegedAction, allow for the runtime alteration of variable, class, or +method visibility, even if they are private. This violates the principle of encapsulation.
+ +This rule is defined by the following XPath expression:
+//PrimaryExpression[
+(
+(PrimarySuffix[
+ ends-with(@Image,'getDeclaredConstructors')
+ or
+ ends-with(@Image,'getDeclaredConstructor')
+ or
+ ends-with(@Image,'setAccessible')
+ ])
+or
+(PrimaryPrefix/Name[
+ ends-with(@Image,'getDeclaredConstructor')
+ or
+ ends-with(@Image,'getDeclaredConstructors')
+ or
+ starts-with(@Image,'AccessibleObject.setAccessible')
+ ])
+)
+and
+(//ImportDeclaration/Name[
+ contains(@Image,'java.security.PrivilegedAction')])
+]
+
Example(s):
+ +import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Method;
+import java.security.PrivilegedAction;
+
+public class Violation {
+ public void invalidCallsInMethod() throws SecurityException, NoSuchMethodException {
+ // Possible call to forbidden getDeclaredConstructors
+ Class[] arrayOfClass = new Class[1];
+ this.getClass().getDeclaredConstructors();
+ this.getClass().getDeclaredConstructor(arrayOfClass);
+ Class clazz = this.getClass();
+ clazz.getDeclaredConstructor(arrayOfClass);
+ clazz.getDeclaredConstructors();
+ // Possible call to forbidden setAccessible
+ clazz.getMethod("", arrayOfClass).setAccessible(false);
+ AccessibleObject.setAccessible(null, false);
+ Method.setAccessible(null, false);
+ Method[] methodsArray = clazz.getMethods();
+ int nbMethod;
+ for ( nbMethod = 0; nbMethod < methodsArray.length; nbMethod++ ) {
+ methodsArray[nbMethod].setAccessible(false);
+ }
+
+ // Possible call to forbidden PrivilegedAction
+ PrivilegedAction priv = (PrivilegedAction) new Object(); priv.run();
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/AvoidAccessibilityAlteration" />
+
Since: PMD 3.4
+ +Priority: Medium High (2)
+ +Use of the term ‘assert’ will conflict with newer versions of Java since it is a reserved word.
+ +This rule is defined by the following XPath expression:
+//VariableDeclaratorId[@Name='assert']
+
Example(s):
+ +public class A {
+ public class Foo {
+ String assert = "foo";
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/AvoidAssertAsIdentifier" />
+
Since: PMD 5.0
+ +Priority: Medium High (2)
+ +Using a branching statement as the last part of a loop may be a bug, and/or is confusing. +Ensure that the usage is not a bug, or consider using another approach.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.errorprone.AvoidBranchingStatementAsLastInLoopRule
+ +Example(s):
+ +// unusual use of branching statement in a loop
+for (int i = 0; i < 10; i++) {
+ if (i*i <= 25) {
+ continue;
+ }
+ break;
+}
+
+// this makes more sense...
+for (int i = 0; i < 10; i++) {
+ if (i*i > 25) {
+ break;
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
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 with the default properties by just referencing it:
+<rule ref="category/java/errorprone.xml/AvoidBranchingStatementAsLastInLoop" />
+
Use this rule and customize it:
+<rule ref="category/java/errorprone.xml/AvoidBranchingStatementAsLastInLoop">
+ <properties>
+ <property name="checkBreakLoopTypes" value="for|do|while" />
+ <property name="checkContinueLoopTypes" value="for|do|while" />
+ <property name="checkReturnLoopTypes" value="for|do|while" />
+ </properties>
+</rule>
+
Since: PMD 3.0
+ +Priority: Medium (3)
+ +The method Object.finalize() is called by the garbage collector on an object when garbage collection determines +that there are no more references to the object. It should not be invoked by application logic.
+ +Note that Oracle has declared Object.finalize() as deprecated since JDK 9.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.errorprone.AvoidCallingFinalizeRule
+ +Example(s):
+ +void foo() {
+ Bar b = new Bar();
+ b.finalize();
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/AvoidCallingFinalize" />
+
Since: PMD 1.8
+ +Priority: Medium (3)
+ +Code should never throw NullPointerExceptions under normal circumstances. A catch block may hide the +original error, causing other, more subtle problems later on.
+ +This rule is defined by the following XPath expression:
+//CatchStatement/FormalParameter/Type
+ /ReferenceType/ClassOrInterfaceType[@Image='NullPointerException']
+
Example(s):
+ +public class Foo {
+ void bar() {
+ try {
+ // do something
+ } catch (NullPointerException npe) {
+ }
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/AvoidCatchingNPE" />
+
Since: PMD 1.2
+ +Priority: Medium (3)
+ +Catching Throwable errors is not recommended since its scope is very broad. It includes runtime issues such as +OutOfMemoryError that should be exposed and managed separately.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.errorprone.AvoidCatchingThrowableRule
+ +Example(s):
+ +public void bar() {
+ try {
+ // do something
+ } catch (Throwable th) { // should not catch Throwable
+ th.printStackTrace();
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/AvoidCatchingThrowable" />
+
Since: PMD 3.4
+ +Priority: Medium (3)
+ +One might assume that the result of "new BigDecimal(0.1)" is exactly equal to 0.1, but it is actually +equal to .1000000000000000055511151231257827021181583404541015625. +This is because 0.1 cannot be represented exactly as a double (or as a binary fraction of any finite +length). Thus, the long value that is being passed in to the constructor is not exactly equal to 0.1, +appearances notwithstanding.
+ +The (String) constructor, on the other hand, is perfectly predictable: ‘new BigDecimal("0.1")’ is +exactly equal to 0.1, as one would expect. Therefore, it is generally recommended that the +(String) constructor be used in preference to this one.
+ +This rule is defined by the following XPath expression:
+//AllocationExpression[pmd-java:typeIs('java.math.BigDecimal')]
+[Arguments/ArgumentList/Expression/PrimaryExpression
+ [
+ pmd-java:typeIs('float') or
+ pmd-java:typeIs('java.lang.Float') or
+ pmd-java:typeIs('double') or
+ pmd-java:typeIs('java.lang.Double')
+ ]
+]
+
Example(s):
+ +BigDecimal bd = new BigDecimal(1.123); // loss of precision, this would trigger the rule
+
+BigDecimal bd = new BigDecimal("1.123"); // preferred approach
+
+BigDecimal bd = new BigDecimal(12); // preferred approach, ok for integer values
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/AvoidDecimalLiteralsInBigDecimalConstructor" />
+
Since: PMD 1.0
+ +Priority: Medium (3)
+ +Code containing duplicate String literals can usually be improved by declaring the String as a constant field.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.errorprone.AvoidDuplicateLiteralsRule
+ +Example(s):
+ +private void bar() {
+ buz("Howdy");
+ buz("Howdy");
+ buz("Howdy");
+ buz("Howdy");
+}
+private void buz(String x) {}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
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 | +
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 with the default properties by just referencing it:
+<rule ref="category/java/errorprone.xml/AvoidDuplicateLiterals" />
+
Use this rule and customize it:
+<rule ref="category/java/errorprone.xml/AvoidDuplicateLiterals">
+ <properties>
+ <property name="separator" value="," />
+ <property name="maxDuplicateLiterals" value="4" />
+ <property name="minimumLength" value="3" />
+ <property name="skipAnnotations" value="false" />
+ <property name="exceptionList" value="" />
+ </properties>
+</rule>
+
Since: PMD 3.4
+ +Priority: Medium High (2)
+ +Use of the term ‘enum’ will conflict with newer versions of Java since it is a reserved word.
+ +This rule is defined by the following XPath expression:
+//VariableDeclaratorId[@Name='enum']
+
Example(s):
+ +public class A {
+ public class Foo {
+ String enum = "foo";
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/AvoidEnumAsIdentifier" />
+
Since: PMD 3.0
+ +Priority: Medium (3)
+ +It can be confusing to have a field name with the same name as a method. While this is permitted, +having information (field) and actions (method) is not clear naming. Developers versed in +Smalltalk often prefer this approach as the methods denote accessor methods.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.errorprone.AvoidFieldNameMatchingMethodNameRule
+ +Example(s):
+ +public class Foo {
+ Object bar;
+ // bar is data or an action or both?
+ void bar() {
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/AvoidFieldNameMatchingMethodName" />
+
Since: PMD 3.0
+ +Priority: Medium (3)
+ +It is somewhat confusing to have a field name matching the declaring class name. +This probably means that type and/or field names should be chosen more carefully.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.errorprone.AvoidFieldNameMatchingTypeNameRule
+ +Example(s):
+ +public class Foo extends Bar {
+ int foo; // There is probably a better name that can be used
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/AvoidFieldNameMatchingTypeName" />
+
Since: PMD 3.0
+ +Priority: Medium (3)
+ +Each caught exception type should be handled in its own catch clause.
+ +This rule is defined by the following XPath expression:
+//CatchStatement/FormalParameter
+ /following-sibling::Block//InstanceOfExpression/PrimaryExpression/PrimaryPrefix
+ /Name[
+ @Image = ./ancestor::Block/preceding-sibling::FormalParameter
+ /VariableDeclaratorId/@Name
+ ]
+
Example(s):
+ +try { // Avoid this
+ // do something
+} catch (Exception ee) {
+ if (ee instanceof IOException) {
+ cleanup();
+ }
+}
+
+try { // Prefer this:
+ // do something
+} catch (IOException ee) {
+ cleanup();
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/AvoidInstanceofChecksInCatchClause" />
+
Since: PMD 4.2.6
+ +Priority: Medium (3)
+ +Avoid using hard-coded literals in conditional statements. By declaring them as static variables +or private members with descriptive names maintainability is enhanced. By default, the literals "-1" and "0" are ignored. +More exceptions can be defined with the property "ignoreMagicNumbers".
+ +The rule doesn’t consider deeper expressions by default, but this can be enabled via the property ignoreExpressions
.
+With this property set to false, if-conditions like i == 1 + 5
are reported as well. Note that in that case,
+the property ignoreMagicNumbers is not taken into account, if there are multiple literals involved in such an expression.
This rule is defined by the following XPath expression:
+(: simple case - no deep expressions :)
+//IfStatement[$ignoreExpressions = true()]/Expression/*/PrimaryExpression/PrimaryPrefix/Literal
+ [not(NullLiteral)]
+ [not(BooleanLiteral)]
+ [empty(index-of(tokenize($ignoreMagicNumbers, '\s*,\s*'), @Image))]
+|
+(: consider also deeper expressions :)
+//IfStatement[$ignoreExpressions = false()]/Expression//*[local-name() != 'UnaryExpression' or @Operator != '-']/PrimaryExpression/PrimaryPrefix/Literal
+ [not(NullLiteral)]
+ [not(BooleanLiteral)]
+ [empty(index-of(tokenize($ignoreMagicNumbers, '\s*,\s*'), @Image))]
+|
+(: consider negative literals :)
+//IfStatement[$ignoreExpressions = false()]/Expression//UnaryExpression[@Operator = '-']/PrimaryExpression/PrimaryPrefix/Literal
+ [not(NullLiteral)]
+ [not(BooleanLiteral)]
+ [empty(index-of(tokenize($ignoreMagicNumbers, '\s*,\s*'), concat('-', @Image)))]
+|
+(: consider multiple literals in expressions :)
+//IfStatement[$ignoreExpressions = false()]/Expression[count(*/PrimaryExpression/PrimaryPrefix/Literal
+ [not(NullLiteral)]
+ [not(BooleanLiteral)]) > 1]
+
Example(s):
+ +private static final int MAX_NUMBER_OF_REQUESTS = 10;
+
+public void checkRequests() {
+
+ if (i == 10) { // magic number, buried in a method
+ doSomething();
+ }
+
+ if (i == MAX_NUMBER_OF_REQUESTS) { // preferred approach
+ doSomething();
+ }
+
+ if (aString.indexOf('.') != -1) {} // magic number -1, by default ignored
+ if (aString.indexOf('.') >= 0) { } // alternative approach
+
+ if (aDouble > 0.0) {} // magic number 0.0
+ if (aDouble >= Double.MIN_VALUE) {} // preferred approach
+
+ // with rule property "ignoreExpressions" set to "false"
+ if (i == pos + 5) {} // violation: magic number 5 within an (additive) expression
+ if (i == pos + SUFFIX_LENGTH) {} // preferred approach
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
ignoreMagicNumbers | +-1,0 | +Comma-separated list of magic numbers, that should be ignored | +no | +
ignoreExpressions | +true | +If true, only literals in simple if conditions are considered. Otherwise literals in expressions are checked, too. | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/errorprone.xml/AvoidLiteralsInIfCondition" />
+
Use this rule and customize it:
+<rule ref="category/java/errorprone.xml/AvoidLiteralsInIfCondition">
+ <properties>
+ <property name="ignoreMagicNumbers" value="-1,0" />
+ <property name="ignoreExpressions" value="true" />
+ </properties>
+</rule>
+
Since: PMD 4.2.6
+ +Priority: Medium High (2)
+ +Statements in a catch block that invoke accessors on the exception without using the information +only add to code size. Either remove the invocation, or use the return result.
+ +This rule is defined by the following XPath expression:
+//CatchStatement/Block/BlockStatement/Statement/StatementExpression/PrimaryExpression/PrimaryPrefix/Name
+[
+ @Image = concat(../../../../../../../FormalParameter/VariableDeclaratorId/@Name, '.getMessage')
+ or
+ @Image = concat(../../../../../../../FormalParameter/VariableDeclaratorId/@Name, '.getLocalizedMessage')
+ or
+ @Image = concat(../../../../../../../FormalParameter/VariableDeclaratorId/@Name, '.getCause')
+ or
+ @Image = concat(../../../../../../../FormalParameter/VariableDeclaratorId/@Name, '.getStackTrace')
+ or
+ @Image = concat(../../../../../../../FormalParameter/VariableDeclaratorId/@Name, '.toString')
+]
+
Example(s):
+ +public void bar() {
+ try {
+ // do something
+ } catch (SomeException se) {
+ se.getMessage();
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/AvoidLosingExceptionInformation" />
+
Since: PMD 4.2
+ +Priority: Medium High (2)
+ +The use of multiple unary operators may be problematic, and/or confusing. +Ensure that the intended usage is not a bug, or consider simplifying the expression.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.errorprone.AvoidMultipleUnaryOperatorsRule
+ +Example(s):
+ +// These are typo bugs, or at best needlessly complex and confusing:
+int i = - -1;
+int j = + - +1;
+int z = ~~2;
+boolean b = !!true;
+boolean c = !!!true;
+
+// These are better:
+int i = 1;
+int j = -1;
+int z = 2;
+boolean b = true;
+boolean c = false;
+
+// And these just make your brain hurt:
+int i = ~-2;
+int j = -~7;
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/AvoidMultipleUnaryOperators" />
+
Since: PMD 3.9
+ +Priority: Medium (3)
+ +Integer literals should not start with zero since this denotes that the rest of literal will be +interpreted as an octal value.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.errorprone.AvoidUsingOctalValuesRule
+ +Example(s):
+ +int i = 012; // set i with 10 not 12
+int j = 010; // set j with 8 not 10
+k = i * j; // set k with 80 not 120
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
strict | +false | +Detect violations between 00 and 07 | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/errorprone.xml/AvoidUsingOctalValues" />
+
Use this rule and customize it:
+<rule ref="category/java/errorprone.xml/AvoidUsingOctalValues">
+ <properties>
+ <property name="strict" value="false" />
+ </properties>
+</rule>
+
Since: PMD 1.8
+ +Priority: Medium (3)
+ +Avoid equality comparisons with Double.NaN. Due to the implicit lack of representation +precision when comparing floating point numbers these are likely to cause logic errors.
+ +This rule is defined by the following XPath expression:
+//EqualityExpression[@Image='==']
+ /PrimaryExpression/PrimaryPrefix
+ /Name[@Image='Double.NaN' or @Image='Float.NaN']
+
Example(s):
+ +boolean x = (y == Double.NaN);
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/BadComparison" />
+
Since: PMD 1.1
+ +Priority: Medium (3)
+ +If a class is a bean, or is referenced by a bean directly or indirectly it needs to be serializable. +Member variables need to be marked as transient, static, or have accessor methods in the class. Marking +variables as transient is the safest and easiest modification. Accessor methods should follow the Java +naming conventions, i.e. for a variable named foo, getFoo() and setFoo() accessor methods should be provided.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.errorprone.BeanMembersShouldSerializeRule
+ +Example(s):
+ +private transient int someFoo; // good, it's transient
+private static int otherFoo; // also OK
+private int moreFoo; // OK, has proper accessors, see below
+private int badFoo; // bad, should be marked transient
+
+private void setMoreFoo(int moreFoo){
+ this.moreFoo = moreFoo;
+}
+
+private int getMoreFoo(){
+ return this.moreFoo;
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
ignoredAnnotations | +lombok.Data | lombok.Getter | lombok.Value | +Fully qualified names of the annotation types that should be ignored by this rule | +yes. Delimiter is ‘|’. | +
prefix | ++ | A variable prefix to skip, i.e., m_ | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/errorprone.xml/BeanMembersShouldSerialize" />
+
Use this rule and customize it:
+<rule ref="category/java/errorprone.xml/BeanMembersShouldSerialize">
+ <properties>
+ <property name="ignoredAnnotations" value="lombok.Data|lombok.Getter|lombok.Value" />
+ <property name="prefix" value="" />
+ </properties>
+</rule>
+
Since: PMD 3.8
+ +Priority: Medium High (2)
+ +The null check is broken since it will throw a NullPointerException itself. +It is likely that you used || instead of && or vice versa.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.errorprone.BrokenNullCheckRule
+ +Example(s):
+ +public String bar(String string) {
+ // should be &&
+ if (string!=null || !string.equals(""))
+ return string;
+ // should be ||
+ if (string==null && string.equals(""))
+ return string;
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/BrokenNullCheck" />
+
Since: PMD 4.2.5
+ +Priority: Medium (3)
+ +Super should be called at the start of the method
+ +This rule is defined by the following XPath expression:
+//MethodDeclaration[
+ @Name='onCreate' or
+ @Name='onConfigurationChanged' or
+ @Name='onPostCreate' or
+ @Name='onPostResume' or
+ @Name='onRestart' or
+ @Name='onRestoreInstanceState' or
+ @Name='onResume' or
+ @Name='onStart'
+ ]
+ /Block[not(
+ (BlockStatement[1]/Statement/StatementExpression/PrimaryExpression[./PrimaryPrefix[@SuperModifier= true()]]/PrimarySuffix[@Image= ancestor::MethodDeclaration/@Name]))]
+[ancestor::ClassOrInterfaceDeclaration[ExtendsList/ClassOrInterfaceType[
+ pmd-java:typeIs('android.app.Activity') or
+ pmd-java:typeIs('android.app.Application') or
+ pmd-java:typeIs('android.app.Service')
+]]]
+
Example(s):
+ +public class DummyActivity extends Activity {
+ public void onCreate(Bundle bundle) {
+ // missing call to super.onCreate(bundle)
+ foo();
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/CallSuperFirst" />
+
Since: PMD 4.2.5
+ +Priority: Medium (3)
+ +Super should be called at the end of the method
+ +This rule is defined by the following XPath expression:
+//MethodDeclaration[
+ @Name='finish' or
+ @Name='onDestroy' or
+ @Name='onPause' or
+ @Name='onSaveInstanceState' or
+ @Name='onStop' or
+ @Name='onTerminate'
+ ]
+ /Block/BlockStatement[last()]
+ [not(Statement/StatementExpression/PrimaryExpression[./PrimaryPrefix[@SuperModifier= true()]]/PrimarySuffix[@Image= ancestor::MethodDeclaration/@Name])]
+[ancestor::ClassOrInterfaceDeclaration[ExtendsList/ClassOrInterfaceType[
+ pmd-java:typeIs('android.app.Activity') or
+ pmd-java:typeIs('android.app.Application') or
+ pmd-java:typeIs('android.app.Service')
+]]]
+
Example(s):
+ +public class DummyActivity extends Activity {
+ public void onPause() {
+ foo();
+ // missing call to super.onPause()
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/CallSuperLast" />
+
Since: PMD 5.0
+ +Priority: Medium (3)
+ +The skip() method may skip a smaller number of bytes than requested. Check the returned value to find out if it was the case or not.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.errorprone.CheckSkipResultRule
+ +Example(s):
+ +public class Foo {
+
+ private FileInputStream _s = new FileInputStream("file");
+
+ public void skip(int n) throws IOException {
+ _s.skip(n); // You are not sure that exactly n bytes are skipped
+ }
+
+ public void skipExactly(int n) throws IOException {
+ while (n != 0) {
+ long skipped = _s.skip(n);
+ if (skipped == 0)
+ throw new EOFException();
+ n -= skipped;
+ }
+ }
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/CheckSkipResult" />
+
Since: PMD 3.4
+ +Priority: Medium (3)
+ +When deriving an array of a specific class from your Collection, one should provide an array of +the same class as the parameter of the toArray() method. Doing otherwise you will will result +in a ClassCastException.
+ +This rule is defined by the following XPath expression:
+//CastExpression[Type/ReferenceType/ClassOrInterfaceType[@Image != "Object"]]
+ /PrimaryExpression
+ [PrimaryPrefix/Name[ends-with(@Image, '.toArray')]]
+ [PrimarySuffix/Arguments[not(*)]]
+ [count(PrimarySuffix) = 1]
+
Example(s):
+ +Collection c = new ArrayList();
+Integer obj = new Integer(1);
+c.add(obj);
+
+ // this would trigger the rule (and throw a ClassCastException if executed)
+Integer[] a = (Integer [])c.toArray();
+
+ // this is fine and will not trigger the rule
+Integer[] b = (Integer [])c.toArray(new Integer[c.size()]);
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/ClassCastExceptionWithToArray" />
+
Since: PMD 5.4.0
+ +Priority: Medium (3)
+ +The java Manual says "By convention, classes that implement this interface should override +Object.clone (which is protected) with a public method."
+ +This rule is defined by the following XPath expression:
+//MethodDeclaration[@Public= false()]
+ [@Name = 'clone']
+ [@Arity = 0]
+
Example(s):
+ +public class Foo implements Cloneable {
+ @Override
+ protected Object clone() throws CloneNotSupportedException { // Violation, must be public
+ }
+}
+
+public class Foo implements Cloneable {
+ @Override
+ protected Foo clone() { // Violation, must be public
+ }
+}
+
+public class Foo implements Cloneable {
+ @Override
+ public Object clone() // Ok
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/CloneMethodMustBePublic" />
+
Since: PMD 1.9
+ +Priority: Medium (3)
+ +The method clone() should only be implemented if the class implements the Cloneable interface with the exception of +a final method that only throws CloneNotSupportedException.
+ +The rule can also detect, if the class implements or extends a Cloneable class.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.errorprone.CloneMethodMustImplementCloneableRule
+ +Example(s):
+ +public class MyClass {
+ public Object clone() throws CloneNotSupportedException {
+ return foo;
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/CloneMethodMustImplementCloneable" />
+
Since: PMD 5.4.0
+ +Priority: Medium (3)
+ +Minimum Language Version: Java 1.5
+ +If a class implements cloneable the return type of the method clone() must be the class name. That way, the caller +of the clone method doesn’t need to cast the returned clone to the correct type.
+ +Note: This is only possible with Java 1.5 or higher.
+ +This rule is defined by the following XPath expression:
+//MethodDeclaration
+[
+@Name = 'clone'
+and @Arity = 0
+and not (ResultType//ClassOrInterfaceType/@Image = ancestor::ClassOrInterfaceDeclaration[1]/@SimpleName)
+]
+
Example(s):
+ +public class Foo implements Cloneable {
+ @Override
+ protected Object clone() { // Violation, Object must be Foo
+ }
+}
+
+public class Foo implements Cloneable {
+ @Override
+ public Foo clone() { //Ok
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/CloneMethodReturnTypeMustMatchClassName" />
+
Since: PMD 1.9
+ +Priority: Medium (3)
+ +The method clone() should throw a CloneNotSupportedException.
+ +This rule is defined by the following XPath expression:
+//MethodDeclaration
+[
+@Name = 'clone'
+and @Arity = 0
+and count(NameList/Name[contains
+(@Image,'CloneNotSupportedException')]) = 0
+]
+[
+../../../../ClassOrInterfaceDeclaration[@Final = false()]
+]
+
Example(s):
+ +public class MyClass implements Cloneable{
+ public Object clone() { // will cause an error
+ MyClass clone = (MyClass)super.clone();
+ return clone;
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/CloneThrowsCloneNotSupportedException" />
+
Since: PMD 1.2.2
+ +Priority: Medium (3)
+ +Ensure that resources (like java.sql.Connection
, java.sql.Statement
, and java.sql.ResultSet
objects
+and any subtype of java.lang.AutoCloseable
) are always closed after use.
+Failing to do so might result in resource leaks.
Note: It suffices to configure the super type, e.g. java.lang.AutoClosable
, so that this rule automatically triggers
+on any subtype (e.g. java.io.FileInputStream
). Additionally specifying java.sql.Connection
helps in detecting
+the types, if the type resolution / auxclasspath is not correctly setup.
Note: Since PMD 6.16.0 the default value for the property types
contains java.lang.AutoCloseable
and detects
+now cases where the standard java.io.*Stream
classes are involved. In order to restore the old behaviour,
+just remove "AutoCloseable" from the types.
This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.errorprone.CloseResourceRule
+ +Example(s):
+ +public class Bar {
+ public void withSQL() {
+ Connection c = pool.getConnection();
+ try {
+ // do stuff
+ } catch (SQLException ex) {
+ // handle exception
+ } finally {
+ // oops, should close the connection using 'close'!
+ // c.close();
+ }
+ }
+
+ public void withFile() {
+ InputStream file = new FileInputStream(new File("/tmp/foo"));
+ try {
+ int c = file.in();
+ } catch (IOException e) {
+ // handle exception
+ } finally {
+ // TODO: close file
+ }
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
closeTargets | ++ | Methods which may close this resource | +yes. Delimiter is ‘,’. | +
types | +java.lang.AutoCloseable , java.sql.Connection , java.sql.Statement , java.sql.ResultSet | +Affected types | +yes. Delimiter is ‘,’. | +
closeAsDefaultTarget | +true | +Consider ‘close’ as a target by default | +no | +
allowedResourceTypes | +java.io.ByteArrayOutputStream | java.io.ByteArrayInputStream | java.io.StringWriter | java.io.CharArrayWriter | java.util.stream.Stream | java.util.stream.IntStream | java.util.stream.LongStream | java.util.stream.DoubleStream | +Exact class names that do not need to be closed | +yes. Delimiter is ‘|’. | +
closeNotInFinally | +false | +Detect if ‘close’ (or other closeTargets) is called outside of a finally-block | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/errorprone.xml/CloseResource" />
+
Use this rule and customize it:
+<rule ref="category/java/errorprone.xml/CloseResource">
+ <properties>
+ <property name="closeTargets" value="" />
+ <property name="types" value="java.lang.AutoCloseable,java.sql.Connection,java.sql.Statement,java.sql.ResultSet" />
+ <property name="closeAsDefaultTarget" value="true" />
+ <property name="allowedResourceTypes" value="java.io.ByteArrayOutputStream|java.io.ByteArrayInputStream|java.io.StringWriter|java.io.CharArrayWriter|java.util.stream.Stream|java.util.stream.IntStream|java.util.stream.LongStream|java.util.stream.DoubleStream" />
+ <property name="closeNotInFinally" value="false" />
+ </properties>
+</rule>
+
Since: PMD 3.2
+ +Priority: Medium (3)
+ +Use equals() to compare object references; avoid comparing them with ==.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.errorprone.CompareObjectsWithEqualsRule
+ +Example(s):
+ +class Foo {
+ boolean bar(String a, String b) {
+ return a == b;
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/CompareObjectsWithEquals" />
+
Since: PMD 1.04
+ +Priority: High (1)
+ +Calling overridable methods during construction poses a risk of invoking methods on an incompletely +constructed object and can be difficult to debug. +It may leave the sub-class unable to construct its superclass or forced to replicate the construction +process completely within itself, losing the ability to call super(). If the default constructor +contains a call to an overridable method, the subclass may be completely uninstantiable. Note that +this includes method calls throughout the control flow graph - i.e., if a constructor Foo() calls a +private method bar() that calls a public method buz(), this denotes a problem.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.errorprone.ConstructorCallsOverridableMethodRule
+ +Example(s):
+ +public class SeniorClass {
+ public SeniorClass(){
+ toString(); //may throw NullPointerException if overridden
+ }
+ public String toString(){
+ return "IAmSeniorClass";
+ }
+}
+public class JuniorClass extends SeniorClass {
+ private String name;
+ public JuniorClass(){
+ super(); //Automatic call leads to NullPointerException
+ name = "JuniorClass";
+ }
+ public String toString(){
+ return name.toUpperCase();
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/ConstructorCallsOverridableMethod" />
+
Deprecated
+ +Since: PMD 3.9
+ +Priority: Low (5)
+ +The dataflow analysis tracks local definitions, undefinitions and references to variables on different paths on the data flow. +From those informations there can be found various problems.
+ +This rule is deprecated. Use UnusedAssignment
in category bestpractices instead.
This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.errorprone.DataflowAnomalyAnalysisRule
+ +Example(s):
+ +public void foo() {
+ int buz = 5;
+ buz = 6; // redefinition of buz -> dd-anomaly
+ foo(buz);
+ buz = 2;
+} // buz is undefined when leaving scope -> du-anomaly
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
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 with the default properties by just referencing it:
+<rule ref="category/java/errorprone.xml/DataflowAnomalyAnalysis" />
+
Use this rule and customize it:
+<rule ref="category/java/errorprone.xml/DataflowAnomalyAnalysis">
+ <properties>
+ <property name="maxPaths" value="1000" />
+ <property name="maxViolations" value="100" />
+ </properties>
+</rule>
+
Since: PMD 6.13.0
+ +Priority: Medium (3)
+ +The method appears to be a test case since it has public or default visibility, +non-static access, no arguments, no return value, has no annotations, but is a +member of a class that has one or more JUnit test cases. If it is a utility +method, it should likely have private visibility. If it is an ignored test, it +should be annotated with @Test and @Ignore.
+ +This rule is defined by the following XPath expression:
+//ClassOrInterfaceBodyDeclaration
+[../ClassOrInterfaceBodyDeclaration/Annotation/*/Name
+ [pmd-java:typeIs('org.junit.Test')
+ or pmd-java:typeIs('org.junit.jupiter.api.Test')
+ or pmd-java:typeIs('org.junit.jupiter.api.RepeatedTest')
+ or pmd-java:typeIs('org.junit.jupiter.api.TestFactory')
+ or pmd-java:typeIs('org.junit.jupiter.api.TestTemplate')
+ or pmd-java:typeIs('org.junit.jupiter.params.ParameterizedTest')]
+]
+[not(Annotation)]
+[MethodDeclaration[(@Public = true() or @PackagePrivate = true()) and @Static = false() and
+ ResultType[@Void = true()] and
+ MethodDeclarator/FormalParameters[@Size = 0]
+ ]
+]
+
Example(s):
+ +public class MyTest {
+ @Test
+ public void someTest() {
+ }
+
+ // violation: Not annotated
+ public void someOtherTest () {
+ }
+
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/DetachedTestCase" />
+
Since: PMD 4.2
+ +Priority: Medium High (2)
+ +Calls to System.gc(), Runtime.getRuntime().gc(), and System.runFinalization() are not advised. Code should have the +same behavior whether the garbage collection is disabled using the option -Xdisableexplicitgc or not. +Moreover, "modern" jvms do a very good job handling garbage collections. If memory usage issues unrelated to memory +leaks develop within an application, it should be dealt with JVM options rather than within the code itself.
+ +This rule is defined by the following XPath expression:
+//Name[
+(starts-with(@Image, 'System.') and
+(starts-with(@Image, 'System.gc') or
+starts-with(@Image, 'System.runFinalization'))) or
+(
+starts-with(@Image,'Runtime.getRuntime') and
+../../PrimarySuffix[ends-with(@Image,'gc')]
+)
+]
+
Example(s):
+ +public class GCCall {
+ public GCCall() {
+ // Explicit gc call !
+ System.gc();
+ }
+
+ public void doSomething() {
+ // Explicit gc call !
+ Runtime.getRuntime().gc();
+ }
+
+ public explicitGCcall() {
+ // Explicit gc call !
+ System.gc();
+ }
+
+ public void doSomething() {
+ // Explicit gc call !
+ Runtime.getRuntime().gc();
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/DoNotCallGarbageCollectionExplicitly" />
+
Deprecated
+ +This rule has been renamed. Use instead: DoNotTerminateVM
+ +Deprecated
+ +Since: PMD 4.1
+ +Priority: Medium (3)
+ +Web applications should not call System.exit()
, since only the web container or the
+application server should stop the JVM. Otherwise a web application would terminate all other applications
+running on the same application server.
This rule also checks for the equivalent calls Runtime.getRuntime().exit()
and Runtime.getRuntime().halt()
.
This rule was called DoNotCallSystemExit until PMD 6.29.0.
+ +This rule is defined by the following XPath expression:
+//Name[
+ starts-with(@Image,'System.exit')
+ or
+ (starts-with(@Image,'Runtime.getRuntime') and ../../PrimarySuffix[ends-with(@Image,'exit') or ends-with(@Image,'halt')])
+][not(ancestor::MethodDeclaration[1][@Name="main" and @Static = true()])]
+
Example(s):
+ +public void bar() {
+ System.exit(0); // never call this when running in an application server!
+}
+public void foo() {
+ Runtime.getRuntime().exit(0); // never stop the JVM manually, the container will do this.
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/DoNotCallSystemExit" />
+
Since: PMD 6.0.0
+ +Priority: Medium (3)
+ +Extend Exception or RuntimeException instead of Throwable.
+ +This rule is defined by the following XPath expression:
+//ClassOrInterfaceDeclaration/ExtendsList/ClassOrInterfaceType
+ [@Image="Throwable" or @Image="java.lang.Throwable"]
+
Example(s):
+ +public class Foo extends Throwable { }
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/DoNotExtendJavaLangThrowable" />
+
Since: PMD 4.2.6
+ +Priority: Medium (3)
+ +Use Environment.getExternalStorageDirectory() instead of "/sdcard"
+ +This rule is defined by the following XPath expression:
+//Literal[starts-with(@Image,'"/sdcard')]
+
Example(s):
+ +public class MyActivity extends Activity {
+ protected void foo() {
+ String storageLocation = "/sdcard/mypackage"; // hard-coded, poor approach
+
+ storageLocation = Environment.getExternalStorageDirectory() + "/mypackage"; // preferred approach
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/DoNotHardCodeSDCard" />
+
Since: PMD 4.1
+ +Priority: Medium (3)
+ +Web applications should not call System.exit()
, since only the web container or the
+application server should stop the JVM. Otherwise a web application would terminate all other applications
+running on the same application server.
This rule also checks for the equivalent calls Runtime.getRuntime().exit()
and Runtime.getRuntime().halt()
.
This rule was called DoNotCallSystemExit until PMD 6.29.0.
+ +This rule is defined by the following XPath expression:
+//Name[
+ starts-with(@Image,'System.exit')
+ or
+ (starts-with(@Image,'Runtime.getRuntime') and ../../PrimarySuffix[ends-with(@Image,'exit') or ends-with(@Image,'halt')])
+][not(ancestor::MethodDeclaration[1][@Name="main" and @Static = true()])]
+
Example(s):
+ +public void bar() {
+ System.exit(0); // never call this when running in an application server!
+}
+public void foo() {
+ Runtime.getRuntime().exit(0); // never stop the JVM manually, the container will do this.
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/DoNotTerminateVM" />
+
Since: PMD 4.2
+ +Priority: Medium Low (4)
+ +Throwing exceptions within a ‘finally’ block is confusing since they may mask other exceptions +or code defects. +Note: This is a PMD implementation of the Lint4j rule "A throw in a finally block"
+ +This rule is defined by the following XPath expression:
+//FinallyStatement[descendant::ThrowStatement]
+
Example(s):
+ +public class Foo {
+ public void bar() {
+ try {
+ // Here do some stuff
+ } catch( Exception e) {
+ // Handling the issue
+ } finally {
+ // is this really a good idea ?
+ throw new Exception();
+ }
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/DoNotThrowExceptionInFinally" />
+
Since: PMD 1.5
+ +Priority: Medium Low (4)
+ +Avoid importing anything from the ‘sun.*’ packages. These packages are not portable and are likely to change.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.errorprone.DontImportSunRule
+ +Example(s):
+ +import sun.misc.foo;
+public class Foo {}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/DontImportSun" />
+
Since: PMD 4.3
+ +Priority: Medium (3)
+ +Don’t use floating point for loop indices. If you must use floating point, use double +unless you’re certain that float provides enough precision and you have a compelling +performance need (space or time).
+ +This rule is defined by the following XPath expression:
+//ForStatement/ForInit/LocalVariableDeclaration
+/Type/PrimitiveType[@Image="float"]
+
Example(s):
+ +public class Count {
+ public static void main(String[] args) {
+ final int START = 2000000000;
+ int count = 0;
+ for (float f = START; f < START + 50; f++)
+ count++;
+ //Prints 0 because (float) START == (float) (START + 50).
+ System.out.println(count);
+ //The termination test misbehaves due to floating point granularity.
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/DontUseFloatTypeForLoopIndices" />
+
Since: PMD 0.1
+ +Priority: Medium (3)
+ +Empty Catch Block finds instances where an exception is caught, but nothing is done. +In most circumstances, this swallows an exception which should either be acted on +or reported.
+ +This rule is defined by the following XPath expression:
+//CatchStatement
+ [not(Block/BlockStatement)]
+ [$allowCommentedBlocks != true() or Block/@containsComment = false()]
+ [FormalParameter/Type/ReferenceType
+ /ClassOrInterfaceType[@Image != 'InterruptedException' and @Image != 'CloneNotSupportedException']
+ ]
+ [FormalParameter/VariableDeclaratorId[not(matches(@Name, $allowExceptionNameRegex))]]
+
Example(s):
+ +public void doSomething() {
+ try {
+ FileInputStream fis = new FileInputStream("/tmp/bugger");
+ } catch (IOException ioe) {
+ // not good
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
allowCommentedBlocks | +false | +Empty blocks containing comments will be skipped | +no | +
allowExceptionNameRegex | +^(ignored|expected)$ | +Empty blocks catching exceptions with names matching this regular expression will be skipped | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/errorprone.xml/EmptyCatchBlock" />
+
Use this rule and customize it:
+<rule ref="category/java/errorprone.xml/EmptyCatchBlock">
+ <properties>
+ <property name="allowCommentedBlocks" value="false" />
+ <property name="allowExceptionNameRegex" value="^(ignored|expected)$" />
+ </properties>
+</rule>
+
Since: PMD 1.5
+ +Priority: Medium (3)
+ +Empty finalize methods serve no purpose and should be removed. Note that Oracle has declared Object.finalize() as deprecated since JDK 9.
+ +This rule is defined by the following XPath expression:
+//MethodDeclaration[@Name='finalize'][@Arity = 0]
+ /Block[not(*)]
+
Example(s):
+ +public class Foo {
+ protected void finalize() {}
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/EmptyFinalizer" />
+
Since: PMD 0.4
+ +Priority: Medium (3)
+ +Empty finally blocks serve no purpose and should be removed.
+ +This rule is defined by the following XPath expression:
+//FinallyStatement[not(Block/BlockStatement)]
+
Example(s):
+ +public class Foo {
+ public void bar() {
+ try {
+ int x=2;
+ } finally {
+ // empty!
+ }
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/EmptyFinallyBlock" />
+
Since: PMD 0.1
+ +Priority: Medium (3)
+ +Empty If Statement finds instances where a condition is checked but nothing is done about it.
+ +This rule is defined by the following XPath expression:
+//IfStatement/Statement
+ [EmptyStatement or Block[not(*)]]
+
Example(s):
+ +public class Foo {
+ void bar(int x) {
+ if (x == 0) {
+ // empty!
+ }
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/EmptyIfStmt" />
+
Since: PMD 5.0
+ +Priority: Medium (3)
+ +Empty initializers serve no purpose and should be removed.
+ +This rule is defined by the following XPath expression:
+//Initializer/Block[not(*)]
+
Example(s):
+ +public class Foo {
+
+ static {} // Why ?
+
+ {} // Again, why ?
+
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/EmptyInitializer" />
+
Since: PMD 5.0
+ +Priority: Medium (3)
+ +Empty block statements serve no purpose and should be removed.
+ +This rule is defined by the following XPath expression:
+//BlockStatement/Statement/Block[not(*)]
+
Example(s):
+ +public class Foo {
+
+ private int _bar;
+
+ public void setBar(int bar) {
+ { _bar = bar; } // Why not?
+ {} // But remove this.
+ }
+
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/EmptyStatementBlock" />
+
Since: PMD 1.5
+ +Priority: Medium (3)
+ +An empty statement (or a semicolon by itself) that is not used as the sole body of a ‘for’ +or ‘while’ loop is probably a bug. It could also be a double semicolon, which has no purpose +and should be removed.
+ +This rule is defined by the following XPath expression:
+//EmptyStatement
+ [not(
+ ../../../ForStatement
+ or ../../../WhileStatement
+ or ../../../BlockStatement/ClassOrInterfaceDeclaration
+ or ../../../../../../ForStatement/Statement[1]
+ /Block[1]/BlockStatement[1]/Statement/EmptyStatement
+ or ../../../../../../WhileStatement/Statement[1]
+ /Block[1]/BlockStatement[1]/Statement/EmptyStatement)
+ ]
+
Example(s):
+ +public void doit() {
+ // this is probably not what you meant to do
+ ;
+ // the extra semicolon here this is not necessary
+ System.out.println("look at the extra semicolon");;
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/EmptyStatementNotInLoop" />
+
Since: PMD 1.0
+ +Priority: Medium (3)
+ +Empty switch statements serve no purpose and should be removed.
+ +This rule is defined by the following XPath expression:
+//SwitchStatement[count(*) = 1]
+
Example(s):
+ +public void bar() {
+ int x = 2;
+ switch (x) {
+ // once there was code here
+ // but it's been commented out or something
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/EmptySwitchStatements" />
+
Since: PMD 1.3
+ +Priority: Medium (3)
+ +Empty synchronized blocks serve no purpose and should be removed.
+ +This rule is defined by the following XPath expression:
+//SynchronizedStatement/Block[1][not(*)]
+
Example(s):
+ +public class Foo {
+ public void bar() {
+ synchronized (this) {
+ // empty!
+ }
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/EmptySynchronizedBlock" />
+
Since: PMD 0.4
+ +Priority: Medium (3)
+ +Avoid empty try blocks - what’s the point?
+ +This rule is defined by the following XPath expression:
+//TryStatement[not(ResourceSpecification)]/Block[1][not(*)]
+
Example(s):
+ +public class Foo {
+ public void bar() {
+ try {
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/EmptyTryBlock" />
+
Since: PMD 0.2
+ +Priority: Medium (3)
+ +Empty While Statement finds all instances where a while statement does nothing. +If it is a timing loop, then you should use Thread.sleep() for it; if it is +a while loop that does a lot in the exit expression, rewrite it to make it clearer.
+ +This rule is defined by the following XPath expression:
+//WhileStatement/Statement[Block[not(*)] or EmptyStatement]
+
Example(s):
+ +void bar(int a, int b) {
+ while (a == b) {
+ // empty!
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/EmptyWhileStmt" />
+
Since: PMD 1.9
+ +Priority: High (1)
+ +Tests for null should not use the equals() method. The ‘==’ operator should be used instead.
+ +This rule is defined by the following XPath expression:
+//PrimaryExpression
+ [
+ PrimaryPrefix[Name[ends-with(@Image, 'equals')]]
+ [following-sibling::node()/Arguments/ArgumentList[count(Expression)=1]
+ /Expression/PrimaryExpression/PrimaryPrefix/Literal/NullLiteral]
+
+ or
+
+ PrimarySuffix[ends-with(@Image, 'equals')]
+ [following-sibling::node()/Arguments/ArgumentList[count(Expression)=1]
+ /Expression/PrimaryExpression/PrimaryPrefix/Literal/NullLiteral]
+
+ ]
+
Example(s):
+ +String x = "foo";
+
+if (x.equals(null)) { // bad form
+ doSomething();
+}
+
+if (x == null) { // preferred
+ doSomething();
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/EqualsNull" />
+
Since: PMD 1.5
+ +Priority: Medium (3)
+ +If the finalize() is implemented, its last action should be to call super.finalize. Note that Oracle has declared Object.finalize() as deprecated since JDK 9.
+ +This rule is defined by the following XPath expression:
+//MethodDeclaration[@Name='finalize'][@Arity = 0]
+ /Block
+ /BlockStatement[last()]
+ [not(Statement/StatementExpression/PrimaryExpression
+ [./PrimaryPrefix[@SuperModifier= true()]]
+ [./PrimarySuffix[@Image='finalize']]
+ )
+ ]
+ [not(Statement/TryStatement/FinallyStatement
+ /Block/BlockStatement/Statement/StatementExpression/PrimaryExpression
+ [./PrimaryPrefix[@SuperModifier= true()]]
+ [./PrimarySuffix[@Image='finalize']]
+ )
+ ]
+
Example(s):
+ +protected void finalize() {
+ something();
+ // neglected to call super.finalize()
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/FinalizeDoesNotCallSuperFinalize" />
+
Since: PMD 1.5
+ +Priority: Medium (3)
+ +If the finalize() is implemented, it should do something besides just calling super.finalize(). Note that Oracle has declared Object.finalize() as deprecated since JDK 9.
+ +This rule is defined by the following XPath expression:
+//MethodDeclaration[@Name='finalize'][@Arity = 0]
+ /Block[count(BlockStatement)=1]
+ /BlockStatement[
+ Statement/StatementExpression/PrimaryExpression
+ [./PrimaryPrefix[@SuperModifier= true()]]
+ [./PrimarySuffix[@Image='finalize']]
+ ]
+
Example(s):
+ +protected void finalize() {
+ super.finalize();
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/FinalizeOnlyCallsSuperFinalize" />
+
Since: PMD 1.5
+ +Priority: Medium (3)
+ +Methods named finalize() should not have parameters. It is confusing and most likely an attempt to +overload Object.finalize(). It will not be called by the VM.
+ +Note that Oracle has declared Object.finalize() as deprecated since JDK 9.
+ +This rule is defined by the following XPath expression:
+//MethodDeclaration[@Name='finalize'][@Arity > 0]
+
Example(s):
+ +public class Foo {
+ // this is confusing and probably a bug
+ protected void finalize(int a) {
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/FinalizeOverloaded" />
+
Since: PMD 1.1
+ +Priority: Medium (3)
+ +When overriding the finalize(), the new method should be set as protected. If made public, +other classes may invoke it at inappropriate times.
+ +Note that Oracle has declared Object.finalize() as deprecated since JDK 9.
+ +This rule is defined by the following XPath expression:
+//MethodDeclaration[@Protected=false()][@Name='finalize'][@Arity = 0]
+
Example(s):
+ +public void finalize() {
+ // do something
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/FinalizeShouldBeProtected" />
+
Since: PMD 2.0
+ +Priority: Medium (3)
+ +Avoid idempotent operations - they have no effect.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.errorprone.IdempotentOperationsRule
+ +Example(s):
+ +public class Foo {
+ public void bar() {
+ int x = 2;
+ x = x;
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/IdempotentOperations" />
+
Since: PMD 1.02
+ +Priority: Medium (3)
+ +There is no need to import a type that lives in the same package.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.errorprone.ImportFromSamePackageRule
+ +Example(s):
+ +package foo;
+
+import foo.Buz; // no need for this
+import foo.*; // or this
+
+public class Bar{}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/ImportFromSamePackage" />
+
Since: PMD 2.0
+ +Priority: Medium Low (4)
+ +Avoid instantiating an object just to call getClass() on it; use the .class public member instead.
+ +This rule is defined by the following XPath expression:
+//PrimarySuffix
+ [@Image='getClass']
+ [parent::PrimaryExpression
+ [PrimaryPrefix/AllocationExpression]
+ [count(PrimarySuffix) = 2]
+ ]
+
Example(s):
+ +// replace this
+Class c = new String().getClass();
+
+// with this:
+Class c = String.class;
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/InstantiationToGetClass" />
+
Since: PMD 5.5.0
+ +Priority: Low (5)
+ +Check for messages in slf4j and log4j2 (since 6.19.0) loggers with non matching number of arguments and placeholders.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.errorprone.InvalidLogMessageFormatRule
+ +Example(s):
+ +LOGGER.error("forget the arg {}");
+LOGGER.error("too many args {}", "arg1", "arg2");
+LOGGER.error("param {}", "arg1", new IllegalStateException("arg")); //The exception is shown separately, so is correct.
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/InvalidLogMessageFormat" />
+
Deprecated
+ +This rule has been renamed. Use instead: InvalidLogMessageFormat
+ +Deprecated
+ +Since: PMD 5.5.0
+ +Priority: Low (5)
+ +Check for messages in slf4j and log4j2 (since 6.19.0) loggers with non matching number of arguments and placeholders.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.errorprone.InvalidLogMessageFormatRule
+ +Example(s):
+ +LOGGER.error("forget the arg {}");
+LOGGER.error("too many args {}", "arg1", "arg2");
+LOGGER.error("param {}", "arg1", new IllegalStateException("arg")); //The exception is shown separately, so is correct.
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/InvalidSlf4jMessageFormat" />
+
Since: PMD 1.0
+ +Priority: Medium (3)
+ +Avoid jumbled loop incrementers - its usually a mistake, and is confusing even if intentional.
+ +This rule is defined by the following XPath expression:
+//ForStatement
+ [
+ ForUpdate/StatementExpressionList/StatementExpression/PostfixExpression/PrimaryExpression/PrimaryPrefix/Name/@Image
+ =
+ ancestor::ForStatement/ForInit//VariableDeclaratorId/@Name
+ ]
+
Example(s):
+ +public class JumbledIncrementerRule1 {
+ public void foo() {
+ for (int i = 0; i < 10; i++) { // only references 'i'
+ for (int k = 0; k < 20; i++) { // references both 'i' and 'k'
+ System.out.println("Hello");
+ }
+ }
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/JumbledIncrementer" />
+
Since: PMD 1.0
+ +Priority: Medium (3)
+ +In JUnit 3, the setUp method is used to set up all data entities required in running tests. +The tearDown method is used to clean up all data entities required in running tests. +You should not misspell method name if you want your test to set up and clean up everything correctly.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.errorprone.JUnitSpellingRule
+ +Example(s):
+ +import junit.framework.*;
+
+public class Foo extends TestCase {
+ public void setup() {} // oops, should be setUp
+ public void TearDown() {} // oops, should be tearDown
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/JUnitSpelling" />
+
Since: PMD 1.0
+ +Priority: Medium (3)
+ +The suite() method in a JUnit test needs to be both public and static.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.errorprone.JUnitStaticSuiteRule
+ +Example(s):
+ +import junit.framework.*;
+
+public class Foo extends TestCase {
+ public void suite() {} // oops, should be static
+ private static void suite() {} // oops, should be public
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/JUnitStaticSuite" />
+
Deprecated
+ +Since: PMD 2.0
+ +Priority: Medium High (2)
+ +In most cases, the Logger reference can be declared as static and final.
+ +This rule is deprecated and will be removed with PMD 7.0.0.
+The rule is replaced by ProperLogger
.
This rule is defined by the following XPath expression:
+//VariableDeclarator
+ [parent::FieldDeclaration]
+ [../Type/ReferenceType
+ /ClassOrInterfaceType[@Image='Logger']
+ and
+ (..[@Final= false()] or ..[@Static = false()] ) ]
+
Example(s):
+ +public class Foo{
+ Logger log = Logger.getLogger(Foo.class.getName()); // not recommended
+
+ static final Logger log = Logger.getLogger(Foo.class.getName()); // preferred approach
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/LoggerIsNotStaticFinal" />
+
Since: PMD 1.5
+ +Priority: Medium (3)
+ +Non-constructor methods should not have the same name as the enclosing class.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.errorprone.MethodWithSameNameAsEnclosingClassRule
+ +Example(s):
+ +public class MyClass {
+
+ public MyClass() {} // this is OK because it is a constructor
+
+ public void MyClass() {} // this is bad because it is a method
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/MethodWithSameNameAsEnclosingClass" />
+
Since: PMD 3.5
+ +Priority: Medium (3)
+ +The null check here is misplaced. If the variable is null a NullPointerException will be thrown. +Either the check is useless (the variable will never be "null") or it is incorrect.
+ +This rule is defined by the following XPath expression:
+//ConditionalAndExpression
+ /EqualityExpression
+ [@Image = '!=']
+ (: one side is null :)
+ [PrimaryExpression/PrimaryPrefix/Literal/NullLiteral]
+ (: other side checks for the variable used somewhere in the first child of conditional and expression :)
+ [some $var in preceding-sibling::PrimaryExpression//Name
+ [not(ancestor::ConditionalOrExpression/EqualityExpression[@Image = '=='])]
+ /@Image
+ satisfies starts-with($var, concat(PrimaryExpression/PrimaryPrefix/Name/@Image, '.'))]
+ /PrimaryExpression/PrimaryPrefix/Name
+|
+//ConditionalOrExpression
+ /EqualityExpression
+ [@Image = '==']
+ (: one side is null :)
+ [PrimaryExpression/PrimaryPrefix/Literal/NullLiteral]
+ (: other side checks for the variable used somewhere in the first child of conditional or expression :)
+ [some $var in preceding-sibling::PrimaryExpression//Name
+ [not(ancestor::ConditionalAndExpression/EqualityExpression[@Image = '!='])]
+ /@Image
+ satisfies starts-with($var, concat(PrimaryExpression/PrimaryPrefix/Name/@Image, '.'))]
+ /PrimaryExpression/PrimaryPrefix/Name
+
Example(s):
+ +public class Foo {
+ void bar() {
+ if (a.equals(baz) && a != null) {} // a could be null, misplaced null check
+
+ if (a != null && a.equals(baz)) {} // correct null check
+ }
+}
+
public class Foo {
+ void bar() {
+ if (a.equals(baz) || a == null) {} // a could be null, misplaced null check
+
+ if (a == null || a.equals(baz)) {} // correct null check
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/MisplacedNullCheck" />
+
Since: PMD 3.0
+ +Priority: Medium (3)
+ +Switch statements without break or return statements for each case option +may indicate problematic behaviour. Empty cases are ignored as these indicate an intentional fall-through.
+ +This rule is defined by the following XPath expression:
+//SwitchStatement
+[(count(.//BreakStatement)
+ + count(BlockStatement//Statement/ReturnStatement)
+ + count(BlockStatement//Statement/ContinueStatement)
+ + count(BlockStatement//Statement/ThrowStatement)
+ + count(BlockStatement//Statement/IfStatement[@Else= true() and Statement[2][ReturnStatement|ContinueStatement|ThrowStatement]]/Statement[1][ReturnStatement|ContinueStatement|ThrowStatement])
+ + count(SwitchLabel[ following-sibling::node()[1][self::SwitchLabel] ])
+ + count(SwitchLabel[count(following-sibling::node()) = 0])
+ < count (SwitchLabel))]
+
Example(s):
+ +public void bar(int status) {
+ switch(status) {
+ case CANCELLED:
+ doCancelled();
+ // break; hm, should this be commented out?
+ case NEW:
+ doNew();
+ // is this really a fall-through?
+ case REMOVED:
+ doRemoved();
+ // what happens if you add another case after this one?
+ case OTHER: // empty case - this is interpreted as an intentional fall-through
+ case ERROR:
+ doErrorHandling();
+ break;
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/MissingBreakInSwitch" />
+
Since: PMD 3.0
+ +Priority: Medium (3)
+ +Serializable classes should provide a serialVersionUID field. +The serialVersionUID field is also needed for abstract base classes. Each individual class in the inheritance +chain needs an own serialVersionUID field. See also Should an abstract class have a serialVersionUID.
+ +This rule is defined by the following XPath expression:
+//ClassOrInterfaceDeclaration
+ [@Interface = false()]
+ [count(ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration
+ /FieldDeclaration/VariableDeclarator/VariableDeclaratorId[@Name='serialVersionUID']) = 0]
+ [(ImplementsList | ExtendsList)/ClassOrInterfaceType[pmd-java:typeIs('java.io.Serializable')]]
+
Example(s):
+ +public class Foo implements java.io.Serializable {
+ String name;
+ // Define serialization id to avoid serialization related bugs
+ // i.e., public static final long serialVersionUID = 4328743;
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/MissingSerialVersionUID" />
+
Since: PMD 3.0
+ +Priority: Medium (3)
+ +A class that has private constructors and does not have any static methods or fields cannot be used.
+ +When one of the private constructors is annotated with one of the annotations, then the class is not considered
+non-instantiatable anymore and no violation will be reported.
+See the property annotations
.
This rule is defined by the following XPath expression:
+//ClassOrInterfaceDeclaration[@Nested= false()]
+[
+ (
+ (: at least one constructor :)
+ ./ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/ConstructorDeclaration
+ and
+ (: only private constructors :)count(./ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/ConstructorDeclaration) = count(./ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/ConstructorDeclaration[@Private= true()])
+ and
+ (: all constructors must not be annotated :)
+ (every $x in $annotations satisfies
+ not(./ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/ConstructorDeclaration/
+ ../Annotation/MarkerAnnotation/Name[pmd-java:typeIs($x)]))
+ )
+ and
+ (: no static methods :)not(.//MethodDeclaration[@Static= true()])
+ and
+ (: no (public, package-private, protected) static fields :)not(.//FieldDeclaration[@Private= false()][@Static= true()])
+ and
+ (: no nested classes, that are public and static, and have no constructors at all or a public constructor :)
+ (: and have a method returning the outer class type :)
+ (: or the inner class extends the outer class :)not(.//ClassOrInterfaceDeclaration[@Nested= true()]
+ [@Public= true()]
+ [@Static= true()]
+ [not(./ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/ConstructorDeclaration) or ./ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/ConstructorDeclaration[@Public= true()]]
+ [(./ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/MethodDeclaration
+ [@Public= true()]
+ [./ResultType/Type/ReferenceType/ClassOrInterfaceType
+ [@Image = //ClassOrInterfaceDeclaration[@Nested= false()]/@SimpleName]
+ ]
+ ) or (
+ ./ExtendsList/ClassOrInterfaceType[@Image = //ClassOrInterfaceDeclaration[@Nested=false()]/@SimpleName]
+ )]
+ )
+]
+
Example(s):
+ +// This class is unusable, since it cannot be
+// instantiated (private constructor),
+// and no static method can be called.
+
+public class Foo {
+ private Foo() {}
+ void foo() {}
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
annotations | +org.springframework.beans.factory.annotation.Autowired , javax.inject.Inject | +If a constructor is annotated with one of these annotations, then the class is ignored. | +yes. Delimiter is ‘,’. | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/errorprone.xml/MissingStaticMethodInNonInstantiatableClass" />
+
Use this rule and customize it:
+<rule ref="category/java/errorprone.xml/MissingStaticMethodInNonInstantiatableClass">
+ <properties>
+ <property name="annotations" value="org.springframework.beans.factory.annotation.Autowired, javax.inject.Inject" />
+ </properties>
+</rule>
+
Since: PMD 2.0
+ +Priority: Medium High (2)
+ +Normally only one logger is used in each class. This rule supports slf4j, log4j, Java Util Logging and +log4j2 (since 6.19.0).
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.errorprone.MoreThanOneLoggerRule
+ +Example(s):
+ +public class Foo {
+ Logger log = Logger.getLogger(Foo.class.getName());
+ // It is very rare to see two loggers on a class, normally
+ // log information is multiplexed by levels
+ Logger log2= Logger.getLogger(Foo.class.getName());
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/MoreThanOneLogger" />
+
Since: PMD 1.5
+ +Priority: Medium (3)
+ +A non-case label (e.g. a named break/continue label) was present in a switch statement. +This legal, but confusing. It is easy to mix up the case labels and the non-case labels.
+ +This rule is defined by the following XPath expression:
+//SwitchStatement//BlockStatement/Statement/LabeledStatement
+
Example(s):
+ +public class Foo {
+ void bar(int a) {
+ switch (a) {
+ case 1:
+ // do something
+ break;
+ mylabel: // this is legal, but confusing!
+ break;
+ default:
+ break;
+ }
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/NonCaseLabelInSwitchStatement" />
+
Since: PMD 1.5
+ +Priority: Medium (3)
+ +A non-static initializer block will be called any time a constructor is invoked (just prior to +invoking the constructor). While this is a valid language construct, it is rarely used and is +confusing.
+ +This rule is defined by the following XPath expression:
+//Initializer[@Static=false()][not(ancestor::*[3][self::AllocationExpression or self::EnumConstant])]
+
Example(s):
+ +public class MyClass {
+ // this block gets run before any call to a constructor
+ {
+ System.out.println("I am about to construct myself");
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/NonStaticInitializer" />
+
Since: PMD 1.02
+ +Priority: Medium (3)
+ +Assigning a "null" to a variable (outside of its declaration) is usually bad form. Sometimes, this type +of assignment is an indication that the programmer doesn’t completely understand what is going on in the code.
+ +NOTE: This sort of assignment may used in some cases to dereference objects and encourage garbage collection.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.errorprone.NullAssignmentRule
+ +Example(s):
+ +public void bar() {
+ Object x = null; // this is OK
+ x = new Object();
+ // big, complex piece of code here
+ x = null; // this is not required
+ // big, complex piece of code here
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/NullAssignment" />
+
Since: PMD 0.4
+ +Priority: Medium (3)
+ +Override both public boolean Object.equals(Object other), and public int Object.hashCode(), or override neither. Even if you are inheriting a hashCode() from a parent class, consider implementing hashCode and explicitly delegating to your superclass.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.errorprone.OverrideBothEqualsAndHashcodeRule
+ +Example(s):
+ +public class Bar { // poor, missing a hashcode() method
+ public boolean equals(Object o) {
+ // do some comparison
+ }
+}
+
+public class Baz { // poor, missing an equals() method
+ public int hashCode() {
+ // return some hash value
+ }
+}
+
+public class Foo { // perfect, both methods provided
+ public boolean equals(Object other) {
+ // do some comparison
+ }
+ public int hashCode() {
+ // return some hash value
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/OverrideBothEqualsAndHashcode" />
+
Since: PMD 1.4
+ +Priority: Medium High (2)
+ +Object clone() should be implemented with super.clone().
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.errorprone.ProperCloneImplementationRule
+ +Example(s):
+ +class Foo{
+ public Object clone(){
+ return new Foo(); // This is bad
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/ProperCloneImplementation" />
+
Since: PMD 3.3
+ +Priority: Medium (3)
+ +A logger should normally be defined private static final and be associated with the correct class.
+private final Log log;
is also allowed for rare cases where loggers need to be passed around,
+with the restriction that the logger needs to be passed into the constructor.
This rule is defined by the following XPath expression:
+//FieldDeclaration
+[Type/ReferenceType/ClassOrInterfaceType[pmd-java:typeIs($loggerClass)]]
+[
+ (: check modifiers :)
+ (@Private = false() or @Final = false())
+ (: check logger name :)
+ or (@Static and VariableDeclarator/VariableDeclaratorId[@Name != $staticLoggerName])
+ or (@Static = false() and VariableDeclarator/VariableDeclaratorId[@Name != $loggerName])
+
+ (: check logger argument type matches class or enum name :)
+ or .//ArgumentList//ClassOrInterfaceType[@Image != ancestor::ClassOrInterfaceDeclaration/@SimpleName]
+ or .//ArgumentList//ClassOrInterfaceType[@Image != ancestor::EnumDeclaration/@SimpleName]
+]
+[not(
+ (: special case - final logger initialized inside constructor :)
+ not(VariableDeclarator/VariableInitializer)
+ and @Static = false()
+ and
+ ancestor::ClassOrInterfaceBody//ConstructorDeclaration//StatementExpression
+ [PrimaryExpression[PrimaryPrefix[@ThisModifier]]/PrimarySuffix[@Image=$loggerName]]
+ [AssignmentOperator[@Image = '=']]
+ [Expression/PrimaryExpression/PrimaryPrefix/Name[@Image = ancestor::ConstructorDeclaration//FormalParameter/VariableDeclaratorId/@Name]]
+ [not(.//AllocationExpression)]
+ )
+]
+
Example(s):
+ +public class Foo {
+
+ private static final Log LOG = LogFactory.getLog(Foo.class); // proper way
+
+ protected Log LOG = LogFactory.getLog(Testclass.class); // wrong approach
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
staticLoggerName | +LOG | +Name of the static Logger variable | +no | +
loggerName | +log | +Name of the Logger instance variable | +no | +
loggerClass | +Log | +Class name of the logger | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/errorprone.xml/ProperLogger" />
+
Use this rule and customize it:
+<rule ref="category/java/errorprone.xml/ProperLogger">
+ <properties>
+ <property name="staticLoggerName" value="LOG" />
+ <property name="loggerName" value="log" />
+ <property name="loggerClass" value="Log" />
+ </properties>
+</rule>
+
Since: PMD 4.2
+ +Priority: High (1)
+ +For any method that returns an array, it is a better to return an empty array rather than a +null reference. This removes the need for null checking all results and avoids inadvertent +NullPointerExceptions.
+ +This rule is defined by the following XPath expression:
+//MethodDeclaration
+[
+(./ResultType/Type[@ArrayType= true()])
+and
+(./Block/BlockStatement/Statement/ReturnStatement/Expression/PrimaryExpression/PrimaryPrefix/Literal/NullLiteral)
+]
+
Example(s):
+ +public class Example {
+ // Not a good idea...
+ public int[] badBehavior() {
+ // ...
+ return null;
+ }
+
+ // Good behavior
+ public String[] bonnePratique() {
+ //...
+ return new String[0];
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/ReturnEmptyArrayRatherThanNull" />
+
Since: PMD 1.05
+ +Priority: Medium (3)
+ +Avoid returning from a finally block, this can discard exceptions.
+ +This rule is defined by the following XPath expression:
+//FinallyStatement//ReturnStatement except //FinallyStatement//(MethodDeclaration|LambdaExpression)//ReturnStatement
+
Example(s):
+ +public class Bar {
+ public String foo() {
+ try {
+ throw new Exception( "My Exception" );
+ } catch (Exception e) {
+ throw e;
+ } finally {
+ return "A. O. K."; // return not recommended here
+ }
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/ReturnFromFinallyBlock" />
+
Since: PMD 2.0
+ +Priority: Medium (3)
+ +Be sure to specify a Locale when creating SimpleDateFormat instances to ensure that locale-appropriate +formatting is used.
+ +This rule is defined by the following XPath expression:
+//AllocationExpression
+ [ClassOrInterfaceType[@Image='SimpleDateFormat']]
+ [Arguments[@Size=1]]
+
Example(s):
+ +public class Foo {
+ // Should specify Locale.US (or whatever)
+ private SimpleDateFormat sdf = new SimpleDateFormat("pattern");
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/SimpleDateFormatNeedsLocale" />
+
Since: PMD 5.4
+ +Priority: Medium High (2)
+ +Some classes contain overloaded getInstance. The problem with overloaded getInstance methods +is that the instance created using the overloaded method is not cached and so, +for each call and new objects will be created for every invocation.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.errorprone.SingleMethodSingletonRule
+ +Example(s):
+ +public class Singleton {
+
+ private static Singleton singleton = new Singleton( );
+
+ private Singleton(){ }
+
+ public static Singleton getInstance( ) {
+ return singleton;
+ }
+
+ public static Singleton getInstance(Object obj){
+ Singleton singleton = (Singleton) obj;
+ return singleton; //violation
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/SingleMethodSingleton" />
+
Since: PMD 5.4
+ +Priority: Medium High (2)
+ +Some classes contain overloaded getInstance. The problem with overloaded getInstance methods +is that the instance created using the overloaded method is not cached and so, +for each call and new objects will be created for every invocation.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.errorprone.SingletonClassReturningNewInstanceRule
+ +Example(s):
+ +class Singleton {
+ private static Singleton instance = null;
+ public static Singleton getInstance() {
+ synchronized(Singleton.class) {
+ return new Singleton();
+ }
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/SingletonClassReturningNewInstance" />
+
Since: PMD 4.1
+ +Priority: Medium (3)
+ +According to the J2EE specification, an EJB should not have any static fields +with write access. However, static read-only fields are allowed. This ensures proper +behavior especially when instances are distributed by the container on several JREs.
+ +This rule is defined by the following XPath expression:
+//ClassOrInterfaceDeclaration[
+ (
+ (./ImplementsList/ClassOrInterfaceType[ends-with(@Image,'SessionBean')])
+ or
+ (./ImplementsList/ClassOrInterfaceType[ends-with(@Image,'EJBHome')])
+ or
+ (./ImplementsList/ClassOrInterfaceType[ends-with(@Image,'EJBLocalObject')])
+ or
+ (./ImplementsList/ClassOrInterfaceType[ends-with(@Image,'EJBLocalHome')])
+ or
+ (./ExtendsList/ClassOrInterfaceType[ends-with(@Image,'EJBObject')])
+ )
+ and
+ (./ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration[
+ (./FieldDeclaration[@Static = true()])
+ and
+ (./FieldDeclaration[@Final = false()])
+ ])
+]
+
Example(s):
+ +public class SomeEJB extends EJBObject implements EJBLocalHome {
+
+ private static int CountA; // poor, field can be edited
+
+ private static final int CountB; // preferred, read-only access
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/StaticEJBFieldShouldBeFinal" />
+
Since: PMD 3.9
+ +Priority: Medium Low (4)
+ +Individual character values provided as initialization arguments will be converted into integers. +This can lead to internal buffer sizes that are larger than expected. Some examples:
+ +new StringBuffer() // 16
+new StringBuffer(6) // 6
+new StringBuffer("hello world") // 11 + 16 = 27
+new StringBuffer('A') // chr(A) = 65
+new StringBuffer("A") // 1 + 16 = 17
+
+new StringBuilder() // 16
+new StringBuilder(6) // 6
+new StringBuilder("hello world") // 11 + 16 = 27
+new StringBuilder('C') // chr(C) = 67
+new StringBuilder("A") // 1 + 16 = 17
+
This rule is defined by the following XPath expression:
+//AllocationExpression/ClassOrInterfaceType
+[@Image='StringBuffer' or @Image='StringBuilder']
+/../Arguments/ArgumentList/Expression/PrimaryExpression
+/PrimaryPrefix/
+Literal
+ [starts-with(@Image, "'")]
+ [ends-with(@Image, "'")]
+
Example(s):
+ +// misleading instantiation, these buffers
+// are actually sized to 99 characters long
+StringBuffer sb1 = new StringBuffer('c');
+StringBuilder sb2 = new StringBuilder('c');
+
+// in these forms, just single characters are allocated
+StringBuffer sb3 = new StringBuffer("c");
+StringBuilder sb4 = new StringBuilder("c");
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/StringBufferInstantiationWithChar" />
+
Since: PMD 2.0
+ +Priority: Medium High (2)
+ +The method name and parameter number are suspiciously close to Object.equals
, which can denote an
+intention to override it. However, the method does not override Object.equals
, but overloads it instead.
+Overloading Object.equals
method is confusing for other programmers, error-prone and hard to maintain,
+especially when using inheritance, because @Override
annotations used in subclasses can provide a false
+sense of security. For more information on Object.equals
method, see Effective Java, 3rd Edition,
+Item 10: Obey the general contract when overriding equals.
This rule is defined by the following XPath expression:
+//MethodDeclaration[@Name = 'equals']
+[
+ (@Arity = 1
+ and not (MethodDeclarator/FormalParameters/FormalParameter/Type/ReferenceType/ClassOrInterfaceType
+ [@Image = 'Object' or @Image = 'java.lang.Object'])
+ or not (ResultType/Type/PrimitiveType[@Image = 'boolean'])
+ ) or (
+ @Arity = 2
+ and ResultType/Type/PrimitiveType[@Image = 'boolean']
+ and MethodDeclarator/FormalParameters//ClassOrInterfaceType[@Image = 'Object' or @Image = 'java.lang.Object']
+ and not(../Annotation/MarkerAnnotation/Name[@Image='Override'])
+ )
+]
+| //MethodDeclaration[@Name = 'equal']
+[
+ @Arity = 1
+ and MethodDeclarator/FormalParameters/FormalParameter/Type/ReferenceType/ClassOrInterfaceType
+ [@Image = 'Object' or @Image = 'java.lang.Object']
+]
+
Example(s):
+ +public class Foo {
+ public int equals(Object o) {
+ // oops, this probably was supposed to be boolean equals
+ }
+ public boolean equals(String s) {
+ // oops, this probably was supposed to be equals(Object)
+ }
+ public boolean equals(Object o1, Object o2) {
+ // oops, this probably was supposed to be equals(Object)
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/SuspiciousEqualsMethodName" />
+
Since: PMD 1.5
+ +Priority: Medium (3)
+ +The method name and return type are suspiciously close to hashCode(), which may denote an intention +to override the hashCode() method.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.errorprone.SuspiciousHashcodeMethodNameRule
+ +Example(s):
+ +public class Foo {
+ public int hashcode() { // oops, this probably was supposed to be 'hashCode'
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/SuspiciousHashcodeMethodName" />
+
Since: PMD 1.5
+ +Priority: Medium (3)
+ +A suspicious octal escape sequence was found inside a String literal. +The Java language specification (section 3.10.6) says an octal +escape sequence inside a literal String shall consist of a backslash +followed by:
+ +OctalDigit | OctalDigit OctalDigit | ZeroToThree OctalDigit OctalDigit
+
Any octal escape sequence followed by non-octal digits can be confusing, +e.g. "\038" is interpreted as the octal escape sequence "\03" followed by +the literal character "8".
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.errorprone.SuspiciousOctalEscapeRule
+ +Example(s):
+ +public void foo() {
+ // interpreted as octal 12, followed by character '8'
+ System.out.println("suspicious: \128");
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/SuspiciousOctalEscape" />
+
Since: PMD 3.0
+ +Priority: Medium (3)
+ +Test classes end with the suffix Test. Having a non-test class with that name is not a good practice, +since most people will assume it is a test case. Test classes have test methods named testXXX.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.errorprone.TestClassWithoutTestCasesRule
+ +Example(s):
+ +//Consider changing the name of the class if it is not a test
+//Consider adding test methods if it is a test
+public class CarTest {
+ public static void main(String[] args) {
+ // do something
+ }
+ // code
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/TestClassWithoutTestCases" />
+
Since: PMD 1.5
+ +Priority: Medium (3)
+ +Do not use "if" statements whose conditionals are always true or always false.
+ +This rule is defined by the following XPath expression:
+//IfStatement/Expression
+ [count(PrimaryExpression)=1]
+ /PrimaryExpression/PrimaryPrefix/Literal/BooleanLiteral
+
Example(s):
+ +public class Foo {
+ public void close() {
+ if (true) { // fixed conditional, not recommended
+ // ...
+ }
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/UnconditionalIfStatement" />
+
Since: PMD 3.0
+ +Priority: Medium (3)
+ +A JUnit test assertion with a boolean literal is unnecessary since it always will evaluate to the same thing. +Consider using flow control (in case of assertTrue(false) or similar) or simply removing +statements like assertTrue(true) and assertFalse(false). If you just want a test to halt after finding +an error, use the fail() method and provide an indication message of why it did.
+ +This rule is defined by the following XPath expression:
+//ClassOrInterfaceDeclaration[
+ pmd-java:typeIs('junit.framework.TestCase')
+ or .//MarkerAnnotation/Name[
+ pmd-java:typeIs('org.junit.Test')
+ or pmd-java:typeIs('org.junit.jupiter.api.Test')
+ or pmd-java:typeIs('org.junit.jupiter.api.RepeatedTest')
+ or pmd-java:typeIs('org.junit.jupiter.api.TestFactory')
+ or pmd-java:typeIs('org.junit.jupiter.api.TestTemplate')
+ or pmd-java:typeIs('org.junit.jupiter.params.ParameterizedTest')
+ ]
+ ]
+//StatementExpression
+[
+ PrimaryExpression/PrimaryPrefix/Name[@Image='assertTrue' or @Image='assertFalse']
+ and
+ PrimaryExpression/PrimarySuffix/Arguments/ArgumentList/Expression[
+ PrimaryExpression/PrimaryPrefix/Literal/BooleanLiteral
+ or
+ UnaryExpressionNotPlusMinus[@Image='!']
+ /PrimaryExpression/PrimaryPrefix[Literal/BooleanLiteral or Name[count(../../*)=1]]
+ ]
+]
+
Example(s):
+ +public class SimpleTest extends TestCase {
+ public void testX() {
+ assertTrue(true); // serves no real purpose
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/UnnecessaryBooleanAssertion" />
+
Since: PMD 3.3
+ +Priority: Medium (3)
+ +Using equalsIgnoreCase() is faster than using toUpperCase/toLowerCase().equals()
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.errorprone.UnnecessaryCaseChangeRule
+ +Example(s):
+ +boolean answer1 = buz.toUpperCase().equals("baz"); // should be buz.equalsIgnoreCase("baz")
+
+boolean answer2 = buz.toUpperCase().equalsIgnoreCase("baz"); // another unnecessary toUpperCase()
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/UnnecessaryCaseChange" />
+
Since: PMD 0.1
+ +Priority: Medium (3)
+ +Avoid the use temporary objects when converting primitives to Strings. Use the static conversion methods +on the wrapper classes instead.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.errorprone.UnnecessaryConversionTemporaryRule
+ +Example(s):
+ +public String convert(int x) {
+ String foo = new Integer(x).toString(); // this wastes an object
+
+ return Integer.toString(x); // preferred approach
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/UnnecessaryConversionTemporary" />
+
Since: PMD 3.5
+ +Priority: Medium (3)
+ +After checking an object reference for null, you should invoke equals() on that object rather than passing it to another object’s equals() method.
+ +This rule is defined by the following XPath expression:
+(//PrimaryPrefix[ends-with(Name/@Image, '.equals') and Name/@Image != 'Arrays.equals'] | //PrimarySuffix[@Image='equals' and not(../PrimaryPrefix/Literal)])
+ /following-sibling::PrimarySuffix/Arguments/ArgumentList/Expression
+ /PrimaryExpression[not(PrimarySuffix)]/PrimaryPrefix
+ /Name[@Image = ./../../../../../../../../../../Expression/ConditionalAndExpression
+ /EqualityExpression[@Image="!=" and not(./preceding-sibling::*) and
+ ./PrimaryExpression/PrimaryPrefix/Literal/NullLiteral]
+ /PrimaryExpression/PrimaryPrefix/Name/@Image]
+
Example(s):
+ +public class Test {
+
+ public String method1() { return "ok";}
+ public String method2() { return null;}
+
+ public void method(String a) {
+ String b;
+ // I don't know it method1() can be "null"
+ // but I know "a" is not null..
+ // I'd better write a.equals(method1())
+
+ if (a!=null && method1().equals(a)) { // will trigger the rule
+ //whatever
+ }
+
+ if (method1().equals(a) && a != null) { // won't trigger the rule
+ //whatever
+ }
+
+ if (a!=null && method1().equals(b)) { // won't trigger the rule
+ //whatever
+ }
+
+ if (a!=null && "LITERAL".equals(a)) { // won't trigger the rule
+ //whatever
+ }
+
+ if (a!=null && !a.equals("go")) { // won't trigger the rule
+ a=method2();
+ if (method1().equals(a)) {
+ //whatever
+ }
+ }
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/UnusedNullCheckInEquals" />
+
Since: PMD 3.2
+ +Priority: Medium (3)
+ +To make sure the full stacktrace is printed out, use the logging statement with two arguments: a String and a Throwable.
+ +This rule is defined by the following XPath expression:
+//CatchStatement/Block/BlockStatement/Statement/StatementExpression
+ /PrimaryExpression
+ [PrimaryPrefix/Name
+ [starts-with(@Image,
+ concat((ancestor::ClassOrInterfaceDeclaration/ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/FieldDeclaration
+ [Type//ClassOrInterfaceType[@Image='Log']]
+ /VariableDeclarator/VariableDeclaratorId/@Name)[1], '.'))
+ ]
+ ]
+ [PrimarySuffix/Arguments[@Size= 1]]
+ [PrimarySuffix/Arguments//Name/@Image = ancestor::CatchStatement/FormalParameter/VariableDeclaratorId/@Name]
+
Example(s):
+ +public class Main {
+ private static final Log _LOG = LogFactory.getLog( Main.class );
+ void bar() {
+ try {
+ } catch( Exception e ) {
+ _LOG.error( e ); //Wrong!
+ } catch( OtherException oe ) {
+ _LOG.error( oe.getMessage(), oe ); //Correct
+ }
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/UseCorrectExceptionLogging" />
+
Since: PMD 4.1
+ +Priority: Medium (3)
+ +Using ‘==’ or ‘!=’ to compare strings only works if intern version is used on both sides. +Use the equals() method instead.
+ +This rule is defined by the following XPath expression:
+//EqualityExpression/PrimaryExpression
+[not(PrimarySuffix)]
+[PrimaryPrefix/Literal
+ [starts-with(@Image, '"')]
+ [ends-with(@Image, '"')]]
+
Example(s):
+ +public boolean test(String s) {
+ if (s == "one") return true; // unreliable
+ if ("two".equals(s)) return true; // better
+ return false;
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/UseEqualsToCompareStrings" />
+
Since: PMD 3.5
+ +Priority: Medium (3)
+ +An operation on an Immutable object (String, BigDecimal or BigInteger) won’t change the object itself +since the result of the operation is a new object. Therefore, ignoring the operation result is an error.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.errorprone.UselessOperationOnImmutableRule
+ +Example(s):
+ +import java.math.*;
+
+class Test {
+ void method1() {
+ BigDecimal bd=new BigDecimal(10);
+ bd.add(new BigDecimal(5)); // this will trigger the rule
+ }
+ void method2() {
+ BigDecimal bd=new BigDecimal(10);
+ bd = bd.add(new BigDecimal(5)); // this won't trigger the rule
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/UselessOperationOnImmutable" />
+
Since: PMD 2.0
+ +Priority: Medium (3)
+ +When doing String::toLowerCase()/toUpperCase()
conversions, use an explicit locale argument to specify the case transformation rules.
Using String::toLowerCase()
without arguments implicitly uses Locale::getDefault()
.
+The problem is that the default locale depends on the current JVM setup (and usually on the system in which it is running).
+Using the system default may be exactly what you want (e.g. if you are manipulating strings you got through standard input),
+but it may as well not be the case (e.g. if you are getting the string over the network or a file, and the encoding is well-defined
+and independent of the environment). In the latter case, using the default locale makes the case transformation brittle, as
+it may yield unexpected results on a machine whose locale has other case translation rules. For example, in Turkish, the
+uppercase form of i
is İ
(U+0130, not ASCII) and not I
(U+0049) as in English.
The rule is intended to force developers to think about locales when dealing with strings. By taking a conscious decision about +the choice of locale at the time of writing, you reduce the risk of surprising behaviour down the line, and communicate your intent +to future readers.
+ +This rule is defined by the following XPath expression:
+//PrimaryExpression
+[
+PrimaryPrefix
+[Name[ends-with(@Image, 'toLowerCase') or ends-with(@Image, 'toUpperCase')]]
+[following-sibling::PrimarySuffix[position() = 1]/Arguments[@Size=0]]
+
+or
+
+PrimarySuffix
+[ends-with(@Image, 'toLowerCase') or ends-with(@Image, 'toUpperCase')]
+[following-sibling::PrimarySuffix[position() = 1]/Arguments[@Size=0]]
+]
+[not(PrimaryPrefix/Name[ends-with(@Image, 'toHexString')])]
+
Example(s):
+ +// violation - implicitly system-dependent conversion
+if (x.toLowerCase().equals("list")) {}
+
+// The above will not match "LIST" on a system with a Turkish locale.
+// It could be replaced with
+if (x.toLowerCase(Locale.US).equals("list")) { }
+// or simply
+if (x.equalsIgnoreCase("list")) { }
+
+// ok - system independent conversion
+String z = a.toLowerCase(Locale.ROOT);
+
+// ok - explicit system-dependent conversion
+String z2 = a.toLowerCase(Locale.getDefault());
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/UseLocaleWithCaseConversions" />
+
Since: PMD 3.7
+ +Priority: Medium (3)
+ +In J2EE, the getClassLoader() method might not work as expected. Use +Thread.currentThread().getContextClassLoader() instead.
+ +This rule is defined by the following XPath expression:
+//PrimarySuffix[@Image='getClassLoader'] | //PrimaryPrefix[ends-with(Name/@Image, '.getClassLoader')]
+
Example(s):
+ +public class Foo {
+ ClassLoader cl = Bar.class.getClassLoader();
+}
+
Use this rule by referencing it:
+<rule ref="category/java/errorprone.xml/UseProperClassLoader" />
+
Since: PMD 3.0
+ +Priority: Medium (3)
+ +Method-level synchronization can cause problems when new code is added to the method. +Block-level synchronization helps to ensure that only the code that needs synchronization +gets it.
+ +This rule is defined by the following XPath expression:
+//MethodDeclaration[@Synchronized = true()]
+
Example(s):
+ +public class Foo {
+ // Try to avoid this:
+ synchronized void foo() {
+ // code, that doesn't need synchronization
+ // ...
+ // code, that requires synchronization
+ if (!sharedData.has("bar")) {
+ sharedData.add("bar");
+ }
+ // more code, that doesn't need synchronization
+ // ...
+ }
+ // Prefer this:
+ void bar() {
+ // code, that doesn't need synchronization
+ // ...
+ synchronized(this) {
+ if (!sharedData.has("bar")) {
+ sharedData.add("bar");
+ }
+ }
+ // more code, that doesn't need synchronization
+ // ...
+ }
+
+ // Try to avoid this for static methods:
+ static synchronized void fooStatic() {
+ }
+
+ // Prefer this:
+ static void barStatic() {
+ // code, that doesn't need synchronization
+ // ...
+ synchronized(Foo.class) {
+ // code, that requires synchronization
+ }
+ // more code, that doesn't need synchronization
+ // ...
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/multithreading.xml/AvoidSynchronizedAtMethodLevel" />
+
Since: PMD 3.6
+ +Priority: Medium (3)
+ +Avoid using java.lang.ThreadGroup; although it is intended to be used in a threaded environment +it contains methods that are not thread-safe.
+ +This rule is defined by the following XPath expression:
+//AllocationExpression/ClassOrInterfaceType[pmd-java:typeIs('java.lang.ThreadGroup')]|
+//PrimarySuffix[contains(@Image, 'getThreadGroup')]
+
Example(s):
+ +public class Bar {
+ void buz() {
+ ThreadGroup tg = new ThreadGroup("My threadgroup");
+ tg = new ThreadGroup(tg, "my thread group");
+ tg = Thread.currentThread().getThreadGroup();
+ tg = System.getSecurityManager().getThreadGroup();
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/multithreading.xml/AvoidThreadGroup" />
+
Since: PMD 4.1
+ +Priority: Medium High (2)
+ +Use of the keyword ‘volatile’ is generally used to fine tune a Java application, and therefore, requires +a good expertise of the Java Memory Model. Moreover, its range of action is somewhat misknown. Therefore, +the volatile keyword should not be used for maintenance purpose and portability.
+ +This rule is defined by the following XPath expression:
+//FieldDeclaration[@Volatile = true()]
+
Example(s):
+ +public class ThrDeux {
+ private volatile String var1; // not suggested
+ private String var2; // preferred
+}
+
Use this rule by referencing it:
+<rule ref="category/java/multithreading.xml/AvoidUsingVolatile" />
+
Since: PMD 4.1
+ +Priority: Medium (3)
+ +The J2EE specification explicitly forbids the use of threads. Threads are resources, that should be managed and monitored by the J2EE server. +If the application creates threads on its own or uses own custom thread pools, then these threads are not managed, which could lead to resource exhaustion. +Also EJB’s might be moved between machines in a cluster and only managed resources can be moved along.
+ +This rule is defined by the following XPath expression:
+//ClassOrInterfaceType[pmd-java:typeIs('java.lang.Thread') or pmd-java:typeIs('java.util.concurrent.ExecutorService')]
+|
+//StatementExpression/PrimaryExpression/PrimaryPrefix/Name[pmd-java:typeIs('java.util.concurrent.Executors') or pmd-java:typeIs('java.util.concurrent.ExecutorService')]
+
Example(s):
+ +// This is not allowed
+public class UsingThread extends Thread {
+
+}
+
+// Neither this,
+public class UsingExecutorService {
+
+ public void methodX() {
+ ExecutorService executorService = Executors.newFixedThreadPool(5);
+ }
+}
+
+// Nor this,
+public class Example implements ExecutorService {
+
+}
+
+// Nor this,
+public class Example extends AbstractExecutorService {
+
+}
+
+// Nor this
+public class UsingExecutors {
+
+ public void methodX() {
+ Executors.newSingleThreadExecutor().submit(() -> System.out.println("Hello!"));
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/multithreading.xml/DoNotUseThreads" />
+
Since: PMD 4.3
+ +Priority: Medium Low (4)
+ +Explicitly calling Thread.run() method will execute in the caller’s thread of control. Instead, call Thread.start() for the intended behavior.
+ +This rule is defined by the following XPath expression:
+//StatementExpression/PrimaryExpression
+[
+ PrimaryPrefix
+ [pmd-java:typeIs('java.lang.Thread')]
+ [
+ ./Name[ends-with(@Image, '.run') or @Image = 'run']
+ or
+ ./AllocationExpression/ClassOrInterfaceType[pmd-java:typeIs('java.lang.Thread')]
+ and ../PrimarySuffix[@Image = 'run']
+ ]
+]
+
Example(s):
+ +Thread t = new Thread();
+t.run(); // use t.start() instead
+new Thread().run(); // same violation
+
Use this rule by referencing it:
+<rule ref="category/java/multithreading.xml/DontCallThreadRun" />
+
Since: PMD 1.04
+ +Priority: High (1)
+ +Partially created objects can be returned by the Double Checked Locking pattern when used in Java. +An optimizing JRE may assign a reference to the baz variable before it calls the constructor of the object the +reference points to.
+ +Note: With Java 5, you can make Double checked locking work, if you declare the variable to be volatile
.
For more details refer to: http://www.javaworld.com/javaworld/jw-02-2001/jw-0209-double.html +or http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.multithreading.DoubleCheckedLockingRule
+ +Example(s):
+ +public class Foo {
+ /*volatile */ Object baz = null; // fix for Java5 and later: volatile
+ Object bar() {
+ if (baz == null) { // baz may be non-null yet not fully created
+ synchronized(this) {
+ if (baz == null) {
+ baz = new Object();
+ }
+ }
+ }
+ return baz;
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/multithreading.xml/DoubleCheckedLocking" />
+
Since: PMD 3.4
+ +Priority: Medium (3)
+ +Non-thread safe singletons can result in bad state changes. Eliminate +static singletons if possible by instantiating the object directly. Static +singletons are usually not needed as only a single instance exists anyway. +Other possible fixes are to synchronize the entire method or to use an +initialize-on-demand holder class.
+ +Refrain from using the double-checked locking pattern. The Java Memory Model doesn’t
+guarantee it to work unless the variable is declared as volatile
, adding an uneeded
+performance penalty. Reference
See Effective Java, item 48.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.multithreading.NonThreadSafeSingletonRule
+ +Example(s):
+ +private static Foo foo = null;
+
+//multiple simultaneous callers may see partially initialized objects
+public static Foo getFoo() {
+ if (foo==null) {
+ foo = new Foo();
+ }
+ return foo;
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
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 with the default properties by just referencing it:
+<rule ref="category/java/multithreading.xml/NonThreadSafeSingleton" />
+
Use this rule and customize it:
+<rule ref="category/java/multithreading.xml/NonThreadSafeSingleton">
+ <properties>
+ <property name="checkNonStaticMethods" value="true" />
+ <property name="checkNonStaticFields" value="false" />
+ </properties>
+</rule>
+
Deprecated
+ +Since: PMD 3.6
+ +Priority: Medium (3)
+ +SimpleDateFormat instances are not synchronized. Sun recommends using separate format instances +for each thread. If multiple threads must access a static formatter, the formatter must be +synchronized on block level.
+ +This rule has been deprecated in favor of the rule UnsynchronizedStaticFormatter
.
This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.multithreading.UnsynchronizedStaticDateFormatterRule
+ +Example(s):
+ +public class Foo {
+ private static final SimpleDateFormat sdf = new SimpleDateFormat();
+ void bar() {
+ sdf.format(); // poor, no thread-safety
+ }
+ void foo() {
+ synchronized (sdf) { // preferred
+ sdf.format();
+ }
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
allowMethodLevelSynchronization | +false | +If true, method level synchronization is allowed as well as synchronized block. Otherwise only synchronized blocks are allowed. | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/multithreading.xml/UnsynchronizedStaticDateFormatter" />
+
Use this rule and customize it:
+<rule ref="category/java/multithreading.xml/UnsynchronizedStaticDateFormatter">
+ <properties>
+ <property name="allowMethodLevelSynchronization" value="false" />
+ </properties>
+</rule>
+
Since: PMD 6.11.0
+ +Priority: Medium (3)
+ +Instances of java.text.Format
are generally not synchronized.
+Sun recommends using separate format instances for each thread.
+If multiple threads must access a static formatter, the formatter must be
+synchronized on block level.
This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.multithreading.UnsynchronizedStaticFormatterRule
+ +Example(s):
+ +public class Foo {
+ private static final SimpleDateFormat sdf = new SimpleDateFormat();
+ void bar() {
+ sdf.format(); // poor, no thread-safety
+ }
+ void foo() {
+ synchronized (sdf) { // preferred
+ sdf.format();
+ }
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
allowMethodLevelSynchronization | +false | +If true, method level synchronization is allowed as well as synchronized block. Otherwise only synchronized blocks are allowed. | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/multithreading.xml/UnsynchronizedStaticFormatter" />
+
Use this rule and customize it:
+<rule ref="category/java/multithreading.xml/UnsynchronizedStaticFormatter">
+ <properties>
+ <property name="allowMethodLevelSynchronization" value="false" />
+ </properties>
+</rule>
+
Since: PMD 4.2.6
+ +Priority: Medium (3)
+ +Minimum Language Version: Java 1.5
+ +Since Java5 brought a new implementation of the Map designed for multi-threaded access, you can +perform efficient map reads without blocking other threads.
+ +This rule is defined by the following XPath expression:
+//Type[../VariableDeclarator/VariableInitializer//AllocationExpression/ClassOrInterfaceType[@Image != 'ConcurrentHashMap']]
+/ReferenceType/ClassOrInterfaceType[@Image = 'Map']
+
Example(s):
+ +public class ConcurrentApp {
+ public void getMyInstance() {
+ Map map1 = new HashMap(); // fine for single-threaded access
+ Map map2 = new ConcurrentHashMap(); // preferred for use with multiple threads
+
+ // the following case will be ignored by this rule
+ Map map3 = someModule.methodThatReturnMap(); // might be OK, if the returned map is already thread-safe
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/multithreading.xml/UseConcurrentHashMap" />
+
Since: PMD 3.0
+ +Priority: Medium (3)
+ +Thread.notify() awakens a thread monitoring the object. If more than one thread is monitoring, then only +one is chosen. The thread chosen is arbitrary; thus its usually safer to call notifyAll() instead.
+ +This rule is defined by the following XPath expression:
+//StatementExpression/PrimaryExpression
+[PrimarySuffix/Arguments[@Size = 0]]
+[
+ PrimaryPrefix[
+ ./Name[@Image='notify' or ends-with(@Image,'.notify')]
+ or ../PrimarySuffix/@Image='notify'
+ or (./AllocationExpression and ../PrimarySuffix[@Image='notify'])
+ ]
+]
+
Example(s):
+ +void bar() {
+ x.notify();
+ // If many threads are monitoring x, only one (and you won't know which) will be notified.
+ // use instead:
+ x.notifyAll();
+ }
+
Use this rule by referencing it:
+<rule ref="category/java/multithreading.xml/UseNotifyAllInsteadOfNotify" />
+
Since: PMD 4.0
+ +Priority: Medium (3)
+ +The conversion of literals to strings by concatenating them with empty strings is inefficient. +It is much better to use one of the type-specific toString() methods instead.
+ +This rule is defined by the following XPath expression:
+//AdditiveExpression/PrimaryExpression/PrimaryPrefix/Literal[@Image='""']
+
Example(s):
+ +String s = "" + 123; // inefficient
+String t = Integer.toString(456); // preferred approach
+
Use this rule by referencing it:
+<rule ref="category/java/performance.xml/AddEmptyString" />
+
Since: PMD 3.5
+ +Priority: Medium (3)
+ +Avoid concatenating characters as strings in StringBuffer/StringBuilder.append methods.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.performance.AppendCharacterWithCharRule
+ +Example(s):
+ +StringBuffer sb = new StringBuffer();
+sb.append("a"); // avoid this
+
+StringBuffer sb = new StringBuffer();
+sb.append('a'); // use this instead
+
Use this rule by referencing it:
+<rule ref="category/java/performance.xml/AppendCharacterWithChar" />
+
Since: PMD 3.5
+ +Priority: Medium (3)
+ +Instead of manually copying data between two arrays, use the efficient Arrays.copyOf or System.arraycopy method instead.
+ +This rule is defined by the following XPath expression:
+//Statement[(ForStatement or WhileStatement) and
+count(*//AssignmentOperator[@Image = '='])=1
+and
+*/Statement
+[
+./Block/BlockStatement/Statement/StatementExpression/PrimaryExpression
+/PrimaryPrefix/Name/../../PrimarySuffix/Expression
+[(PrimaryExpression or AdditiveExpression) and count
+(.//PrimaryPrefix/Name)=1]//PrimaryPrefix/Name/@Image
+and
+./Block/BlockStatement/Statement/StatementExpression/Expression/PrimaryExpression
+/PrimaryPrefix/Name/../../PrimarySuffix[count
+(..//PrimarySuffix)=1]/Expression[(PrimaryExpression
+or AdditiveExpression) and count(.//PrimaryPrefix/Name)=1]
+//PrimaryPrefix/Name/@Image
+]]
+
Example(s):
+ +public class Test {
+ public void bar() {
+ int[] a = new int[10];
+ int[] b = new int[10];
+ for (int i=0;i<10;i++) {
+ b[i]=a[i];
+ }
+
+ int[] c = new int[10];
+ // this will trigger the rule
+ for (int i=0;i<10;i++) {
+ b[i]=a[c[i]];
+ }
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/performance.xml/AvoidArrayLoops" />
+
Since: PMD 6.25.0
+ +Priority: Medium (3)
+ +Problem: A Calendar is a heavyweight object and expensive to create.
+ +Solution: Use new Date()
, Java 8+ java.time.LocalDateTime.now()
or ZonedDateTime.now()
.
This rule is defined by the following XPath expression:
+//PrimaryPrefix[Name[ends-with(@Image, 'Calendar.getInstance')]] [count(../PrimarySuffix) > 2 and ../PrimarySuffix[last()-1][@Image = 'getTime' or @Image='getTimeInMillis']]
+|
+//MethodDeclaration[not(MethodDeclarator/FormalParameters//ClassOrInterfaceType[pmd-java:typeIs('java.util.Calendar')])]
+ /Block/BlockStatement//PrimaryExpression
+ /PrimaryPrefix/Name
+ [pmd-java:typeIs('java.util.Calendar')]
+ [every $var in @Image satisfies (
+ (ends-with($var, '.getTime') or ends-with($var, '.getTimeInMillis'))
+ and
+ (: ignore if .set* or .add* or .clear is called on the variable :)
+ not(ancestor::Block/BlockStatement//Name[
+ starts-with(@Image, concat((tokenize($var, '\.'), $var)[1], '.set'))
+ or
+ starts-with(@Image, concat((tokenize($var, '\.'), $var)[1], '.add'))
+ or
+ starts-with(@Image, concat((tokenize($var, '\.'), $var)[1], '.clear'))
+ ])
+ )]
+|
+//ClassOrInterfaceType[pmd-java:typeIs('org.joda.time.DateTime') or pmd-java:typeIs('org.joda.time.LocalDateTime')][../Arguments/ArgumentList/Expression/PrimaryExpression/PrimaryPrefix/Name[ends-with(@Image, 'Calendar.getInstance')]]
+
Example(s):
+ +import java.time.LocalDateTime;
+import java.util.Calendar;
+import java.util.Date;
+
+public class DateStuff {
+ private Date bad1() {
+ return Calendar.getInstance().getTime(); // now
+ }
+ private Date good1a() {
+ return new Date(); // now
+ }
+ private LocalDateTime good1b() {
+ return LocalDateTime.now();
+ }
+ private long bad2() {
+ return Calendar.getInstance().getTimeInMillis();
+ }
+ private long good2() {
+ return System.currentTimeMillis();
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/performance.xml/AvoidCalendarDateCreation" />
+
Since: PMD 6.0.0
+ +Priority: High (1)
+ +Minimum Language Version: Java 1.7
+ +The FileInputStream and FileOutputStream classes contains a finalizer method which will cause garbage +collection pauses. +See JDK-8080225 for details.
+ +The FileReader and FileWriter constructors instantiate FileInputStream and FileOutputStream, +again causing garbage collection issues while finalizer methods are called.
+ +Files.newInputStream(Paths.get(fileName))
instead of new FileInputStream(fileName)
.Files.newOutputStream(Paths.get(fileName))
instead of new FileOutputStream(fileName)
.Files.newBufferedReader(Paths.get(fileName))
instead of new FileReader(fileName)
.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:
+//PrimaryPrefix/AllocationExpression/ClassOrInterfaceType[
+ pmd-java:typeIs('java.io.FileInputStream')
+ or pmd-java:typeIs('java.io.FileOutputStream')
+ or pmd-java:typeIs('java.io.FileReader')
+ or pmd-java:typeIs('java.io.FileWriter')
+ ]
+
Example(s):
+ +// these instantiations cause garbage collection pauses, even if properly closed
+
+ FileInputStream fis = new FileInputStream(fileName);
+ FileOutputStream fos = new FileOutputStream(fileName);
+ FileReader fr = new FileReader(fileName);
+ FileWriter fw = new FileWriter(fileName);
+
+ // the following instantiations help prevent Garbage Collection pauses, no finalization
+
+ try(InputStream is = Files.newInputStream(Paths.get(fileName))) {
+ }
+ try(OutputStream os = Files.newOutputStream(Paths.get(fileName))) {
+ }
+ try(BufferedReader br = Files.newBufferedReader(Paths.get(fileName), StandardCharsets.UTF_8)) {
+ }
+ try(BufferedWriter wr = Files.newBufferedWriter(Paths.get(fileName), StandardCharsets.UTF_8)) {
+ }
+
Use this rule by referencing it:
+<rule ref="category/java/performance.xml/AvoidFileStream" />
+
Since: PMD 2.2
+ +Priority: Medium (3)
+ +New objects created within loops should be checked to see if they can created outside them and reused.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.performance.AvoidInstantiatingObjectsInLoopsRule
+ +Example(s):
+ +public class Something {
+ public static void main( String as[] ) {
+ for (int i = 0; i < 10; i++) {
+ Foo f = new Foo(); // Avoid this whenever you can it's really expensive
+ }
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/performance.xml/AvoidInstantiatingObjectsInLoops" />
+
Since: PMD 4.1
+ +Priority: High (1)
+ +Java uses the ‘short’ type to reduce memory usage, not to optimize calculation. In fact, the JVM does not have any +arithmetic capabilities for the short type: the JVM must convert the short into an int, do the proper calculation +and convert the int back to a short. Thus any storage gains found through use of the ‘short’ type may be offset by +adverse impacts on performance.
+ +This rule is defined by the following XPath expression:
+//FieldDeclaration/Type/PrimitiveType[@Image = 'short']
+|
+//ClassOrInterfaceBodyDeclaration[not(Annotation/MarkerAnnotation/Name[pmd-java:typeIs('java.lang.Override')])]
+ /MethodDeclaration/ResultType/Type/PrimitiveType[@Image = 'short']
+|
+//ClassOrInterfaceBodyDeclaration[not(Annotation/MarkerAnnotation/Name[pmd-java:typeIs('java.lang.Override')])]
+ /MethodDeclaration/MethodDeclarator/FormalParameters/FormalParameter/Type/PrimitiveType[@Image = 'short']
+|
+//LocalVariableDeclaration/Type/PrimitiveType[@Image = 'short']
+|
+//AnnotationMethodDeclaration/Type/PrimitiveType[@Image = 'short']
+
Example(s):
+ +public class UsingShort {
+ private short doNotUseShort = 0;
+
+ public UsingShort() {
+ short shouldNotBeUsed = 1;
+ doNotUseShort += shouldNotBeUsed;
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/performance.xml/AvoidUsingShortType" />
+
Since: PMD 3.9
+ +Priority: Medium (3)
+ +Don’t create instances of already existing BigInteger (BigInteger.ZERO, BigInteger.ONE) and +for Java 1.5 onwards, BigInteger.TEN and BigDecimal (BigDecimal.ZERO, BigDecimal.ONE, BigDecimal.TEN)
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.performance.BigIntegerInstantiationRule
+ +Example(s):
+ +BigInteger bi = new BigInteger(1); // reference BigInteger.ONE instead
+BigInteger bi2 = new BigInteger("0"); // reference BigInteger.ZERO instead
+BigInteger bi3 = new BigInteger(0.0); // reference BigInteger.ZERO instead
+BigInteger bi4;
+bi4 = new BigInteger(0); // reference BigInteger.ZERO instead
+
Use this rule by referencing it:
+<rule ref="category/java/performance.xml/BigIntegerInstantiation" />
+
Since: PMD 1.2
+ +Priority: Medium High (2)
+ +Avoid instantiating Boolean objects; you can reference Boolean.TRUE, Boolean.FALSE, or call Boolean.valueOf() instead. +Note that new Boolean() is deprecated since JDK 9 for that reason.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.performance.BooleanInstantiationRule
+ +Example(s):
+ +Boolean bar = new Boolean("true"); // unnecessary creation, just reference Boolean.TRUE;
+Boolean buz = Boolean.valueOf(false); // ...., just reference Boolean.FALSE;
+
Use this rule by referencing it:
+<rule ref="category/java/performance.xml/BooleanInstantiation" />
+
Since: PMD 4.0
+ +Priority: Medium High (2)
+ +Calling new Byte() causes memory allocation that can be avoided by the static Byte.valueOf(). +It makes use of an internal cache that recycles earlier instances making it more memory efficient. +Note that new Byte() is deprecated since JDK 9 for that reason.
+ +This rule is defined by the following XPath expression:
+//AllocationExpression
+[not (ArrayDimsAndInits)
+and ClassOrInterfaceType[pmd-java:typeIs('java.lang.Byte')]]
+
Example(s):
+ +public class Foo {
+ private Byte i = new Byte(0); // change to Byte i = Byte.valueOf(0);
+}
+
Use this rule by referencing it:
+<rule ref="category/java/performance.xml/ByteInstantiation" />
+
Since: PMD 5.1
+ +Priority: Medium (3)
+ +Consecutive calls to StringBuffer/StringBuilder .append should be chained, reusing the target object. This can improve the performance +by producing a smaller bytecode, reducing overhead and improving inlining. A complete analysis can be found here
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.performance.ConsecutiveAppendsShouldReuseRule
+ +Example(s):
+ +String foo = " ";
+
+StringBuffer buf = new StringBuffer();
+buf.append("Hello"); // poor
+buf.append(foo);
+buf.append("World");
+
+StringBuffer buf = new StringBuffer();
+buf.append("Hello").append(foo).append("World"); // good
+
Use this rule by referencing it:
+<rule ref="category/java/performance.xml/ConsecutiveAppendsShouldReuse" />
+
Since: PMD 3.5
+ +Priority: Medium (3)
+ +Consecutively calling StringBuffer/StringBuilder.append(…) with literals should be avoided. +Since the literals are constants, they can already be combined into a single String literal and this String +can be appended in a single method call.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.performance.ConsecutiveLiteralAppendsRule
+ +Example(s):
+ +StringBuilder buf = new StringBuilder();
+buf.append("Hello").append(" ").append("World"); // poor
+buf.append("Hello World"); // good
+
+buf.append('h').append('e').append('l').append('l').append('o'); // poor
+buf.append("hello"); // good
+
+buf.append(1).append('m'); // poor
+buf.append("1m"); // good
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
threshold | +1 | +Max consecutive appends | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/performance.xml/ConsecutiveLiteralAppends" />
+
Use this rule and customize it:
+<rule ref="category/java/performance.xml/ConsecutiveLiteralAppends">
+ <properties>
+ <property name="threshold" value="1" />
+ </properties>
+</rule>
+
Since: PMD 3.6
+ +Priority: Medium (3)
+ +String.trim().length() == 0 (or String.trim().isEmpty() for the same reason) is an inefficient +way to check if a String is really blank, as it creates a new String object just to check its size. +Consider creating a static function that loops through a string, checking Character.isWhitespace() +on each character and returning false if a non-whitespace character is found. A Smarter code to +check for an empty string would be:
+ +private boolean checkTrimEmpty(String str) {
+ for(int i = 0; i < str.length(); i++) {
+ if(!Character.isWhitespace(str.charAt(i))) {
+ return false;
+ }
+ }
+ return true;
+}
+
You can refer to Apache’s StringUtils#isBlank (in commons-lang), +Spring’s StringUtils#hasText (in the Spring framework) or Google’s +CharMatcher#whitespace (in Guava) for existing implementations (some might +include the check for != null).
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.performance.InefficientEmptyStringCheckRule
+ +Example(s):
+ +public void bar(String string) {
+ if (string != null && string.trim().length() > 0) {
+ doSomething();
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/performance.xml/InefficientEmptyStringCheck" />
+
Since: PMD 3.4
+ +Priority: Medium (3)
+ +Avoid concatenating non-literals in a StringBuffer constructor or append() since intermediate buffers will +need to be be created and destroyed by the JVM.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.performance.InefficientStringBufferingRule
+ +Example(s):
+ +// Avoid this, two buffers are actually being created here
+StringBuffer sb = new StringBuffer("tmp = "+System.getProperty("java.io.tmpdir"));
+
+// do this instead
+StringBuffer sb = new StringBuffer("tmp = ");
+sb.append(System.getProperty("java.io.tmpdir"));
+
Use this rule by referencing it:
+<rule ref="category/java/performance.xml/InefficientStringBuffering" />
+
Since: PMD 3.6
+ +Priority: Medium (3)
+ +Failing to pre-size a StringBuffer or StringBuilder properly could cause it to re-size many times +during runtime. This rule attempts to determine the total number the characters that are actually +passed into StringBuffer.append(), but represents a best guess "worst case" scenario. An empty +StringBuffer/StringBuilder constructor initializes the object to 16 characters. This default +is assumed if the length of the constructor can not be determined.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.performance.InsufficientStringBufferDeclarationRule
+ +Example(s):
+ +StringBuffer bad = new StringBuffer();
+bad.append("This is a long string that will exceed the default 16 characters");
+
+StringBuffer good = new StringBuffer(41);
+good.append("This is a long string, which is pre-sized");
+
Use this rule by referencing it:
+<rule ref="category/java/performance.xml/InsufficientStringBufferDeclaration" />
+
Since: PMD 3.5
+ +Priority: Medium High (2)
+ +Calling new Integer() causes memory allocation that can be avoided by the static Integer.valueOf(). +It makes use of an internal cache that recycles earlier instances making it more memory efficient. +Note that new Integer() is deprecated since JDK 9 for that reason.
+ +This rule is defined by the following XPath expression:
+//AllocationExpression
+ [not (ArrayDimsAndInits)
+ and ClassOrInterfaceType[pmd-java:typeIs('java.lang.Integer')]]
+
Example(s):
+ +public class Foo {
+ private Integer i = new Integer(0); // change to Integer i = Integer.valueOf(0);
+}
+
Use this rule by referencing it:
+<rule ref="category/java/performance.xml/IntegerInstantiation" />
+
Since: PMD 4.0
+ +Priority: Medium High (2)
+ +Calling new Long() causes memory allocation that can be avoided by the static Long.valueOf(). +It makes use of an internal cache that recycles earlier instances making it more memory efficient. +Note that new Long() is deprecated since JDK 9 for that reason.
+ +This rule is defined by the following XPath expression:
+//AllocationExpression
+[not (ArrayDimsAndInits)
+and ClassOrInterfaceType[pmd-java:typeIs('java.lang.Long')]]
+
Example(s):
+ +public class Foo {
+ private Long i = new Long(0); // change to Long i = Long.valueOf(0);
+}
+
Use this rule by referencing it:
+<rule ref="category/java/performance.xml/LongInstantiation" />
+
Since: PMD 1.8
+ +Priority: Medium (3)
+ +Minimum Language Version: Java 1.6
+ +Calls to a collection’s toArray(E[])
method should specify a target array of zero size. This allows the JVM
+to optimize the memory allocation and copying as much as possible.
Previous versions of this rule (pre PMD 6.0.0) suggested the opposite, but current JVM implementations +perform always better, when they have full control over the target array. And allocation an array via +reflection is nowadays as fast as the direct allocation.
+ +See also Arrays of Wisdom of the Ancients
+ +Note: If you don’t need an array of the correct type, then the simple toArray()
method without an array
+is faster, but returns only an array of type Object[]
.
This rule is defined by the following XPath expression:
+//PrimaryExpression
+[PrimaryPrefix/Name[ends-with(@Image, 'toArray')]]
+[
+PrimarySuffix/Arguments/ArgumentList/Expression
+ /PrimaryExpression/PrimaryPrefix/AllocationExpression
+ /ArrayDimsAndInits/Expression/PrimaryExpression/PrimaryPrefix[not(Literal[@Image='0'])]
+]
+
Example(s):
+ +List<Foo> foos = getFoos();
+
+// much better; this one allows the jvm to allocate an array of the correct size and effectively skip
+// the zeroing, since each array element will be overridden anyways
+Foo[] fooArray = foos.toArray(new Foo[0]);
+
+// inefficient, the array needs to be zeroed out by the jvm before it is handed over to the toArray method
+Foo[] fooArray = foos.toArray(new Foo[foos.size()]);
+
Use this rule by referencing it:
+<rule ref="category/java/performance.xml/OptimizableToArrayCall" />
+
Since: PMD 5.0
+ +Priority: Medium (3)
+ +Java will initialize fields with known default values so any explicit initialization of those same defaults +is redundant and results in a larger class file (approximately three additional bytecode instructions per field).
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.performance.RedundantFieldInitializerRule
+ +Example(s):
+ +public class C {
+ boolean b = false; // examples of redundant initializers
+ byte by = 0;
+ short s = 0;
+ char c = 0;
+ int i = 0;
+ long l = 0;
+
+ float f = .0f; // all possible float literals
+ doable d = 0d; // all possible double literals
+ Object o = null;
+
+ MyClass mca[] = null;
+ int i1 = 0, ia1[] = null;
+
+ class Nested {
+ boolean b = false;
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/performance.xml/RedundantFieldInitializer" />
+
Since: PMD 4.0
+ +Priority: Medium High (2)
+ +Calling new Short() causes memory allocation that can be avoided by the static Short.valueOf(). +It makes use of an internal cache that recycles earlier instances making it more memory efficient. +Note that new Short() is deprecated since JDK 9 for that reason.
+ +This rule is defined by the following XPath expression:
+//AllocationExpression
+[not (ArrayDimsAndInits)
+and ClassOrInterfaceType[pmd-java:typeIs('java.lang.Short')]]
+
Example(s):
+ +public class Foo {
+ private Short i = new Short(0); // change to Short i = Short.valueOf(0);
+}
+
Use this rule by referencing it:
+<rule ref="category/java/performance.xml/ShortInstantiation" />
+
Since: PMD 3.1
+ +Priority: Medium (3)
+ +Calls to string.startsWith("x")
with a string literal of length 1 can be rewritten using string.charAt(0)
,
+at the expense of some readability. To prevent IndexOutOfBoundsException
being thrown by the charAt
method,
+ensure that the string is not empty by making an additional check first.
This rule is defined by the following XPath expression:
+//PrimaryExpression
+ [PrimaryPrefix/Name
+ [ends-with(@Image, '.startsWith')] or PrimarySuffix[@Image='startsWith']]
+ [PrimarySuffix/Arguments/ArgumentList
+ /Expression/PrimaryExpression/PrimaryPrefix
+ /Literal
+ [string-length(@Image)=3]
+ [starts-with(@Image, '"')]
+ [ends-with(@Image, '"')]
+ ]
+
Example(s):
+ +public class Foo {
+
+ boolean checkIt(String x) {
+ return x.startsWith("a"); // suboptimal
+ }
+
+ boolean fasterCheckIt(String x) {
+ return !x.isEmpty() && x.charAt(0) == 'a'; // faster approach
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/performance.xml/SimplifyStartsWith" />
+
Since: PMD 1.0
+ +Priority: Medium High (2)
+ +Avoid instantiating String objects; this is usually unnecessary since they are immutable and can be safely shared.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.performance.StringInstantiationRule
+ +Example(s):
+ +private String bar = new String("bar"); // just do a String bar = "bar";
+
Use this rule by referencing it:
+<rule ref="category/java/performance.xml/StringInstantiation" />
+
Since: PMD 1.0
+ +Priority: Medium (3)
+ +Avoid calling toString() on objects already known to be string instances; this is unnecessary.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.performance.StringToStringRule
+ +Example(s):
+ +private String baz() {
+ String bar = "howdy";
+ return bar.toString();
+}
+
Use this rule by referencing it:
+<rule ref="category/java/performance.xml/StringToString" />
+
Since: PMD 4.2
+ +Priority: Medium (3)
+ +Switch statements are intended to be used to support complex branching behaviour. Using a switch for only a few +cases is ill-advised, since switches are not as easy to understand as if-then statements. In these cases use the +if-then statement to increase code readability.
+ +This rule is defined by the following XPath expression:
+//SwitchStatement[
+ (count(.//SwitchLabel) < $minimumNumberCaseForASwitch)
+]
+
Example(s):
+ +// With a minimumNumberCaseForASwitch of 3
+public class Foo {
+ public void bar() {
+ switch (condition) {
+ case ONE:
+ instruction;
+ break;
+ default:
+ break; // not enough for a 'switch' stmt, a simple 'if' stmt would have been more appropriate
+ }
+ }
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
minimumNumberCaseForASwitch | +3 | +Minimum number of branches for a switch | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/java/performance.xml/TooFewBranchesForASwitchStatement" />
+
Use this rule and customize it:
+<rule ref="category/java/performance.xml/TooFewBranchesForASwitchStatement">
+ <properties>
+ <property name="minimumNumberCaseForASwitch" value="3" />
+ </properties>
+</rule>
+
Since: PMD 3.8
+ +Priority: Medium (3)
+ +Most wrapper classes provide static conversion methods that avoid the need to create intermediate objects +just to create the primitive forms. Using these avoids the cost of creating objects that also need to be +garbage-collected later.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.performance.UnnecessaryWrapperObjectCreationRule
+ +Example(s):
+ +public int convert(String s) {
+ int i, i2;
+
+ i = Integer.valueOf(s).intValue(); // this wastes an object
+ i = Integer.parseInt(s); // this is better
+
+ i2 = Integer.valueOf(i).intValue(); // this wastes an object
+ i2 = i; // this is better
+
+ String s3 = Integer.valueOf(i2).toString(); // this wastes an object
+ s3 = Integer.toString(i2); // this is better
+
+ return i2;
+}
+
Use this rule by referencing it:
+<rule ref="category/java/performance.xml/UnnecessaryWrapperObjectCreation" />
+
Since: PMD 3.0
+ +Priority: Medium (3)
+ +ArrayList is a much better Collection implementation than Vector if thread-safe operation is not required.
+ +This rule is defined by the following XPath expression:
+//CompilationUnit[not(ImportDeclaration) or ImportDeclaration[@ImportedName='java.util.Vector']]
+ //AllocationExpression/ClassOrInterfaceType
+ [@Image='Vector' or @Image='java.util.Vector']
+
Example(s):
+ +public class SimpleTest extends TestCase {
+ public void testX() {
+ Collection c1 = new Vector();
+ Collection c2 = new ArrayList(); // achieves the same with much better performance
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/performance.xml/UseArrayListInsteadOfVector" />
+
Since: PMD 3.5
+ +Priority: Medium (3)
+ +The java.util.Arrays class has a "asList" method that should be used when you want to create a new List from +an array of objects. It is faster than executing a loop to copy all the elements of the array one by one.
+ +Note that the result of Arrays.asList() is backed by the specified array, +changes in the returned list will result in the array to be modified. +For that reason, it is not possible to add new elements to the returned list of Arrays.asList() (UnsupportedOperationException). +You must use new ArrayList<>(Arrays.asList(…)) if that is inconvenient for you (e.g. because of concurrent access).
+ +This rule is defined by the following XPath expression:
+//Statement[
+ (ForStatement) and (ForStatement//VariableInitializer//Literal[@IntLiteral= true() and @Image='0']) and (not(.//IfStatement))
+ ]
+ //StatementExpression[
+ PrimaryExpression/PrimaryPrefix/Name[
+ substring-before(@Image,'.add') = ancestor::MethodDeclaration//LocalVariableDeclaration[
+ ./Type//ClassOrInterfaceType[
+ @Image = 'Collection' or
+ @Image = 'List' or @Image='ArrayList'
+ ]
+ ]
+ /VariableDeclarator/VariableDeclaratorId[
+ count(..//AllocationExpression/ClassOrInterfaceType[
+ @Image="ArrayList"
+ ]
+ )=1
+ ]/@Name
+ ]
+ and
+ PrimaryExpression/PrimarySuffix/Arguments/ArgumentList/Expression/PrimaryExpression/PrimaryPrefix/Name
+ [
+ @Image = ancestor::MethodDeclaration[1]//LocalVariableDeclaration/VariableDeclarator/VariableDeclaratorId[@ArrayType=true()]/@Name
+ or
+ @Image = ancestor::MethodDeclaration[1]//FormalParameter/VariableDeclaratorId/@Name
+ ]
+ /../..[count(.//PrimarySuffix)
+ =1]/PrimarySuffix/Expression/PrimaryExpression/PrimaryPrefix
+ /Name
+ ]
+
Example(s):
+ +public class Test {
+ public void foo(Integer[] ints) {
+ // could just use Arrays.asList(ints)
+ List<Integer> l= new ArrayList<>(100);
+ for (int i=0; i< 100; i++) {
+ l.add(ints[i]);
+ }
+ for (int i=0; i< 100; i++) {
+ l.add(a[i].toString()); // won't trigger the rule
+ }
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/performance.xml/UseArraysAsList" />
+
Since: PMD 3.5
+ +Priority: Medium (3)
+ +Use String.indexOf(char) when checking for the index of a single character; it executes faster.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.performance.UseIndexOfCharRule
+ +Example(s):
+ +String s = "hello world";
+// avoid this
+if (s.indexOf("d") {}
+// instead do this
+if (s.indexOf('d') {}
+
Use this rule by referencing it:
+<rule ref="category/java/performance.xml/UseIndexOfChar" />
+
Since: PMD 6.25.0
+ +Priority: Medium (3)
+ +Problem: Use of FileItem.get() +and FileItem.getString() +could exhaust memory since they load the entire file into memory.
+ +Solution: Use FileItem.getInputStream() +and buffering.
+ +This rule is defined by the following XPath expression:
+//PrimaryPrefix/Name
+[ends-with(@Image, '.get') or ends-with(@Image, '.getString')]
+[
+ starts-with(@Image, concat(
+ ancestor::MethodDeclaration//FormalParameter/Type/ReferenceType/ClassOrInterfaceType[pmd-java:typeIs('org.apache.commons.fileupload.FileItem')]/../../..//VariableDeclaratorId/@Name,
+ '.')
+ ) or
+ starts-with(@Image, concat(
+ ancestor::MethodDeclaration//LocalVariableDeclaration/Type/ReferenceType/ClassOrInterfaceType[pmd-java:typeIs('org.apache.commons.fileupload.FileItem')]/../../..//VariableDeclaratorId/@Name,
+ '.')
+ ) or
+ starts-with(@Image, concat(
+ ancestor::ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/FieldDeclaration/Type/ReferenceType/ClassOrInterfaceType[pmd-java:typeIs('org.apache.commons.fileupload.FileItem')]/../../..//VariableDeclaratorId/@Name,
+ '.')
+ )
+]
+
Example(s):
+ +import org.apache.commons.fileupload.FileItem;
+
+public class FileStuff {
+ private String bad(FileItem fileItem) {
+ return fileItem.getString();
+ }
+
+ private InputStream good(FileItem fileItem) {
+ return fileItem.getInputStream();
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/performance.xml/UseIOStreamsWithApacheCommonsFileItem" />
+
Since: PMD 3.8
+ +Priority: Medium (3)
+ +No need to call String.valueOf to append to a string; just use the valueOf() argument directly.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.performance.UselessStringValueOfRule
+ +Example(s):
+ +public String convert(int i) {
+ String s;
+ s = "a" + String.valueOf(i); // not required
+ s = "a" + i; // preferred approach
+ return s;
+}
+
Use this rule by referencing it:
+<rule ref="category/java/performance.xml/UselessStringValueOf" />
+
Since: PMD 3.1
+ +Priority: Medium (3)
+ +The use of the ‘+=’ operator for appending strings causes the JVM to create and use an internal StringBuffer. +If a non-trivial number of these concatenations are being used then the explicit use of a StringBuilder or +threadsafe StringBuffer is recommended to avoid this.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.performance.UseStringBufferForStringAppendsRule
+ +Example(s):
+ +public class Foo {
+ void bar() {
+ String a;
+ a = "foo";
+ a += " bar";
+ // better would be:
+ // StringBuilder a = new StringBuilder("foo");
+ // a.append(" bar");
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/performance.xml/UseStringBufferForStringAppends" />
+
Since: PMD 3.4
+ +Priority: Medium (3)
+ +Use StringBuffer.length() to determine StringBuffer length rather than using StringBuffer.toString().equals("") +or StringBuffer.toString().length() == …
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.performance.UseStringBufferLengthRule
+ +Example(s):
+ +StringBuffer sb = new StringBuffer();
+
+if (sb.toString().equals("")) {} // inefficient
+
+if (sb.length() == 0) {} // preferred
+
Use this rule by referencing it:
+<rule ref="category/java/performance.xml/UseStringBufferLength" />
+
Since: PMD 6.4.0
+ +Priority: Medium (3)
+ +Do not use hard coded values for cryptographic operations. Please store keys outside of source code.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.security.HardCodedCryptoKeyRule
+ +Example(s):
+ +public class Foo {
+ void good() {
+ SecretKeySpec secretKeySpec = new SecretKeySpec(Properties.getKey(), "AES");
+ }
+
+ void bad() {
+ SecretKeySpec secretKeySpec = new SecretKeySpec("my secret here".getBytes(), "AES");
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/security.xml/HardCodedCryptoKey" />
+
Since: PMD 6.3.0
+ +Priority: Medium (3)
+ +Do not use hard coded initialization vector in cryptographic operations. Please use a randomly generated IV.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.java.rule.security.InsecureCryptoIvRule
+ +Example(s):
+ +public class Foo {
+ void good() {
+ SecureRandom random = new SecureRandom();
+ byte iv[] = new byte[16];
+ random.nextBytes(bytes);
+ }
+
+ void bad() {
+ byte[] iv = new byte[] { 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, };
+ }
+
+ void alsoBad() {
+ byte[] iv = "secret iv in here".getBytes();
+ }
+}
+
Use this rule by referencing it:
+<rule ref="category/java/security.xml/InsecureCryptoIv" />
+
Basic JSP (rulesets/jsp/basic.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ +DuplicateJspImports, IframeMissingSrcAttribute, JspEncoding, NoClassAttribute, NoHtmlComments, NoInlineScript, NoInlineStyleInformation, NoJspForward, NoLongScripts, NoScriptlets, NoUnsanitizedJSPExpression
+Since: PMD 3.6
+ +Priority: Medium (3)
+ +Do not nest JSF component custom actions inside a custom action that iterates over its body.
+ +This rule is defined by the following XPath expression:
+//Element[ @Name="c:forEach" ] // Element[ @NamespacePrefix="h" or @NamespacePrefix="f" ]
+
Example(s):
+ +<html>
+ <body>
+ <ul>
+ <c:forEach items='${books}' var='b'>
+ <li> <h:outputText value='#{b}' /> </li>
+ </c:forEach>
+ </ul>
+ </body>
+</html>
+
Use this rule by referencing it:
+<rule ref="category/jsp/bestpractices.xml/DontNestJsfInJstlIteration" />
+
Since: PMD 3.6
+ +Priority: Medium High (2)
+ +Do not use an attribute called ‘class’. Use "styleclass" for CSS styles.
+ +This rule is defined by the following XPath expression:
+//Attribute[ upper-case(@Name)="CLASS" ]
+
Example(s):
+ +<HTML> <BODY>
+<P class="MajorHeading">Some text</P>
+</BODY> </HTML>
+
Use this rule by referencing it:
+<rule ref="category/jsp/bestpractices.xml/NoClassAttribute" />
+
Since: PMD 3.6
+ +Priority: Medium High (2)
+ +In a production system, HTML comments increase the payload +between the application server to the client, and serve +little other purpose. Consider switching to JSP comments.
+ +This rule is defined by the following XPath expression:
+//CommentTag
+
Example(s):
+ +<HTML><title>bad example><BODY>
+<!-- HTML comment -->
+</BODY> </HTML>
+
+<HTML><title>good example><BODY>
+<%-- JSP comment --%>
+</BODY> </HTML>
+
Use this rule by referencing it:
+<rule ref="category/jsp/bestpractices.xml/NoHtmlComments" />
+
Since: PMD 3.6
+ +Priority: Medium (3)
+ +Do not do a forward from within a JSP file.
+ +This rule is defined by the following XPath expression:
+//Element[ @Name="jsp:forward" ]
+
Example(s):
+ +<jsp:forward page='UnderConstruction.jsp'/>
+
Use this rule by referencing it:
+<rule ref="category/jsp/bestpractices.xml/NoJspForward" />
+
Since: PMD 3.7
+ +Priority: Medium (3)
+ +Avoid duplicate import statements inside JSP’s.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.jsp.rule.codestyle.DuplicateJspImportsRule
+ +Example(s):
+ +<%@ page import=\"com.foo.MyClass,com.foo.MyClass\"%><html><body><b><img src=\"<%=Some.get()%>/foo\">xx</img>text</b></body></html>
+
Use this rule by referencing it:
+<rule ref="category/jsp/codestyle.xml/DuplicateJspImports" />
+
Since: PMD 4.0
+ +Priority: Medium (3)
+ +Avoid inlining HTML script content. Consider externalizing the HTML script using the ‘src’ attribute on the "script" element. +Externalized script could be reused between pages. Browsers can also cache the script, reducing overall download bandwidth.
+ +This rule is defined by the following XPath expression:
+//HtmlScript[@Image != '']
+
Use this rule by referencing it:
+<rule ref="category/jsp/design.xml/NoInlineScript" />
+
Since: PMD 3.6
+ +Priority: Medium (3)
+ +Style information should be put in CSS files, not in JSPs. Therefore, don’t use <B> or <FONT> +tags, or attributes like "align=’center’".
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.jsp.rule.design.NoInlineStyleInformationRule
+ +Example(s):
+ +<html><body><p align='center'><b>text</b></p></body></html>
+
Use this rule by referencing it:
+<rule ref="category/jsp/design.xml/NoInlineStyleInformation" />
+
Since: PMD 3.6
+ +Priority: Medium High (2)
+ +Scripts should be part of Tag Libraries, rather than part of JSP pages.
+ +This rule is defined by the following XPath expression:
+//HtmlScript[(@EndLine - @BeginLine > 10)]
+
Example(s):
+ +<HTML>
+<BODY>
+<!--Java Script-->
+<SCRIPT language="JavaScript" type="text/javascript">
+<!--
+function calcDays(){
+ var date1 = document.getElementById('d1').lastChild.data;
+ var date2 = document.getElementById('d2').lastChild.data;
+ date1 = date1.split("-");
+ date2 = date2.split("-");
+ var sDate = new Date(date1[0]+"/"+date1[1]+"/"+date1[2]);
+ var eDate = new Date(date2[0]+"/"+date2[1]+"/"+date2[2]);
+ var daysApart = Math.abs(Math.round((sDate-eDate)/86400000));
+ document.getElementById('diffDays').lastChild.data = daysApart;
+}
+
+onload=calcDays;
+//-->
+</SCRIPT>
+</BODY>
+</HTML>
+
Use this rule by referencing it:
+<rule ref="category/jsp/design.xml/NoLongScripts" />
+
Since: PMD 3.6
+ +Priority: Medium (3)
+ +Scriptlets should be factored into Tag Libraries or JSP declarations, rather than being part of JSP pages.
+ +This rule is defined by the following XPath expression:
+//JspScriptlet
+|
+//Element[ upper-case(@Name)="JSP:SCRIPTLET" ]
+
Example(s):
+ +<HTML>
+<HEAD>
+<%
+response.setHeader("Pragma", "No-cache");
+%>
+</HEAD>
+ <BODY>
+ <jsp:scriptlet>String title = "Hello world!";</jsp:scriptlet>
+ </BODY>
+</HTML>
+
Use this rule by referencing it:
+<rule ref="category/jsp/design.xml/NoScriptlets" />
+
Since: PMD 4.0
+ +Priority: Medium (3)
+ +A missing ‘meta’ tag or page directive will trigger this rule, as well as a non-UTF-8 charset.
+ +This rule is defined by the following XPath expression:
+//CompilationUnit/Content[
+not(Element[@Name="meta"][
+ Attribute[@Name="content"]/AttributeValue[contains(lower-case(@Image),"charset=utf-8")]
+])
+and
+ not(JspDirective[@Name='page']/JspDirectiveAttribute[@Name='contentType'][contains(lower-case(@Value),"charset=utf-8")])
+]
+
Example(s):
+ +Most browsers should be able to interpret the following headers:
+
+<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
+
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+
Use this rule by referencing it:
+<rule ref="category/jsp/errorprone.xml/JspEncoding" />
+
Since: PMD 3.6
+ +Priority: Medium High (2)
+ +IFrames which are missing a src element can cause security information popups in IE if you are accessing the page +through SSL. See http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q261188
+ +This rule is defined by the following XPath expression:
+//Element[upper-case(@Name)="IFRAME"][count(Attribute[upper-case(@Name)="SRC" ]) = 0]
+
Example(s):
+ +<HTML><title>bad example><BODY>
+<iframe></iframe>
+</BODY> </HTML>
+
+<HTML><title>good example><BODY>
+<iframe src="foo"></iframe>
+</BODY> </HTML>
+
Use this rule by referencing it:
+<rule ref="category/jsp/security.xml/IframeMissingSrcAttribute" />
+
Since: PMD 5.1.4
+ +Priority: Medium (3)
+ +Avoid using expressions without escaping / sanitizing. This could lead to cross site scripting - as the expression +would be interpreted by the browser directly (e.g. "<script>alert(‘hello’);</script>").
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.jsp.rule.security.NoUnsanitizedJSPExpressionRule
+ +Example(s):
+ +<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
+${expression} <!-- don't use this -->
+${fn:escapeXml(expression)} <!-- instead, escape it -->
+<c:out value="${expression}" /> <!-- or use c:out -->
+
Use this rule by referencing it:
+<rule ref="category/jsp/security.xml/NoUnsanitizedJSPExpression" />
+
Priority: Medium (3)
+ +There is multiple candidates for this type resolution. While generally this is not an error, +this may indicate a bug.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.modelica.rule.AmbiguousResolutionRule
+ +Example(s):
+ +package Test
+ package Inc1
+ model X
+ end X;
+ model Y
+ end Y;
+ end Inc1;
+ package Inc2
+ model Y
+ end Y;
+ model Z
+ end Z;
+ end Inc2;
+ model B
+ import Test.Inc1.*;
+ import Test.Inc2.*;
+ Y y; // Class Y is imported twice
+ end B;
+end Test;
+
+
+Use this rule by referencing it:
+<rule ref="category/modelica/bestpractices.xml/AmbiguousResolution" />
+
Priority: High (1)
+ +Having a class starting with some name and some different +name in its end clause is an error.
+ +This rule is defined by the following XPath expression:
+//ClassSpecifier/*[SimpleName[1]/@Image != SimpleName[last()]/@Image]
+
Example(s):
+ +model SomeName
+ Real x;
+equation
+ x = 1;
+end SomeOtherName /* should be SomeName */;
+
+
+Use this rule by referencing it:
+<rule ref="category/modelica/bestpractices.xml/ClassStartNameEqualsEndName" />
+
Priority: Medium High (2)
+ +Modelica specification requires passing connectors to the connect
clause,
+while some implementations tolerate using it on plain variables, etc..
This rule is defined by the following Java class: net.sourceforge.pmd.lang.modelica.rule.ConnectUsingNonConnector
+ +Example(s):
+ +package Example
+ connector Conn
+ Real x;
+ Real y;
+ end Conn;
+
+ model Test
+ input Conn c1;
+ output Conn c2;
+ input Real x1;
+ output Real x2;
+ equation
+ connect(c1, c2); // OK
+ connect(x1, x2); // error, x1 and x2 are not (both) connectors
+ // x1 = x2; // OK
+ end Test;
+end Example;
+
+
+Use this rule by referencing it:
+<rule ref="category/modelica/bestpractices.xml/ConnectUsingNonConnector" />
+
Code Size (rulesets/plsql/codesize.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ +CyclomaticComplexity, ExcessiveMethodLength, ExcessiveObjectLength, ExcessivePackageBodyLength, ExcessivePackageSpecificationLength, ExcessiveParameterList, ExcessiveTypeLength, NcssMethodCount, NcssObjectCount, NPathComplexity, TooManyFields, TooManyMethods
+PLSQL DATETIME (rulesets/plsql/dates.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ +TO_DATE_TO_CHAR, TO_DATEWithoutDateFormat, TO_TIMESTAMPWithoutDateFormat
+Strict Syntax (rulesets/plsql/strictsyntax.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ + +Tom Kyte’s Despair (rulesets/plsql/TomKytesDespair.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ + +Since: PMD 5.1
+ +Priority: Medium (3)
+ +"WHEN OTHERS THEN NULL" hides all errors - (Re)RAISE an exception or call RAISE_APPLICATION_ERROR
+ +This rule is defined by the following XPath expression:
+//ExceptionHandler[QualifiedName/@Image='OTHERS' and upper-case(Statement/UnlabelledStatement/Expression/@Image)='NULL']
+
Example(s):
+ +CREATE OR REPLACE PACKAGE BODY update_planned_hrs
+IS
+
+PROCEDURE set_new_planned (p_emp_id IN NUMBER, p_project_id IN NUMBER, p_hours IN NUMBER)
+IS
+BEGIN
+ UPDATE employee_on_activity ea
+ SET ea.ea_planned_hours = p_hours
+ WHERE
+ ea.ea_emp_id = p_emp_id
+ AND ea.ea_proj_id = p_project_id;
+
+EXCEPTION
+ WHEN NO_DATA_FOUND THEN
+ RAISE_APPLICATION_ERROR (-20100, 'No such employee or project');
+
+END set_new_planned;
+
+FUNCTION existing_planned (p_emp_id IN NUMBER, p_project_id IN NUMBER) RETURN NUMBER
+
+IS
+
+existing_hours NUMBER(4);
+
+BEGIN
+ SELECT ea.ea_planned_hours INTO existing_hours
+ FROM employee_on_activity ea
+ WHERE
+ ea.ea_emp_id = p_emp_id
+ AND ea.ea_proj_id = p_project_id;
+
+ RETURN (existing_hours);
+
+ EXCEPTION
+ WHEN OTHERS THEN NULL;
+
+ END existing_planned;
+
+END update_planned_hrs;
+/
+
Use this rule by referencing it:
+<rule ref="category/plsql/bestpractices.xml/TomKytesDespair" />
+
Since: PMD 6.13.0
+ +Priority: Medium (3)
+ +This rule checks, that there are no tab characters (\t
) in the source file.
+It reports only the first occurrence per file.
Using tab characters for indentation is not recommended, since this requires that every developer +uses the same tab with in their editor.
+ +This rule is the PMD equivalent of checkstyle’s FileTabCharacter check.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.plsql.rule.codestyle.AvoidTabCharacterRule
+ +This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
eachLine | +false | +Whether to report each line with a tab character or only the first line | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/plsql/codestyle.xml/AvoidTabCharacter" />
+
Use this rule and customize it:
+<rule ref="category/plsql/codestyle.xml/AvoidTabCharacter">
+ <properties>
+ <property name="eachLine" value="false" />
+ </properties>
+</rule>
+
Since: PMD 6.9.0
+ +Priority: Medium (3)
+ +This rule verifies that the PLSQL code is properly formatted. The following checks are executed:
+ +SQL Queries:
+ +Parameter definitions for procedures:
+ +Variable declarations:
+ +Calling a procedure:
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.plsql.rule.codestyle.CodeFormatRule
+ +Example(s):
+ +BEGIN
+ -- select columns each on a separate line
+ SELECT cmer_id
+ ,version
+ ,cmp_id
+ BULK COLLECT INTO v_cmer_ids
+ ,v_versions
+ ,v_cmp_ids
+ FROM cmer;
+
+ -- each parameter on a new line
+ PROCEDURE create_prospect(
+ company_info_in IN prospects.company_info%TYPE -- Organization
+ ,firstname_in IN persons.firstname%TYPE -- FirstName
+ ,lastname_in IN persons.lastname%TYPE -- LastName
+ );
+
+ -- more than three parameters, each parameter on a separate line
+ webcrm_marketing.prospect_ins(
+ cmp_id_in => NULL
+ ,company_info_in => company_info_in
+ ,firstname_in => firstname_in
+ ,lastname_in => lastname_in
+ ,slt_code_in => NULL
+ );
+
+END;
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
indentation | +2 | +Indentation to be used for blocks | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/plsql/codestyle.xml/CodeFormat" />
+
Use this rule and customize it:
+<rule ref="category/plsql/codestyle.xml/CodeFormat">
+ <properties>
+ <property name="indentation" value="2" />
+ </properties>
+</rule>
+
Since: PMD 6.7.0
+ +Priority: Medium (3)
+ +In case you have loops please name the loop variables more meaningful.
+ +This rule is defined by the following XPath expression:
+//CursorForLoopStatement[
+ $allowSimpleLoops = false() or
+ (Statement//CursorForLoopStatement or ancestor::CursorForLoopStatement)
+]
+/ForIndex[not(matches(@Image, $cursorPattern))]
+|
+//ForStatement[
+ $allowSimpleLoops = false() or
+ (Statement//ForStatement or ancestor::ForStatement)
+]
+/ForIndex[not(matches(@Image, $indexPattern))]
+
Example(s):
+ +-- good example
+BEGIN
+FOR company IN (SELECT * FROM companies) LOOP
+ FOR contact IN (SELECT * FROM contacts) LOOP
+ FOR party IN (SELECT * FROM parties) LOOP
+ NULL;
+ END LOOP;
+ END LOOP;
+END LOOP;
+END;
+/
+
+-- bad example
+BEGIN
+FOR c1 IN (SELECT * FROM companies) LOOP
+ FOR c2 IN (SELECT * FROM contacts) LOOP
+ FOR c3 IN (SELECT * FROM parties) LOOP
+ NULL;
+ END LOOP;
+ END LOOP;
+END LOOP;
+END;
+/
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
allowSimpleLoops | +false | +Ignore simple loops, that are not nested | +no | +
cursorPattern | +[a-zA-Z_0-9]{5,} | +The pattern used for the curosr loop variable | +no | +
indexPattern | +[a-zA-Z_0-9]{5,} | +The pattern used for the index loop variable | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/plsql/codestyle.xml/ForLoopNaming" />
+
Use this rule and customize it:
+<rule ref="category/plsql/codestyle.xml/ForLoopNaming">
+ <properties>
+ <property name="allowSimpleLoops" value="false" />
+ <property name="cursorPattern" value="[a-zA-Z_0-9]{5,}" />
+ <property name="indexPattern" value="[a-zA-Z_0-9]{5,}" />
+ </properties>
+</rule>
+
Since: PMD 6.13.0
+ +Priority: Medium (3)
+ +This rule checks for long lines. Please note that comments are not ignored.
+ +This rule is the PMD equivalent of checkstyle’s LineLength check.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.plsql.rule.codestyle.LineLengthRule
+ +This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
maxLineLength | +80 | +The maximum allowed line length | +no | +
eachLine | +false | +Whether to report each line that is longer only the first line | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/plsql/codestyle.xml/LineLength" />
+
Use this rule and customize it:
+<rule ref="category/plsql/codestyle.xml/LineLength">
+ <properties>
+ <property name="maxLineLength" value="80" />
+ <property name="eachLine" value="false" />
+ </properties>
+</rule>
+
Since: PMD 5.5.2
+ +Priority: Medium (3)
+ +Oracle states that the PRAQMA AUTONOMOUS_TRANSACTION must be in the declaration block, +but the code does not complain, when being compiled on the 11g DB. +https://docs.oracle.com/cd/B28359_01/appdev.111/b28370/static.htm#BABIIHBJ
+ +This rule is defined by the following XPath expression:
+//ProgramUnit/Pragma
+
Example(s):
+ +create or replace package inline_pragma_error is
+
+end;
+/
+
+create or replace package body inline_pragma_error is
+ procedure do_transaction(p_input_token in varchar(200)) is
+ PRAGMA AUTONOMOUS_TRANSACTION; /* this is correct place for PRAGMA */
+ begin
+ PRAGMA AUTONOMOUS_TRANSACTION; /* this is the wrong place for PRAGMA -> violation */
+ /* do something */
+ COMMIT;
+ end do_transaction;
+
+end inline_pragma_error;
+/
+
Use this rule by referencing it:
+<rule ref="category/plsql/codestyle.xml/MisplacedPragma" />
+
Since: PMD 5.1
+ +Priority: Medium (3)
+ +Complexity directly affects maintenance costs is determined by the number of decision points in a method +plus one for the method entry. The decision points include ‘if’, ‘while’, ‘for’, and ‘case labels’ calls. +Generally, numbers ranging from 1-4 denote low complexity, 5-7 denote moderate complexity, 8-10 denote +high complexity, and 11+ is very high complexity.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.plsql.rule.design.CyclomaticComplexityRule
+ +Example(s):
+ +-- Cyclomatic Complexity of 25
+CREATE OR REPLACE PACKAGE BODY pkg_pmd_working_sequence AS
+1 PROCEDURE ty_logger IS BEGIN
+2 IF true
+ THEN
+ DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer);
+3 IF true
+ THEN
+ DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer);
+4 IF true
+ THEN
+ DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer);
+5 ELSIF false
+ THEN
+ DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer);
+ ELSE
+ DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer);
+ END IF;
+6 ELSIF false
+ THEN
+ DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer);
+7 IF true
+ THEN
+ DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer);
+8 ELSIF false
+ THEN
+ DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer);
+ ELSE
+ DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer);
+ END IF;
+ ELSE
+ DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer);
+9 IF true
+ THEN
+ DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer);
+10 ELSIF false
+ THEN
+ DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer);
+ ELSE
+ DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer);
+ END IF;
+ END IF;
+11 ELSIF false
+ THEN
+ DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer);
+12 IF true
+ THEN
+ DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer);
+13 IF true
+ THEN
+ DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer);
+14 ELSIF false
+ THEN
+ DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer);
+ ELSE
+ DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer);
+ END IF;
+15 ELSIF false
+ THEN
+16 IF true
+ THEN
+ DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer);
+17 ELSIF false
+ THEN
+ DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer);
+ ELSE
+ DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer);
+ END IF;
+ DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer);
+ ELSE
+ DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer);
+ END IF;
+ ELSE
+ DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer);
+18 IF true
+ THEN
+ DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer);
+19 IF true
+ THEN
+ DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer);
+20 ELSIF false
+ THEN
+ DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer);
+ ELSE
+ DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer);
+ END IF;
+21 ELSIF false
+ THEN
+ DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer);
+22 IF true
+ THEN
+ DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer);
+23 ELSIF false
+ THEN
+ DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer);
+ ELSE
+ DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer);
+ END IF;
+ ELSE
+ DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer);
+24 IF true
+ THEN
+ DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer);
+25 ELSIF false
+ THEN
+ DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer);
+ ELSE
+ DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer);
+ END IF;
+ END IF;
+ END IF;
+END;
+
+END;
+
This rule has the following properties:
+ +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 | +
reportLevel | +10 | +Cyclomatic Complexity reporting threshold | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/plsql/design.xml/CyclomaticComplexity" />
+
Use this rule and customize it:
+<rule ref="category/plsql/design.xml/CyclomaticComplexity">
+ <properties>
+ <property name="showMethodsComplexity" value="true" />
+ <property name="showClassesComplexity" value="true" />
+ <property name="reportLevel" value="10" />
+ </properties>
+</rule>
+
Since: PMD 5.1
+ +Priority: Medium (3)
+ +When methods are excessively long this usually indicates that the method is doing more than its +name/signature might suggest. They also become challenging for others to digest since excessive +scrolling causes readers to lose focus. +Try to reduce the method length by creating helper methods and removing any copy/pasted code.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.plsql.rule.design.ExcessiveMethodLengthRule
+ +Example(s):
+ +CREATE OR REPLACE
+PROCEDURE doSomething BEGIN
+ DBMS_OUTPUT.PUT_LINE("Hello world!");
+ DBMS_OUTPUT.PUT_LINE("Hello world!");
+ -- 98 copies omitted for brevity.
+END;
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
topscore | ++ | Deprecated Top score value | +no | +
minimum | +100.0 | +Minimum reporting threshold | +no | +
sigma | ++ | Deprecated Sigma value | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/plsql/design.xml/ExcessiveMethodLength" />
+
Use this rule and customize it:
+<rule ref="category/plsql/design.xml/ExcessiveMethodLength">
+ <properties>
+ <property name="minimum" value="100.0" />
+ </properties>
+</rule>
+
Since: PMD 5.1
+ +Priority: Medium (3)
+ +Excessive object line lengths are usually indications that the object may be burdened with excessive +responsibilities that could be provided by other objects. In breaking these methods +apart the code becomes more managable and ripe for reuse.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.plsql.rule.design.ExcessiveObjectLengthRule
+ +Example(s):
+ +CREATE OR REPLACE
+PACKAGE BODY Foo AS
+ PROCEDURE bar1 IS BEGIN
+ -- 1000 lines of code
+ END bar1;
+ PROCEDURE bar2 IS BEGIN
+ -- 1000 lines of code
+ END bar2;
+ PROCEDURE bar3 IS BEGIN
+ -- 1000 lines of code
+ END bar3;
+
+
+ PROCEDURE barN IS BEGIN
+ -- 1000 lines of code
+ END barn;
+END;
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
topscore | ++ | Deprecated Top score value | +no | +
minimum | +1000.0 | +Minimum reporting threshold | +no | +
sigma | ++ | Deprecated Sigma value | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/plsql/design.xml/ExcessiveObjectLength" />
+
Use this rule and customize it:
+<rule ref="category/plsql/design.xml/ExcessiveObjectLength">
+ <properties>
+ <property name="minimum" value="1000.0" />
+ </properties>
+</rule>
+
Since: PMD 5.1
+ +Priority: Medium (3)
+ +Excessive class file lengths are usually indications that the class may be burdened with excessive +responsibilities that could be provided by external classes or functions. In breaking these methods +apart the code becomes more managable and ripe for reuse.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.plsql.rule.design.ExcessivePackageBodyLengthRule
+ +Example(s):
+ +CREATE OR REPLACE
+PACKAGE BODY Foo AS
+ PROCEDURE bar1 IS BEGIN
+ -- 1000 lines of code
+ END bar1;
+ PROCEDURE bar2 IS BEGIN
+ -- 1000 lines of code
+ END bar2;
+ PROCEDURE bar3 IS BEGIN
+ -- 1000 lines of code
+ END bar3;
+
+
+ PROCEDURE barN IS BEGIN
+ -- 1000 lines of code
+ END barn;
+END;
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
topscore | ++ | Deprecated Top score value | +no | +
minimum | +1000.0 | +Minimum reporting threshold | +no | +
sigma | ++ | Deprecated Sigma value | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/plsql/design.xml/ExcessivePackageBodyLength" />
+
Use this rule and customize it:
+<rule ref="category/plsql/design.xml/ExcessivePackageBodyLength">
+ <properties>
+ <property name="minimum" value="1000.0" />
+ </properties>
+</rule>
+
Since: PMD 5.1
+ +Priority: Medium (3)
+ +Excessive class file lengths are usually indications that the class may be burdened with excessive +responsibilities that could be provided by external classes or functions. In breaking these methods +apart the code becomes more managable and ripe for reuse.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.plsql.rule.design.ExcessivePackageSpecificationLengthRule
+ +Example(s):
+ +CREATE OR REPLACE
+PACKAGE Foo AS
+ PROCEDURE bar1;
+ PROCEDURE bar2;
+ PROCEDURE bar3;
+
+ ...
+
+ PROCEDURE barN;
+END;
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
topscore | ++ | Deprecated Top score value | +no | +
minimum | +1000.0 | +Minimum reporting threshold | +no | +
sigma | ++ | Deprecated Sigma value | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/plsql/design.xml/ExcessivePackageSpecificationLength" />
+
Use this rule and customize it:
+<rule ref="category/plsql/design.xml/ExcessivePackageSpecificationLength">
+ <properties>
+ <property name="minimum" value="1000.0" />
+ </properties>
+</rule>
+
Since: PMD 5.1
+ +Priority: Medium (3)
+ +Methods with numerous parameters are a challenge to maintain, especially if most of them share the +same datatype. These situations usually denote the need for new objects to wrap the numerous parameters.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.plsql.rule.design.ExcessiveParameterListRule
+ +Example(s):
+ +CREATE OR REPLACE
+PROCEDURE addPerson( -- too many arguments liable to be mixed up
+ birthYear pls_integer, birthMonth pls_integer, birthDate pls_integer, height pls_integer, weight pls_integer, ssn pls_integer) {
+
+ . . . .
+END ADDPERSON;
+
+CREATE OR REPLACE
+PROCEDURE addPerson( -- preferred approach
+ birthdate DATE, measurements BodyMeasurements , ssn INTEGER) BEGIN
+
+ . . . .
+END;
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
topscore | ++ | Deprecated Top score value | +no | +
minimum | +10.0 | +Minimum reporting threshold | +no | +
sigma | ++ | Deprecated Sigma value | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/plsql/design.xml/ExcessiveParameterList" />
+
Use this rule and customize it:
+<rule ref="category/plsql/design.xml/ExcessiveParameterList">
+ <properties>
+ <property name="minimum" value="10.0" />
+ </properties>
+</rule>
+
Since: PMD 5.1
+ +Priority: Medium (3)
+ +Excessive class file lengths are usually indications that the class may be burdened with excessive +responsibilities that could be provided by external classes or functions. In breaking these methods +apart the code becomes more managable and ripe for reuse.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.plsql.rule.design.ExcessiveTypeLengthRule
+ +Example(s):
+ +CREATE OR REPLACE
+TYPE BODY Foo AS
+ MEMBER PROCEDURE bar1 IS BEGIN
+ -- 1000 lines of code
+ END bar1;
+ MEMBER PROCEDURE bar2 IS BEGIN
+ -- 1000 lines of code
+ END bar2;
+ MEMBER PROCEDURE bar3 IS BEGIN
+ -- 1000 lines of code
+ END bar3;
+
+
+ MEMBER PROCEDURE barN IS BEGIN
+ -- 1000 lines of code
+ END barn;
+END;
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
topscore | ++ | Deprecated Top score value | +no | +
minimum | +1000.0 | +Minimum reporting threshold | +no | +
sigma | ++ | Deprecated Sigma value | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/plsql/design.xml/ExcessiveTypeLength" />
+
Use this rule and customize it:
+<rule ref="category/plsql/design.xml/ExcessiveTypeLength">
+ <properties>
+ <property name="minimum" value="1000.0" />
+ </properties>
+</rule>
+
Since: PMD 5.1
+ +Priority: Medium (3)
+ +This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of lines +of code for a given method. NCSS ignores comments, and counts actual statements. Using this algorithm, +lines of code that are split are counted as one.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.plsql.rule.design.NcssMethodCountRule
+ +Example(s):
+ +CREATE OR REPLACE PACKAGE BODY AS
+ FUNCTION methd RETURN INTEGER IS
+ BEGIN
+ RETURN 1;;
+ END;
+END;
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
topscore | ++ | Deprecated Top score value | +no | +
minimum | +100.0 | +Minimum reporting threshold | +no | +
sigma | ++ | Deprecated Sigma value | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/plsql/design.xml/NcssMethodCount" />
+
Use this rule and customize it:
+<rule ref="category/plsql/design.xml/NcssMethodCount">
+ <properties>
+ <property name="minimum" value="100.0" />
+ </properties>
+</rule>
+
Since: PMD 5.1
+ +Priority: Medium (3)
+ +This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of lines +of code for a given Oracle object. NCSS ignores comments, and counts actual statements. Using this algorithm, +lines of code that are split are counted as one.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.plsql.rule.design.NcssObjectCountRule
+ +Example(s):
+ +CREATE OR REPLACE PACKAGE pkg_
+ PROCEDURE Foo IS
+ BEGIN
+ --this class only has 6 NCSS lines
+ super();
+ super();
+ END;
+}
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
topscore | ++ | Deprecated Top score value | +no | +
minimum | +1500.0 | +Minimum reporting threshold | +no | +
sigma | ++ | Deprecated Sigma value | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/plsql/design.xml/NcssObjectCount" />
+
Use this rule and customize it:
+<rule ref="category/plsql/design.xml/NcssObjectCount">
+ <properties>
+ <property name="minimum" value="1500.0" />
+ </properties>
+</rule>
+
Since: PMD 5.1
+ +Priority: Medium (3)
+ +The NPath complexity of a method is the number of acyclic execution paths through that method. +A threshold of 200 is generally considered the point where measures should be taken to reduce +complexity and increase readability.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.plsql.rule.design.NPathComplexityRule
+ +Example(s):
+ +CREATE OR REPLACE
+PROCEDURE bar AS BEGIN -- this is something more complex than it needs to be,
+ if (y) THEN -- it should be broken down into smaller methods or functions
+ for j IN 0 .. j-1 LOOP
+ if (j > r) THEN
+ doSomething;
+ while (f < 5 ) LOOP
+ anotherThing;
+ f := f - 27;
+ END LOOP;
+ else
+ tryThis();
+ END IF;
+ END LOOP;
+ END IF;
+ if ( r - n > 45) THEN
+ while (doMagic) LOOP
+ findRabbits;
+ END LOOP;
+ END IF;
+ BEGIN
+ doSomethingDangerous();
+ EXCEPTION WHEN FooException THEN
+ makeAmends;
+ BEGIN
+ dontDoItAgain;
+ EXCEPTION
+ WHEN OTHERS THEN
+ log_problem;
+ END;
+ END;
+END;
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
topscore | ++ | Deprecated Top score value | +no | +
minimum | +200.0 | +Minimum reporting threshold | +no | +
sigma | ++ | Deprecated Sigma value | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/plsql/design.xml/NPathComplexity" />
+
Use this rule and customize it:
+<rule ref="category/plsql/design.xml/NPathComplexity">
+ <properties>
+ <property name="minimum" value="200.0" />
+ </properties>
+</rule>
+
Since: PMD 5.1
+ +Priority: Medium (3)
+ +Classes that have too many fields can become unwieldy and could be redesigned to have fewer fields, +possibly through grouping related fields in new objects. For example, a class with individual +city/state/zip fields could park them within a single Address field.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.plsql.rule.design.TooManyFieldsRule
+ +Example(s):
+ +CREATE OR REPLACE PACKAGE pkg_too_many_fields AS
+ C_CHAR_A CONSTANT CHAR(1 CHAR) := 'A';
+ C_CHAR_B CONSTANT CHAR(1 CHAR) := 'B';
+ ...
+ C_CHAR_Z CONSTANT CHAR(1 CHAR) := 'Z';
+END pkg_too_many_fields;
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
maxfields | +15 | +Max allowable fields | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/plsql/design.xml/TooManyFields" />
+
Use this rule and customize it:
+<rule ref="category/plsql/design.xml/TooManyFields">
+ <properties>
+ <property name="maxfields" value="15" />
+ </properties>
+</rule>
+
Since: PMD 5.1
+ +Priority: Medium (3)
+ +A package or type with too many methods is probably a good suspect for refactoring, in order to reduce its complexity and find a way to +have more fine grained objects.
+ +This rule is defined by the following XPath expression:
+//node()
+ [ (
+ local-name(.) = 'PackageSpecification'
+ or
+ local-name(.) = 'TypeSpecification'
+ )
+ and
+ (
+ count(/descendant::ProgramUnit[
+ not (
+ starts-with(@Name,'get')
+ or
+ starts-with(@Name,'set')
+ or
+ starts-with(@Name,'is')
+ )
+ ]
+ )
+ +
+ count(/descendant::TypeMethod[
+ not (
+ starts-with(@Name,'get')
+ or
+ starts-with(@Name,'set')
+ or
+ starts-with(@Name,'is')
+ )
+ ]
+ )
+ ) > $maxmethods
+ ]
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
maxmethods | +1 | +The method count reporting threshold | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/plsql/design.xml/TooManyMethods" />
+
Use this rule and customize it:
+<rule ref="category/plsql/design.xml/TooManyMethods">
+ <properties>
+ <property name="maxmethods" value="1" />
+ </properties>
+</rule>
+
Since: PMD 5.1
+ +Priority: Medium (3)
+ +TO_DATE(TO_CHAR(date-variable)) used to remove time component - use TRUNC(date-variable)
+ +This rule is defined by the following XPath expression:
+//FunctionCall[@Image='TO_DATE']
+ [count(Arguments/ArgumentList/Argument) = 1]
+ [Arguments/ArgumentList/Argument//FunctionCall[@Image='TO_CHAR']]
+
Example(s):
+ +CREATE OR REPLACE PACKAGE BODY date_utilities
+IS
+
+-- Take single parameter, relying on current default NLS date format
+FUNCTION strip_time (p_date IN DATE) RETURN DATE
+IS
+BEGIN
+ RETURN TO_DATE(TO_CHAR(p_date));
+END strip_time;
+
+
+END date_utilities;
+/
+
Use this rule by referencing it:
+<rule ref="category/plsql/errorprone.xml/TO_DATE_TO_CHAR" />
+
Since: PMD 5.1
+ +Priority: Medium (3)
+ +TO_DATE without date format- use TO_DATE(expression, date-format)
+ +This rule is defined by the following XPath expression:
+//FunctionCall[@Image='TO_DATE']
+ [count(Arguments/ArgumentList/Argument) = 1]
+
Example(s):
+ +CREATE OR REPLACE PACKAGE BODY date_utilities
+IS
+
+-- Take single parameter, relying on current default NLS date format
+FUNCTION to_date_single_parameter (p_date_string IN VARCHAR2) RETURN DATE
+IS
+BEGIN
+ RETURN TO_DATE(p_date_string);
+END to_date_single_parameter ;
+
+-- Take 2 parameters, using an explicit date format string
+FUNCTION to_date_two_parameters (p_date_string IN VARCHAR2, p_format_mask IN VARCHAR2) RETURN DATE
+IS
+BEGIN
+ TO_DATE(p_date_string, p_date_format);
+END to_date_two_parameters;
+
+-- Take 3 parameters, using an explicit date format string and an explicit language
+FUNCTION to_date_three_parameters (p_date_string IN VARCHAR2, p_format_mask IN VARCHAR2, p_nls_language VARCHAR2 ) RETURN DATE
+IS
+BEGIN
+ TO_DATE(p_date_string, p_format_mask, p_nls_language);
+END to_date_three_parameters;
+
+END date_utilities;
+/
+
Use this rule by referencing it:
+<rule ref="category/plsql/errorprone.xml/TO_DATEWithoutDateFormat" />
+
Since: PMD 5.1
+ +Priority: Medium (3)
+ +TO_TIMESTAMP without date format- use TO_TIMESTAMP(expression, date-format)
+ +This rule is defined by the following XPath expression:
+//FunctionCall[@Image='TO_TIMESTAMP']
+ [count(Arguments/ArgumentList/Argument) = 1]
+
Example(s):
+ +CREATE OR REPLACE PACKAGE BODY date_utilities
+IS
+
+-- Take single parameter, relying on current default NLS date format
+FUNCTION to_timestamp_single_parameter (p_date_string IN VARCHAR2) RETURN DATE
+IS
+BEGIN
+ RETURN TO_TIMESTAMP(p_date_string);
+END to_timestamp_single_parameter;
+
+-- Take 2 parameters, using an explicit date format string
+FUNCTION to_timestamp_two_parameters (p_date_string IN VARCHAR2, p_format_mask IN VARCHAR2) RETURN DATE
+IS
+BEGIN
+ TO_TIMESTAMP(p_date_string, p_date_format);
+END to_timestamp_two_parameters;
+
+-- Take 3 parameters, using an explicit date format string and an explicit language
+FUNCTION to_timestamp_three_parameters (p_date_string IN VARCHAR2, p_format_mask IN VARCHAR2, p_nls_language VARCHAR2 ) RETURN DATE
+IS
+BEGIN
+ TO_TIMESTAMP(p_date_string, p_format_mask, p_nls_language);
+END to_timestamp_three_parameters;
+
+END date_utilities;
+/
+
Use this rule by referencing it:
+<rule ref="category/plsql/errorprone.xml/TO_TIMESTAMPWithoutDateFormat" />
+
Basic POM (rulesets/pom/basic.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ + +Since: PMD 5.4
+ +Priority: Medium (3)
+ +If you use an invalid dependency type in the dependency management section, Maven doesn’t fail. Instead, +the entry is just ignored, which might have the effect, that the wrong version of the dependency is used.
+ +The following types are considered valid: pom, jar, maven-plugin, ejb, war, ear, rar, par.
+ +This rule is defined by the following XPath expression:
+//dependencyManagement/dependency/type/text[not(@Image = $validTypes)]
+
Example(s):
+ +<project...>
+ ...
+ <dependencyManagement>
+ ...
+ <dependency>
+ <groupId>org.jboss.arquillian</groupId>
+ <artifactId>arquillian-bom</artifactId>
+ <version>${arquillian.version}</version>
+ <type>bom</type> <!-- not a valid type ! 'pom' is ! -->
+ <scope>import</scope>
+ </dependency>
+ ...
+ </dependencyManagement>
+</project>
+
This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
validTypes | +pom , jar , maven-plugin , ejb , war , ear , rar , par | +Set of valid types. | +yes. Delimiter is ‘,’. | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/pom/errorprone.xml/InvalidDependencyTypes" />
+
Use this rule and customize it:
+<rule ref="category/pom/errorprone.xml/InvalidDependencyTypes">
+ <properties>
+ <property name="validTypes" value="pom,jar,maven-plugin,ejb,war,ear,rar,par" />
+ </properties>
+</rule>
+
Since: PMD 5.4
+ +Priority: Medium (3)
+ +Using that expression in dependency declarations seems like a shortcut, but it can go wrong. +By far the most common problem is the use of ${project.version} in a BOM or parent POM.
+ +This rule is defined by the following XPath expression:
+//dependencies/dependency
+ [contains(version/text/@Image,'{project.version}')]
+ [
+ (/document/project/parent/groupId and groupId/text/@Image != /document/project/parent/groupId/text/@Image)
+ or
+ (/document/project/groupId and groupId/text/@Image != /document/project/groupId/text/@Image)
+ ]/version
+
Example(s):
+ +<project...>
+ ...
+ <dependency>
+ ...
+ <version>6.30.0-SNAPSHOT</version>
+ </dependency>
+</project>
+
Use this rule by referencing it:
+<rule ref="category/pom/errorprone.xml/ProjectVersionAsDependencyVersion" />
+
Currently there are no built-in rules yet for Scala.
+ +Contributions are welcome!
+ + + + + + + +Basic VF (rulesets/vf/security.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ + +Since: PMD 5.6.0
+ +Priority: Medium (3)
+ +Avoid calling VF action upon page load as the action becomes vulnerable to CSRF.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.vf.rule.security.VfCsrfRule
+ +Example(s):
+ +<apex:page controller="AcRestActionsController" action="{!csrfInitMethod}" >
+
+
+Use this rule by referencing it:
+<rule ref="category/vf/security.xml/VfCsrf" />
+
Since: PMD 5.6.0
+ +Priority: Medium (3)
+ +Avoid unescaped user controlled content in EL as it results in XSS.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.vf.rule.security.VfUnescapeElRule
+ +Example(s):
+ +<apex:outputText value="Potential XSS is {! here }" escape="false" />
+
+
+Use this rule by referencing it:
+<rule ref="category/vf/security.xml/VfUnescapeEl" />
+
Basic Velocity (rulesets/vm/basic.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ +AvoidDeeplyNestedIfStmts, AvoidReassigningParameters, CollapsibleIfStatements, EmptyForeachStmt, EmptyIfStmt, ExcessiveTemplateLength, NoInlineJavaScript, NoInlineStyles, UnusedMacroParameter
+Since: PMD 5.1
+ +Priority: Medium High (2)
+ +Reassigning values to incoming parameters is not recommended. Use temporary local variables instead.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.vm.rule.bestpractices.AvoidReassigningParametersRule
+ +Use this rule by referencing it:
+<rule ref="category/vm/bestpractices.xml/AvoidReassigningParameters" />
+
Since: PMD 5.1
+ +Priority: Medium High (2)
+ +Avoid unused macro parameters. They should be deleted.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.vm.rule.bestpractices.UnusedMacroParameterRule
+ +Use this rule by referencing it:
+<rule ref="category/vm/bestpractices.xml/UnusedMacroParameter" />
+
Since: PMD 5.1
+ +Priority: Medium (3)
+ +Avoid creating deeply nested if-then statements since they are harder to read and error-prone to maintain.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.vm.rule.design.AvoidDeeplyNestedIfStmtsRule
+ +This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
problemDepth | +3 | +The if statement depth reporting threshold | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/vm/design.xml/AvoidDeeplyNestedIfStmts" />
+
Use this rule and customize it:
+<rule ref="category/vm/design.xml/AvoidDeeplyNestedIfStmts">
+ <properties>
+ <property name="problemDepth" value="3" />
+ </properties>
+</rule>
+
Since: PMD 5.1
+ +Priority: Medium (3)
+ +Sometimes two consecutive ‘if’ statements can be consolidated by separating their conditions with a boolean short-circuit operator.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.vm.rule.design.CollapsibleIfStatementsRule
+ +Use this rule by referencing it:
+<rule ref="category/vm/design.xml/CollapsibleIfStatements" />
+
Since: PMD 5.1
+ +Priority: Medium (3)
+ +The template is too long. It should be broken up into smaller pieces.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.vm.rule.design.ExcessiveTemplateLengthRule
+ +This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
topscore | ++ | Deprecated Top score value | +no | +
minimum | +1000.0 | +Minimum reporting threshold | +no | +
sigma | ++ | Deprecated Sigma value | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/vm/design.xml/ExcessiveTemplateLength" />
+
Use this rule and customize it:
+<rule ref="category/vm/design.xml/ExcessiveTemplateLength">
+ <properties>
+ <property name="minimum" value="1000.0" />
+ </properties>
+</rule>
+
Since: PMD 5.1
+ +Priority: Medium High (2)
+ +Avoid inline JavaScript. Import .js files instead.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.vm.rule.design.NoInlineJavaScriptRule
+ +Use this rule by referencing it:
+<rule ref="category/vm/design.xml/NoInlineJavaScript" />
+
Since: PMD 5.1
+ +Priority: Medium High (2)
+ +Avoid inline styles. Use css classes instead.
+ +This rule is defined by the following XPath expression:
+//Text[matches(@literal, "<[^>]+\s[sS][tT][yY][lL][eE]\s*=")]
+
Use this rule by referencing it:
+<rule ref="category/vm/design.xml/NoInlineStyles" />
+
Since: PMD 5.1
+ +Priority: Medium High (2)
+ +Empty foreach statements should be deleted.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.vm.rule.errorprone.EmptyForeachStmtRule
+ +Use this rule by referencing it:
+<rule ref="category/vm/errorprone.xml/EmptyForeachStmt" />
+
Since: PMD 5.1
+ +Priority: Medium High (2)
+ +Empty if statements should be deleted.
+ +This rule is defined by the following Java class: net.sourceforge.pmd.lang.vm.rule.errorprone.EmptyIfStmtRule
+ +Use this rule by referencing it:
+<rule ref="category/vm/errorprone.xml/EmptyIfStmt" />
+
Basic XML (rulesets/xml/basic.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ + +Since: PMD 5.0
+ +Priority: Medium (3)
+ +An XML CDATA section begins with a <![CDATA[ marker, which has only one [, and ends with a ]]> marker, which has two ].
+ +This rule is defined by the following XPath expression:
+//cdata-section[starts-with(@Image,'[') or ends-with(@Image,']')]
+
Example(s):
+ +<root>
+ <child>
+ <![CDATA[[ character data ]]> - this cdata section is valid, but it contains an
+ additional square bracket at the beginning.
+ It should probably be just <![CDATA[ character data ]]>.
+ </child>
+ <child>
+ <![CDATA[ character data ]]]> - this cdata section is valid, but it contains an
+ additional square bracket in the end.
+ It should probably be just <![CDATA[ character data ]]>.
+ </child>
+</root>
+
Use this rule by referencing it:
+<rule ref="category/xml/errorprone.xml/MistypedCDATASection" />
+
XPath in XSL (rulesets/xsl/xpath.xml
):
Deprecated This ruleset is for backwards compatibility.
+ +It contains the following rules:
+ + +Since: PMD 5.0
+ +Priority: Medium (3)
+ +The XPath concat() functions accepts as many arguments as required so you can have +"concat($a,’b’,$c)" rather than "concat($a,concat(‘b’,$c)".
+ +This rule is defined by the following XPath expression:
+//node()[contains(substring-after(@select,'concat'),'concat')]
+
Example(s):
+ +<xsl:variable name="var" select="concat("Welcome",concat("to you ",$name))"/>
+<xsl:variable name="var" select="concat("Welcome","to you ",$name))">
+
+
+Use this rule by referencing it:
+<rule ref="category/xsl/codestyle.xml/UseConcatOnce" />
+
Since: PMD 5.0
+ +Priority: Medium (3)
+ +Avoid using the ‘following’ or ‘preceding’ axes whenever possible, as these can cut +through 100% of the document in the worst case. Also, try to avoid using ‘descendant’ +or ‘descendant-or-self’ axes, as if you’re at the top of the Document, it necessarily means +cutting through 100% of the document.
+ +This rule is defined by the following XPath expression:
+//node()[
+ contains(@select,'preceding::')
+ or
+ contains(@select,'following::')
+ or
+ contains(@select,'descendant::')
+ or
+ contains(@select,'descendant-self::')
+ or (
+ ($checkSelfDescendantAbreviation = true() )
+ and
+ contains(@select,'//')
+ )
+]
+
Example(s):
+ +<xsl:variable name="var" select="//item/descendant::child"/>
+
+
+This rule has the following properties:
+ +Name | +Default Value | +Description | +Multivalued | +
---|---|---|---|
checkSelfDescendantAbreviation | +false | +descendant::self abreviation, ‘//’, will also trigger this rule. | +no | +
Use this rule with the default properties by just referencing it:
+<rule ref="category/xsl/performance.xml/AvoidAxisNavigation" />
+
Use this rule and customize it:
+<rule ref="category/xsl/performance.xml/AvoidAxisNavigation">
+ <properties>
+ <property name="checkSelfDescendantAbreviation" value="false" />
+ </properties>
+</rule>
+
Running every existing rule will result in a huge number of rule violations, most of which will be unimportant. +Having to sort through a thousand line report to find the few you’re really interested in takes +all the fun out of things.
+ +Instead, start with some selected specific rules, e.g. the rules that detect unused code from +the category Best Practices and fix any unused locals and fields.
+ +Then, run rules, that detect empty if
statements and such-like. You can find these rules in the category
+Error Prone.
After that, look at all the categories and select the rules, that are useful for your project. +You can find an overview of the rules on the Rule Index.
+ +Use the rules you like via a custom ruleset.
+ +Generally, pick the ones you like, and ignore or suppress +the warnings you don’t like. It’s just a tool.
+ +Using PMD within your IDE is much more enjoyable than flipping back and forth +between an HTML report and your IDE. Most IDE plugins have the “click on the rule +violation and jump to that line of code” feature. Find the PMD plugin for your IDE, install it, +and soon you’ll be fixing problems much faster.
+ +Suggestions? Comments? Post them here. Thanks!
+ + + + + + +The tool comes with a rather extensive help text, simply running with -help
!
Option | +Description | +Default value | +Applies to | +
---|---|---|---|
-rulesets <refs> -R <refs> |
+ Required Comma-separated list of ruleset or rule references. | +
|
+ + |
-dir <path> -d <path> |
+ Required Root directory for the analyzed sources. | +
|
+ + |
-format <format> -f <format> |
+ Output format of the analysis report. The available formats + are described here. | +text |
+ + |
-auxclasspath <cp> |
+ Specifies the classpath for libraries used by the source code.
+ This is used to resolve types in source files. The platform specific path delimiter
+ (":" on Linux, ";" on Windows) is used to separate the entries.
+ Alternatively, a single file: URL
+ to a text file containing path elements on consecutive lines can be specified. |
+
|
+ Java | +
-benchmark -b |
+ Enables benchmark mode, which outputs a benchmark report upon completion. + The report is sent to standard error. | +
|
+ + |
-cache <filepath> |
+ Specify the location of the cache file for incremental analysis. + This should be the full path to the file, including the desired file name (not just the parent directory). + If the file doesn't exist, it will be created on the first run. The file will be overwritten on each run + with the most up-to-date rule violations. + This can greatly improve analysis performance and is highly recommended. | +
|
+ + |
-debug -verbose -D -V |
+ Debug mode. Prints more log output. | +
|
+ + |
-encoding <charset> -e <charset> |
+ Specifies the character set encoding of the source code files PMD is reading.
+ The valid values are the standard character sets of java.nio.charset.Charset . |
+ UTF-8 |
+ + |
-failOnViolation <bool> --failOnViolation <bool> |
+ Specifies whether PMD exits with non-zero status if violations are found.
+ By default PMD exits with status 4 if violations are found.
+ Disable this feature with -failOnViolation false to exit with 0 instead and just output the report. |
+ true |
+ + |
-filelist <filepath> |
+ Path to file containing a comma delimited list of files to analyze.
+ If this is given, then you don't need to provide -dir . |
+
|
+ + |
-ignorelist <filepath> |
+ Path to file containing a comma delimited list of files to ignore.
+ This option can be combined with -dir and -filelist .
+ This ignore list takes precedence over any files in the filelist. |
+
|
+ + |
-help -h -H |
+ Display help on usage. | +
|
+ + |
-language <lang> -l <lang> |
+ Specify the language PMD should use. Used together with -version . See also Supported Languages. |
+
|
+ + |
-minimumpriority <num> -min <num> |
+ Rule priority threshold; rules with lower priority than configured here won't be used. | +5 |
+ + |
-norulesetcompatibility |
+ Disable automatic fixing of invalid rule references. Without the switch, PMD tries to automatically replace rule references that point to moved or renamed rules with the newer location if possible. Disabling it is not recommended. | +
|
+ + |
-no-cache |
+ Explicitly disables incremental analysis. This switch turns off suggestions to use Incremental Analysis,
+ and causes the -cache option to be discarded if it is provided. |
+
|
+ + |
-property <name>=<value> -P <name>=<value> |
+ Specifies a property for the report renderer. The option can be specified several times. | +[] |
+ + |
-reportfile <path> -r <path> |
+ Path to a file in which the report output will be sent. By default the report is printed on standard output. | +
|
+ + |
-shortnames |
+ Prints shortened filenames in the report. | +
|
+ + |
-showsuppressed |
+ Causes the suppressed rule violations to be added to the report. | +
|
+ + |
-stress -S |
+ Performs a stress test. | +
|
+ + |
-suppressmarker <marker> |
+ Specifies the comment token that marks lines which PMD should ignore. | +NOPMD |
+ + |
-threads <num> -t <num> |
+ Sets the number of threads used by PMD.
+ Set threads to 0 to disable multi-threading processing. |
+ 1 |
+ + |
-uri <uri> -u <uri> |
+ Database URI for sources. If this is given, then you don't need to provide -dir . |
+
|
+ PLSQL | +
-version <version> -v <version> |
+ Specify the version of a language PMD should use. Used together with -language . See also Supported Languages. |
+
|
+ + |
PMD is executed via a Java runtime. In some cases, you might need to set additional runtime options, e.g. +if you want to analyze a project, that uses one of OpenJDK’s Preview Language Features.
+ +Just set the environment variable PMD_JAVA_OPTS
before executing PMD, e.g.
export PMD_JAVA_OPTS="--enable-preview"
+./run.sh pmd -d ../../../src/main/java/ -f text -R rulesets/java/quickstart.xml
+
Please note that if PMD detects any violations, it will exit with status 4 (since 5.3). +This behavior has been introduced to ease PMD integration into scripts or hooks, such as SVN hooks.
+ +0 | Everything is fine, no violations found |
1 | Couldn't understand command-line parameters or PMD exited with an exception |
4 | At least one violation has been detected, unless -failOnViolation false is set. |
The language is determined automatically by PMD from the file extensions. Some languages such as “Java”
+however support multiple versions. The default version will be used, which is usually the latest supported
+version. If you want to use an older version, so that e.g. rules, that suggest usage of language features,
+that are not available yet, won’t be executed, you need to specify a specific version via the -language
+and -version
parameter.
These parameters are irrelevant for languages that don’t support different versions.
+ +Example:
+ +./run.sh pmd -d src/main/java -f text -R rulesets/java/quickstart.xml -language java -version 8
+
PMD comes with many different renderers. +All formats are described at PMD Report formats
+ + + + + + + +You can change a rule’s message by specifying a message
+attribute on the rule element. This will override the previous
+value and change the message the rule will print on the report.
Similarly, the priority of a rule can be changed via a nested
+element. Using priority, you can deactivate some rules based on a
+minimum priority threshold (set using the -min
CLI option).
+Priority is an integer ranging from 1 to 5, with 1 being the highest
+priority.
Putting things together, the following rule reference lowers the priority
+of EmptyCatchBlock to 5, such that e.g. using the -min 4
CLI parameters
+will cause the rule to be ignored.
<rule ref="category/java/errorprone.xml/EmptyCatchBlock"
+ message="Empty catch blocks should be avoided" >
+ <priority>5</priority>
+</rule>
+
Properties make it easy to customise the behaviour of a rule directly from the xml. They come in several types, which correspond to the type of their values. For example, NPathComplexity declares a property “reportLevel”, with an integer value type, and which corresponds to the threshold above which a method will be reported. If you believe that its default value of 200 is too high, you could lower it to e.g. 150 in the following way:
+ +<rule ref="category/java/design.xml/NPathComplexity">
+ <properties>
+ <property name="reportLevel">
+ <value>150</value>
+ </property>
+ </properties>
+</rule>
+
Properties are assigned a value with a property
element, which should mention the name of a property as an attribute. The value of the property can be specified either in the content of the element, like above, or in the value
attribute, e.g.
<property name="reportLevel" value="150"/>
+
All property assignments must be enclosed in a properties
element, which is itself inside a rule
element.
Some properties take multiple values (a list), in which case you can provide them all by delimiting them with a delimiter character. It is usually a pipe (‘|’), or a comma (‘,’) for numeric properties, e.g.
+ <property name="legalCollectionTypes"
+ value="java.util.ArrayList|java.util.Vector|java.util.HashMap"/>
+
These properties are referred to as multivalued properties in this documentation.
+ + + + + + +Duplicate code can be hard to find, especially in a large project. +But PMD’s Copy/Paste Detector (CPD) can find it for you!
+ +CPD works with Java, JSP, C/C++, C#, Go, Kotlin, Ruby, Swift and many more languages.
+It can be used via command-line, or via an Ant task.
+It can also be run with Maven by using the cpd-check
goal on the Maven PMD Plugin.
Your own language is missing? +See how to add it here.
+ +It’s certainly important to know where to get CPD, and how to call it, but it’s worth stepping back for a moment and asking yourself why you should care about this, being the occurrence of duplicate code blocks.
+ +Assuming duplicated blocks of code are supposed to do the same thing, any refactoring, even simple, must be duplicated too – which is unrewarding grunt work, and puts pressure on the developer to find every place in which to perform the refactoring. Automated tools like CPD can help with that to some extent.
+ +However, failure to keep the code in sync may mean automated tools will no longer recognise these blocks as duplicates. This means the task of finding duplicates to keep them in sync when doing subsequent refactorings can no longer be entrusted to an automated tool – adding more burden on the maintainer. Segments of code initially supposed to do the same thing may grow apart undetected upon further refactoring.
+ +Now, if the code may never change in the future, then this is not a problem.
+ +Otherwise, the most viable solution is to not duplicate. If the duplicates are already there, then they should be refactored out. We thus advise developers to use CPD to help remove duplicates, not to help keep duplicates in sync.
+ +Once you have located some duplicates, several refactoring strategies may apply depending of the scope and extent of the duplication. Here’s a quick summary:
+ +Novice as much as advanced readers may want to read on on Refactoring Guru for more in-depth strategies, use cases and explanations.
+ +Option | +Description | +Default | +Applies to | +
---|---|---|---|
--minimum-tokens |
+ Required The minimum token length which should be reported as a duplicate. | +
|
+ + |
--files |
+ Required List of files and directories to process | +
|
+ + |
--filelist |
+ Path to file containing a comma delimited list of files to analyze. If this is given, then you don't need to provide --files . |
+
|
+ + |
--language |
+ Sources code language. | +java |
+ + |
--encoding |
+ Character encoding to use when processing files. If not specified, CPD uses the system default encoding. | +
|
+ + |
--skip-duplicate-files |
+ Ignore multiple copies of files of the same name and length in comparison. | +false |
+ + |
--exclude |
+ Files to be excluded from CPD check | +
|
+ + |
--non-recursive |
+ Don't scan subdirectories | +false |
+ + |
--skip-lexical-errors |
+ Skip files which can't be tokenized due to invalid characters instead of aborting CPD | +false |
+ + |
--format |
+ Report format. | +text |
+ + |
--failOnViolation <bool> |
+ By default CPD exits with status 4 if code duplications are found.
+ Disable this option with --failOnViolation false to exit with 0 instead and just write the report. |
+ true |
+ + |
--ignore-literals |
+ Ignore number values and string contents when comparing text | +false |
+ Java | +
--ignore-identifiers |
+ Ignore constant and variable names when comparing text | +false |
+ Java | +
--ignore-annotations |
+ Ignore language annotations when comparing text | +false |
+ Java | +
--ignore-usings |
+ Ignore using directives in C# when comparing text |
+ false |
+ C# | +
--no-skip-blocks |
+ Do not skip code blocks matched by --skip-blocks-pattern |
+ false |
+ C++ | +
--skip-blocks-pattern |
+ Pattern to find the blocks to skip. It is a string property and contains of two parts,
+ separated by | . The first part is the start pattern, the second part is the ending pattern. |
+ #if 0|#endif |
+ C++ | +
--uri |
+ URI to process | +
|
+ PLSQL | +
--help -h |
+ Print help text | +false |
+ + |
Note: The following example use the Linux start script. For Windows, just replace “./run.sh cpd” by “cpd.bat”.
+ +Minimum required options: Just give it the minimum duplicate size and the source directory:
+ +$ ./run.sh cpd --minimum-tokens 100 --files /usr/local/java/src/java
+
You can also specify the language:
+ +$ ./run.sh cpd --minimum-tokens 100 --files /path/to/c/source --language cpp
+
You may wish to check sources that are stored in different directories:
+ +$ ./run.sh cpd --minimum-tokens 100 --files /path/to/other/source --files /path/to/other/source --files /path/to/other/source --language fortran
+
There should be no limit to the number of ‘–files’, you may add… But if you stumble one, please tell us !
+ +And if you’re checking a C source tree with duplicate files in different architecture directories +you can skip those using –skip-duplicate-files:
+ +$ ./run.sh cpd --minimum-tokens 100 --files /path/to/c/source --language cpp --skip-duplicate-files
+
You can also specify the encoding to use when parsing files:
+ +$ ./run.sh cpd --minimum-tokens 100 --files /usr/local/java/src/java --encoding utf-16le
+
You can also specify a report format - here we’re using the XML report:
+ +$ ./run.sh cpd --minimum-tokens 100 --files /usr/local/java/src/java --format xml
+
The default format is a text report, and there’s also a csv
report.
Note that CPD is pretty memory-hungry; you may need to give Java more memory to run it, like this:
+ +$ export PMD_JAVA_OPTS=-Xmx512m
+$ ./run.sh cpd --minimum-tokens 100 --files /usr/local/java/src/java
+
In order to change the heap size under Windows, you’ll need to edit the batch file cpd.bat
or
+set the environment variable PMD_JAVA_OPTS
prior to starting CPD:
C:\ > cd C:\pmd-bin-6.30.0-SNAPSHOT\bin
+C:\...\bin > set PMD_JAVA_OPTS=-Xmx512m
+C:\...\bin > .\cpd.bat --minimum-tokens 100 --files c:\temp\src
+
If you specify a source directory but don’t want to scan the sub-directories, you can use the non-recursive option:
+ +$ ./run.sh cpd --minimum-tokens 100 --non-recursive --files /usr/local/java/src/java
+
Please note that if CPD detects duplicated source code, it will exit with status 4 (since 5.0). +This behavior has been introduced to ease CPD integration into scripts or hooks, such as SVN hooks.
+ +0 | Everything is fine, no code duplications found |
1 | Couldn't understand command line parameters or CPD exited with an exception |
4 | At least one code duplication has been detected unless '--failOnViolation false' is used. |
For details, see CPD Report Formats.
+ +Andy Glover wrote an Ant task for CPD; here’s how to use it:
+ + <target name="cpd">
+ <taskdef name="cpd" classname="net.sourceforge.pmd.cpd.CPDTask" />
+ <cpd minimumTokenCount="100" outputFile="/home/tom/cpd.txt">
+ <fileset dir="/home/tom/tmp/ant">
+ <include name="**/*.java"/>
+ </fileset>
+ </cpd>
+ </target>
+
Attribute | +Description | +Default | +Applies to | +
---|---|---|---|
minimumtokencount |
+ Required A positive integer indicating the minimum duplicate size. | +
|
+ + |
encoding |
+ The character set encoding (e.g., UTF-8) to use when reading the source code files, but also when
+ producing the report. A piece of warning, even if you set properly the encoding value,
+ let's say to UTF-8, but you are running CPD encoded with CP1252, you may end up with not UTF-8 file.
+ Indeed, CPD copy piece of source code in its report directly, therefore, the source files
+ keep their encoding. + If not specified, CPD uses the system default encoding. |
+
|
+ + |
format |
+ The format of the report (e.g. csv , text , xml ). |
+ text |
+ + |
ignoreLiterals |
+ if true , CPD ignores literal value differences when evaluating a duplicate
+ block. This means that foo=42; and foo=43; will be seen as equivalent. You may want
+ to run PMD with this option off to start with and then switch it on to see what it turns up. |
+ false |
+ Java | +
ignoreIdentifiers |
+ Similar to ignoreLiterals but for identifiers; i.e., variable names, methods names, and so forth. |
+ false |
+ Java | +
ignoreAnnotations |
+ Ignore annotations. More and more modern frameworks use annotations on classes and methods, + which can be very redundant and trigger CPD matches. With J2EE (CDI, Transaction Handling, etc) + and Spring (everything) annotations become very redundant. Often classes or methods have the + same 5-6 lines of annotations. This causes false positives. | +false |
+ Java | +
ignoreUsings |
+ Ignore using directives in C#. | +false |
+ C# | +
skipDuplicateFiles |
+ Ignore multiple copies of files of the same name and length in comparison. | +false |
+ + |
skipLexicalErrors |
+ Skip files which can't be tokenized due to invalid characters instead of aborting CPD. | +false |
+ + |
skipBlocks |
+ Enables or disabled skipping of blocks like a pre-processor. See also option skipBlocksPattern. | +true |
+ C++ | +
skipBlocksPattern |
+ Configures the pattern, to find the blocks to skip. It is a string property and contains of two parts,
+ separated by | . The first part is the start pattern, the second part is the ending pattern. |
+ #if 0|#endif |
+ C++ | +
language |
+ Flag to select the appropriate language (e.g. c , cpp , cs , java , jsp , php , ruby , fortran
+ ecmascript , and plsql ). |
+ java |
+ + |
outputfile |
+ The destination file for the report. If not specified the console will be used instead. | +
|
+ + |
Also, you can get verbose output from this task by running ant with the -v
flag; i.e.:
ant -v -f mybuildfile.xml cpd
+
Also, you can get an HTML report from CPD by using the XSLT script in pmd/etc/xslt/cpdhtml.xslt. Just run +the CPD task as usual and right after it invoke the Ant XSLT script like this:
+ + <xslt in="cpd.xml" style="etc/xslt/cpdhtml.xslt" out="cpd.html" />
+
CPD also comes with a simple GUI. You can start it via some scripts in the bin
folder:
For Windows:
+ +cpdgui.bat
+
For Linux:
+ +./run.sh cpdgui
+
Here’s a screenshot of CPD after running on the JDK 8 java.lang package:
+ + + +Arbitrary blocks of code can be ignored through comments on Java, C/C++, Dart, Go, Javascript,
+Kotlin, Lua, Matlab, Objective-C, PL/SQL, Python, Swift and C# by including the keywords CPD-OFF
and CPD-ON
.
public Object someParameterizedFactoryMethod(int x) throws Exception {
+ // some unignored code
+
+ // tell cpd to start ignoring code - CPD-OFF
+
+ // mission critical code, manually loop unroll
+ goDoSomethingAwesome(x + x / 2);
+ goDoSomethingAwesome(x + x / 2);
+ goDoSomethingAwesome(x + x / 2);
+ goDoSomethingAwesome(x + x / 2);
+ goDoSomethingAwesome(x + x / 2);
+ goDoSomethingAwesome(x + x / 2);
+
+ // resume CPD analysis - CPD-ON
+
+ // further code will *not* be ignored
+ }
+
Additionally, Java allows to toggle suppression by adding the annotations
+@SuppressWarnings("CPD-START")
and @SuppressWarnings("CPD-END")
+all code within will be ignored by CPD.
This approach however, is limited to the locations were @SuppressWarnings
is accepted.
+It’s legacy and the new comment’s based approach should be favored.
//enable suppression
+ @SuppressWarnings("CPD-START")
+ public Object someParameterizedFactoryMethod(int x) throws Exception {
+ // any code here will be ignored for the duplication detection
+ }
+ //disable suppression
+ @SuppressWarnings("CPD-END)
+ public void nextMethod() {
+ }
+
Other languages currently have no support to suppress CPD reports. In the future, +the comment based approach will be extended to those of them that can support it.
+ +CPD has been through three major incarnations:
+ +First we wrote it using a variant of Michael Wise’s Greedy String Tiling algorithm (our variant is described +here).
+Then it was completely rewritten by Brian Ewins using the +Burrows-Wheeler transform.
+Finally, it was rewritten by Steve Hawkins to use the +Karp-Rabin string matching algorithm.
+CPD collects occurrences of found duplications and provides them to the selected report format. +Each found code duplication appears in one or more other files, so that each code duplication can +have multiple locations. Not all report formats display all locations.
+ +The following examples always describe the same duplications:
+ +This is the default format.
+ +All duplications are reported one after another. For each duplication, the complete code snippet is output.
+Each duplication is separated by ======
.
Example:
+ +Found a 33 line (239 tokens) duplication in the following files:
+Starting at line 32 of /home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/RuleReferenceTest.java
+Starting at line 68 of /home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/RuleReferenceTest.java
+
+ public void testOverride() {
+ final StringProperty PROPERTY1_DESCRIPTOR = new StringProperty("property1", "Test property", null, 0f);
+ MockRule rule = new MockRule();
+ rule.definePropertyDescriptor(PROPERTY1_DESCRIPTOR);
+ rule.setLanguage(LanguageRegistry.getLanguage(Dummy2LanguageModule.NAME));
+ rule.setName("name1");
+ rule.setProperty(PROPERTY1_DESCRIPTOR, "value1");
+ rule.setMessage("message1");
+ rule.setDescription("description1");
+ rule.addExample("example1");
+ rule.setExternalInfoUrl("externalInfoUrl1");
+ rule.setPriority(RulePriority.HIGH);
+
+ final StringProperty PROPERTY2_DESCRIPTOR = new StringProperty("property2", "Test property", null, 0f);
+ RuleReference ruleReference = new RuleReference();
+ ruleReference.setRule(rule);
+ ruleReference.definePropertyDescriptor(PROPERTY2_DESCRIPTOR);
+ ruleReference.setLanguage(LanguageRegistry.getLanguage(DummyLanguageModule.NAME));
+ ruleReference
+ .setMinimumLanguageVersion(LanguageRegistry.getLanguage(DummyLanguageModule.NAME).getVersion("1.3"));
+ ruleReference
+ .setMaximumLanguageVersion(LanguageRegistry.getLanguage(DummyLanguageModule.NAME).getVersion("1.7"));
+ ruleReference.setDeprecated(true);
+ ruleReference.setName("name2");
+ ruleReference.setProperty(PROPERTY1_DESCRIPTOR, "value2");
+ ruleReference.setProperty(PROPERTY2_DESCRIPTOR, "value3");
+ ruleReference.setMessage("message2");
+ ruleReference.setDescription("description2");
+ ruleReference.addExample("example2");
+ ruleReference.setExternalInfoUrl("externalInfoUrl2");
+ ruleReference.setPriority(RulePriority.MEDIUM_HIGH);
+
+ validateOverriddenValues(PROPERTY1_DESCRIPTOR, PROPERTY2_DESCRIPTOR, ruleReference);
+=====================================================================
+Found a 16 line (110 tokens) duplication in the following files:
+Starting at line 66 of /home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/JaxenXPathRuleQueryTest.java
+Starting at line 88 of /home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/JaxenXPathRuleQueryTest.java
+Starting at line 110 of /home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/JaxenXPathRuleQueryTest.java
+
+ JaxenXPathRuleQuery query = createQuery(xpath);
+ List<String> ruleChainVisits = query.getRuleChainVisits();
+ Assert.assertEquals(2, ruleChainVisits.size());
+ Assert.assertTrue(ruleChainVisits.contains("dummyNode"));
+ // Note: Having AST_ROOT in the rule chain visits is probably a mistake. But it doesn't hurt, it shouldn't
+ // match a real node name.
+ Assert.assertTrue(ruleChainVisits.contains(JaxenXPathRuleQuery.AST_ROOT));
+
+ DummyNodeWithListAndEnum dummy = new DummyNodeWithListAndEnum(1);
+ RuleContext data = new RuleContext();
+ data.setLanguageVersion(LanguageRegistry.findLanguageByTerseName("dummy").getDefaultVersion());
+
+ query.evaluate(dummy, data);
+ // note: the actual xpath queries are only available after evaluating
+ Assert.assertEquals(2, query.nodeNameToXPaths.size());
+ Assert.assertEquals("self::node()[(attribute::Test1 = \"false\")][(attribute::Test2 = \"true\")]", query.nodeNameToXPaths.get("dummyNode").get(0).toString());
+
This format uses XML to output the duplications in a more structured format.
+ +Example:
+ +<?xml version="1.0" encoding="UTF-8"?>
+<pmd-cpd>
+ <duplication lines="33" tokens="239">
+ <file column="29" endcolumn="75" endline="64" line="32"
+ path="/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/RuleReferenceTest.java"/>
+ <file column="37" endcolumn="75" endline="100" line="68"
+ path="/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/RuleReferenceTest.java"/>
+ <codefragment><![CDATA[ public void testOverride() {
+ final StringProperty PROPERTY1_DESCRIPTOR = new StringProperty("property1", "Test property", null, 0f);
+ MockRule rule = new MockRule();
+ rule.definePropertyDescriptor(PROPERTY1_DESCRIPTOR);
+ rule.setLanguage(LanguageRegistry.getLanguage(Dummy2LanguageModule.NAME));
+ rule.setName("name1");
+ rule.setProperty(PROPERTY1_DESCRIPTOR, "value1");
+ rule.setMessage("message1");
+ rule.setDescription("description1");
+ rule.addExample("example1");
+ rule.setExternalInfoUrl("externalInfoUrl1");
+ rule.setPriority(RulePriority.HIGH);
+
+ final StringProperty PROPERTY2_DESCRIPTOR = new StringProperty("property2", "Test property", null, 0f);
+ RuleReference ruleReference = new RuleReference();
+ ruleReference.setRule(rule);
+ ruleReference.definePropertyDescriptor(PROPERTY2_DESCRIPTOR);
+ ruleReference.setLanguage(LanguageRegistry.getLanguage(DummyLanguageModule.NAME));
+ ruleReference
+ .setMinimumLanguageVersion(LanguageRegistry.getLanguage(DummyLanguageModule.NAME).getVersion("1.3"));
+ ruleReference
+ .setMaximumLanguageVersion(LanguageRegistry.getLanguage(DummyLanguageModule.NAME).getVersion("1.7"));
+ ruleReference.setDeprecated(true);
+ ruleReference.setName("name2");
+ ruleReference.setProperty(PROPERTY1_DESCRIPTOR, "value2");
+ ruleReference.setProperty(PROPERTY2_DESCRIPTOR, "value3");
+ ruleReference.setMessage("message2");
+ ruleReference.setDescription("description2");
+ ruleReference.addExample("example2");
+ ruleReference.setExternalInfoUrl("externalInfoUrl2");
+ ruleReference.setPriority(RulePriority.MEDIUM_HIGH);
+
+ validateOverriddenValues(PROPERTY1_DESCRIPTOR, PROPERTY2_DESCRIPTOR, ruleReference);]]></codefragment>
+ </duplication>
+ <duplication lines="16" tokens="110">
+ <file column="9" endcolumn="28" endline="81" line="66"
+ path="/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/JaxenXPathRuleQueryTest.java"/>
+ <file column="9" endcolumn="28" endline="103" line="88"
+ path="/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/JaxenXPathRuleQueryTest.java"/>
+ <file column="9" endcolumn="28" endline="125" line="110"
+ path="/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/JaxenXPathRuleQueryTest.java"/>
+ <codefragment><![CDATA[ JaxenXPathRuleQuery query = createQuery(xpath);
+ List<String> ruleChainVisits = query.getRuleChainVisits();
+ Assert.assertEquals(2, ruleChainVisits.size());
+ Assert.assertTrue(ruleChainVisits.contains("dummyNode"));
+ // Note: Having AST_ROOT in the rule chain visits is probably a mistake. But it doesn't hurt, it shouldn't
+ // match a real node name.
+ Assert.assertTrue(ruleChainVisits.contains(JaxenXPathRuleQuery.AST_ROOT));
+
+ DummyNodeWithListAndEnum dummy = new DummyNodeWithListAndEnum(1);
+ RuleContext data = new RuleContext();
+ data.setLanguageVersion(LanguageRegistry.findLanguageByTerseName("dummy").getDefaultVersion());
+
+ query.evaluate(dummy, data);
+ // note: the actual xpath queries are only available after evaluating
+ Assert.assertEquals(2, query.nodeNameToXPaths.size());
+ Assert.assertEquals("self::node()[(attribute::Test1 = \"false\")][(attribute::Test2 = \"true\")]", query.nodeNameToXPaths.get("dummyNode").get(0).toString());]]></codefragment>
+ </duplication>
+</pmd-cpd>
+
This outputs the duplication as comma separated values. It only reports the duplication size (number +of lines and tokens) and the number of occurrences. After that, the begin lines and filenames are reported on +after another.
+ +Example:
+ +lines,tokens,occurrences
+33,239,2,32,/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/RuleReferenceTest.java,68,/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/RuleReferenceTest.java
+16,110,3,66,/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/JaxenXPathRuleQueryTest.java,88,/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/JaxenXPathRuleQueryTest.java,110,/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/JaxenXPathRuleQueryTest.java
+
This format is similar to “csv”, but it has one difference: The duplication size in number of lines is reported +for each occurrence separately. While the tokens are the same, due to formatting or comments, the code blocks might be +different. Whitespace and comments are usually ignored when finding duplicated code.
+ +In each line, the duplication size in tokens is reported, then the number of occurrences. And after that, for each +file, the begin line, the number of duplicated lines and the filename.
+ +Example:
+ +tokens,occurrences
+239,2,32,33,/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/RuleReferenceTest.java,68,33,/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/RuleReferenc
+eTest.java
+110,3,66,16,/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/JaxenXPathRuleQueryTest.java,88,16,/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/JaxenXPathRuleQueryTest.java,110,16,/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/JaxenXPathRuleQueryTest.java
+
This outputs the duplication in a format, that Visual Studio. CPD can be added as a external tool and the output +is shown in the console. You can then click on the filenames to jump to the source where the duplication is located.
+ +Each occurrence of a duplication is reported in a separate line, that’s why in this example, we have 5 lines.
+ +Example:
+ +/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/RuleReferenceTest.java(32): Between lines 32 and 65
+/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/RuleReferenceTest.java(68): Between lines 68 and 101
+/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/JaxenXPathRuleQueryTest.java(66): Between lines 66 and 82
+/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/JaxenXPathRuleQueryTest.java(88): Between lines 88 and 104
+/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/JaxenXPathRuleQueryTest.java(110): Between lines 110 and 126
+
Rule properties are a way to make your rules configurable directly from the +ruleset XML. Their usage is described on the Configuring Rules page.
+ +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… Chances are there is some detail +that can be abstracted away from your implementation, and in that case, this +page can help you squeeze that sweet flexibility out of your rule.
+ +The basic thing you need to do as a developer is to define a property descriptor and declare that your rule uses it. A property descriptor defines a number of attributes for your property:
+Don’t worry, all of these attributes can be specified in a single Java statement (or xml element for XPath rules).
+ +The procedure to define a property is quite straightforward:
+PropertyFactory
definePropertyDescriptor(PropertyDescriptor)
` in the rule’s noarg constructor.You can then retrieve the value of the property at any time using getProperty(PropertyDescriptor)
.
Properties can be built using type-specific builders, which can be obtained
+from the factory methods of PropertyFactory
. For example, to build a
+string property, you’d call
PropertyFactory.stringProperty("myProperty")
+ .desc("This is my property")
+ .defaultValue("foo")
+ .build();
+
This is fairly more readable than a constructor call, but keep in mind the description and the default value are not optional.
+ +For numeric properties, you can add constraints on the range of acceptable values, e.g.
+PropertyFactory.intProperty("myIntProperty")
+ .desc("This is my property")
+ .defaultValue(3)
+ .require(positive())
+ .range(0, 100)
+ .build();
+
The positive
method is part of
+the NumericConstraints
class, which provides some
+other constraints. The constraint mechanism will be completely unlocked with 7.0.0,
+since we’ll be migrating our API to Java 8.
Enumerated properties 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:
+static Map<String, ModeStrategy> map = new HashMap<>();
+
+static {
+ map.put("easyMode", new EasyStrategy());
+ map.put("hardMode", new HardStrategy());
+}
+
+static PropertyDescriptor<ModeStrategy> modeProperty
+ = PropertyFactory.enumProperty("modeProperty", map)
+ .desc("This is my property")
+ .defaultValue(new EasyStrategy())
+ .build();
+
You can see an example of properties used in a PMD rule here. +There are several things to notice here:
+static final
, which should generally be
+the case, as descriptors are immutable and can be shared between instances of the same rule;definePropertyDescriptor
` in the constructor,
+which ensures the property gets recognised by PMD at the time the properties
+are overridden (which happens before rule execution);visit
methods (typically on the highest node in the tree, since the property
+doesn’t change).XPath rules can also define their own properties. To do so, you must add a property
element in the properties
element of your rule, which declares the type
attribute. This attribute conditions what type the underlying property has, and can have the following values:
type attribute |
+ XSD type | +
---|---|
Integer | +xs:integer | +
Long | +xs:integer | +
Double | +xs:decimal | +
Boolean | +xs:boolean | +
String | +xs:string | +
Character | +xs:string | +
Regex | +xs:string | +
Note that enumerated properties are not available in XPath rules (yet?).
+ +Properties defined in XPath also must declare the description
attribute.
+Numeric properties also expect the min
and max
attributes for now. Here are
+a few examples to sum it up:
<property name="stringProp" type="Boolean" value="true" description="A BooleanProperty."/>
+<property name="intProp" type="Integer" value="3" min="1" max="20" description="An IntegerProperty."/>
+
You can then use the property in XPath with the syntax $propertyName
, for example:
<rule name="MyXpathRule" ...>
+ <properties>
+ <property name="maxStatements" type="Integer" value="10" min="1" max="40"
+ description="Max number of statements per method"/>
+ <property name="xpath">
+ <![CDATA[
+ //MethodDeclaration/Block[count(//BlockStatement) > $maxStatements]
+ ]]></property>
+ </properties>
+</rule>
+
Multivalued properties are also allowed and their type
attribute has the form
+List[Boolean]
or List[Character]
, with every above type allowed. These
+properties require XPath 2.0 to work properly, and make use of the
+sequence datatype provided by that language. You thus need to set the
+version
property to 2.0
to use them. Properties can also declare the
+delimiter
attribute.
<rule name="MyXpathRule" ...>
+ <properties>
+ <property name="version" value="2.0" />
+ <property name="intProp" type="List[Integer]" value="1,2,5" description="An IntegerMultiProperty." />
+ <property name="reportedIdentifiers" type="List[String]" value="foo$bar" delimiter="$"
+ description="A StringMultiProperty." />
+ <property name="xpath">
+ <![CDATA[
+ //VariableDeclaratorId[@Image = $reportedIdentifiers]
+ ]]></property>
+ </properties>
+</rule>
+
Notice that in the example above, @Image = $reportedIdentifiers
doesn’t test
+@Image
for equality with the whole sequence ('foo', 'bar')
, it tests whether
+the sequence contains @Image
. That is, the above rule will report all variables
+named foo
or bar
. All other XPath 2.0 functions operating on sequences
+are supported.
The designer is part of PMD’s binary distributions. To install a distribution, see the documentation page about installing PMD.
+ +The app needs JRE 1.8 or above to run. Be aware that on JRE 11+, the JavaFX distribution should be installed separately. Visit the JavaFX download page to download a distribution, extract it, and set the JAVAFX_HOME environment variable.
+ +If the bin directory of your PMD distribution is on your shell’s path, then you can launch the app with
+ +run.sh designer on Linux/ OSX
+designer.bat on Windows
+
This is to allow easy updating, and let you choose the dependencies you’re interested in. +The available language modules are those on the classpath of the app’s JVM. That’s why it’s recommended to use the standard PMD startup scripts, which setup the classpath with the available PMD libraries.
+ +The latest version of the designer currently works with PMD 6.12.0 and above. You can simply replace pmd-ui-6.X.Y.jar with the latest build in the installation folder of your PMD distribution, and run it normally. Note that updating may cause some persisted state to get lost, for example the code snippet.
+ +The rule designer is both a tool to inspect the tree on which PMD rules run on, and to write XPath rules in an integrated manner. This page describes the features that enable this.
+ +You can enter source code in the middle zone.
+There are several ways to focus a node for inspection:
+Search
button and enter a search query. You can cycle through results with CTRL+TAB
or CTRL+F3
, and cycle back with CTRL+SHIFT+TAB
or CTRL+SHIFT+F3
The left panel displays the following information:
+ +The bottom part of the UI is dedicated to designing XPath rules:
+ + + +The center is an XPath expression. As you type it, the matched nodes are updated on the right, and highlighted on the code area. Autocompletion is available on some languages.
+ +Note: you can keep several rules in the editor (there’s a tab for each of them).
+ +Above the XPath expression area, the “Properties” button allows you to define new properties for your prototype rule. You can also edit the existing properties.
+ +When you click on it, a small popup appears:
+ + + +The popup contains in the center a list of currently defined properties, displaying their name and expected type.
+ +The edition menu of a property looks like the following:
+ + + +The little export icon next to the gear icon opens a menu to export your rule. This menu lets you fill-in the metadata necessary for an XPath rule to be included in a ruleset.
+ +PMD has its own XML format to describe rule tests and execute them using our test framework. The designer includes a test editor, which allows you to edit such files or create a new one directly as you edit the rule. This is what the panel left of the XPath expression area is for.
+ +See also the test framework documentation.
+ +A rule test describes
+When executing a test, the rule is run on the source with the given configuration, then the violations it finds are compared to the expected ones.
+ +Tests can be added in one of four ways:
+From the current source: A new test case with a default configuration is created, with the source that is currently in the editor
+With an empty source: A new test case with a default configuration is created, with an empty source file. You must edit the source yourself then.
+From an existing test case: Each test case list item has a “Copy” button which duplicates the test and loads the new one.
+In the designer, the test panel is a list of test cases. Their status (passing, failing, error, unknown) is color coded.
+ +All tests passing (green):
+ + + +A failing test (orange):
+ + + +Each test has a piece of source, which you can edit independently of the others, when the test is loaded in the editor. Additional rule configuration options can be chosen when the test is loaded.
+ +Loading is done with the Load button:
+ +Only one test case may be loaded at a time. If the loaded test is unloaded, the editor reverts back to the state it had before the first test case was loaded.
+ +When a test is loaded, the source you edit in the code area is the source of the test. Changes are independent from other tests, and from the piece of source that was previously in the editor.
+ +When a test is loaded, an additional toolbar shows up at the top of the code area:
+ + + +The “Expected violations” button is used to add or edit the expected violations.
+ +Initially the list of violations is empty. You can add violations by dragging and dropping nodes onto the button or its popup, from any control that displays nodes. For example:
+ +Rule properties can be configured for each test case independently using the “Property mapping” button. For example:
+ +This configuration will be used when executing the test to check its status.
+ +When you’re done editing tests, it’s a good idea to save the test file to an XML file. Exporting is done using the “Export” button above the list of test cases:
+ +Note that the exported file does not contain any information about the rule. The rule must be in a ruleset file somewhere else.
+ +If you want to use PMD’s test framework to use the test file in your build, please refer to the conventions explained in the test framework documentation.
+ + + + + + + +In PMD’s Metrics framework, a metric is an operation that can be carried out on nodes of a certain type and produces +a numeric result. In the Java framework, metrics can be computed on operation declaration nodes (constructor and +method declaration), and type declaration nodes (class, interface, enum, and annotation declarations). A metric +object in the framework can only handle either types or operations, but not both.
+ +PMD ships with a library of already implemented metrics. These metrics are referenced by MetricKey
objects,
+which are listed in two public enums: JavaClassMetricKey
and JavaOperationMetricKey
.
+Metric keys wrap a metric, and know which type of node their metric can be computed on. That way, you cannot compute an operation metric on a class
+declaration node. Metrics that can be computed on both operation and type declarations (e.g. NCSS) have one metric key in
+each enum.
XPath rules can compute metrics using the metric
function. This function takes a single string argument,
+which is the name of the metric key as defined in JavaClassMetricKey
or JavaOperationMetricKey
. The metric
+ will be computed on the context node.
The function will throw an exception in the following cases:
+ASTAnyTypeDeclaration
or MethodLikeNode
, that is,
+it’s not one of ASTClassOrInterfaceDeclaration
, ASTEnumDeclaration
, ASTMethodDeclaration
,
+ASTConstructorDeclaration
, or ASTLambdaExpression
.//ClassOrInterfaceDeclaration[metric('NCSS') > 200]
//MethodDeclaration[metric('CYCLO') > 10 and metric('NCSS') > 20]
//ClassOrInterfaceDeclaration[metric('CYCLO') > 50]
: IllegalArgumentException!
+CYCLO’s only defined for methods and constructors.The static façade class JavaMetrics
is the single entry point to compute metrics in the Java framework.
This class provides the method get
and its overloads. The following sections describes the interface of this class.
The simplest overloads of JavaMetrics.get
take two parameters: a MetricKey
and a node of the corresponding type.
+Say you want to write a rule to report methods that have a high cyclomatic complexity. In your rule’s visitor, you
+can get the value of Cyclo for a method node like so:
public Object visit(ASTMethodDeclaration method, Object data) {
+ int cyclo = (int) JavaMetrics.get(JavaOperationMetricKey.CYCLO, method);
+ if (cyclo > 10) {
+ // add violation
+ }
+ return data;
+}
+
The same goes for class metrics: you select one among JavaClassMetricKey
’s constants and pass it along with the node
+to JavaMetrics.get
.
AbstractJavaMetricsRule
) exists
+ to e.g. check constructors and method nodes completely alike. This comes
+ in handy for metrics, as they usually don’t make the distinctionMetrics are not necessarily computable on any node of the type they handle. For example, Cyclo cannot be computed on
+abstract methods. Metric keys provides a supports(Node)
boolean method
+to find out if the metric can be computed on
+the specified node. If the metric cannot be computed on the given node, JavaMetrics.get
will return Double.NaN
.
+If you’re concerned about that, you can condition your call on whether the node is supported or not:
public Object visit(ASTMethodDeclaration method, Object data) {
+ if (JavaOperationMetricKey.CYCLO.supports(node)) {
+ int cyclo = (int) JavaMetrics.get(JavaOperationMetricKey.CYCLO, method);
+ if (cyclo > 10) {
+ // add violation
+ }
+ return data;
+ }
+}
+
Some metrics define options that can be used to slightly modify the computation. You’ll typically see these options
+gathered inside an enum in the implementation class of the metric, for example CycloMetric.CycloOption
. They’re
+also documented on the index of metrics.
To use options with a metric, you must first bundle them into a MetricOptions
object. MetricOptions
provides the
+utility method ofOptions
to get a MetricOptions
bundle from a collection or with varargs parameters. You can then
+pass this bundle as a parameter to JavaMetrics.get
:
public Object visit(ASTMethodDeclaration method, Object data) {
+ int cyclo = (int) JavaMetrics.get(JavaOperationMetricKey.CYCLO, method,
+ MetricOptions.ofOptions(CycloOptions.IGNORE_BOOLEAN_PATHS));
+ if (cyclo > 10) {
+ // add violation
+ }
+ return data;
+}
+
The version of MetricOptions.ofOptions
using a collection is useful when you’re building a MetricOptions
from eg
+the value of an EnumeratedMultiProperty
, which gives users control of the options they use. See
+CyclomaticComplexityRule
+for an example usage.
The Metrics API also gives you the possibility to aggregate the result of an operation metric on all operations of a +class very simply. You can for example get the highest value of the metric over a class that way:
+public Object visit(ASTClassOrInterfaceDeclaration clazz, Object data) {
+ int highest = (int) JavaMetrics.get(JavaOperationMetricKey.CYCLO, clazz,
+ ResultOption.HIGHEST);
+ if (highest > 10) {
+ // add violation
+ }
+ return data;
+}
+
Notice that we use an operation metric and a class node. The ResultOption
parameter controls what result will be
+computed: you can choose among HIGHEST
, SUM
and AVERAGE
. You can use metric options together with a result
+option too.
The following is a sample code for a rule reporting methods with a cyclomatic +complexity over 10 and classes with a total cyclo over 50. A metric option can be +user-configured with a rule property. More complete examples can be found in +CyclomaticComplexityRule, +NcssCountRule, +or GodClassRule.
+ +public class CycloRule extends AbstractJavaMetricsRule {
+
+ public static final BooleanProperty COUNT_BOOLEAN_PATHS
+ = BooleanProperty.named("countBooleanPaths")
+ .desc("Count boolean paths")
+ .defaultValue(true).build();
+
+ private static final MetricOptions options;
+
+ public CycloRule() {
+ definePropertyDescriptor(COUNT_BOOLEAN_PATHS);
+ }
+
+ @Override
+ public Object visit(ASTCompilationUnit node, Object data) {
+ options = getProperty(COUNT_BOOLEAN_PATHS)
+ ? MetricOptions.ofOptions(CycloOptions.IGNORE_BOOLEAN_PATHS)
+ : MetricOptions.emptyOptions();
+ }
+
+ @Override
+ public Object visit(ASTAnyTypeDeclaration clazz, Object data) {
+ int total = (int) JavaMetrics.get(JavaOperationMetricKey.CYCLO, clazz,
+ options, ResultOption.SUM);
+
+ if (total > 50) {
+ // add violation
+ }
+
+ return data;
+ }
+
+ @Override
+ public Object visit(ASTMethodDeclaration method, Object data) {
+ int cyclo = (int) JavaMetrics.get(JavaOperationMetricKey.CYCLO, method,
+ options);
+ if (cyclo > 10) { // this is safe if the node is not supported, as (Double.NaN > 10) == false
+ // add violation
+ }
+ return data;
+ }
+}
+
There are already many metrics ready to use. We maintain the following documentation +pages to describe them all, including their usage and options:
+You can use the framework to customize the existing metrics at will, or define +new ones quite easily. Here’s some info to get you started. Again, the examples are for +the Java framework but it’s symmetrical in the Apex framework.
+ +AbstractJavaClassMetric
or
+AbstractJavaOperationMetric
)computeFor
method.
+This method takes a node of the type you want to handle, a bundle of options,
+and returns the result of the metric.supports
method.MetricOption
)
+and handle them as you see fit in your computeFor
methodMetricKeyUtil
’s of
method, specifying a name
+for your metric and an instance of your metric. You’re done and can use your
+metric key as if it were a standard one.equals
. The same instance of your metric will be used to
+compute the metric on the AST of different nodes so it should really be
+“functionnally pure”. That rule also makes you keep it simple and understandable
+which is nice.computeFor
method as you
+like it. But most metrics in our library are implemented following a few
+patterns you may want to look at:
+ Visitor metrics: Those metrics use one or more AST visitor to compute their +value. That’s especially good to implement metrics that count some kind of node, +e.g. NPath complexity +or NCSS. +Additionally, it makes your metric more easily generalisable to other node types.
+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
+a field or method, with info about its modifers and other node-specific info.
+ AbstractJavaClassMetric
has a few methods that allow you to count signatures
+ directly, see e.g. the metrics NOPA
+ and WOC.
You may have noticed that when you extend e.g. AbstractJavaClassMetric
, the
+computeFor
method you’re prompted to implement takes a node of type
+ASTAnyTypeDeclaration
as a parameter. That’s not a concrete node type, but
+an interface, implemented by several concrete node types. Basically that’s done
+so that class metrics are given the ability to be computed on any type
+declaration, and operation metrics on constructors and methods. Here are the
+concrete node types you can target with class and operation metrics, by language:
Language | +Java | +Apex | +
---|---|---|
Operation declaration | +ASTMethodOrConstructorDeclaration >: ASTMethodDeclaration , ASTConstructorDeclaration |
+ ASTMethod * |
+
Type declaration | +ASTAnyTypeDeclaration >: ASTEnumDeclaration , ASTAnnotationDeclaration , ASTClassOrInterfaceDeclaration |
+ ASTUserClassOrInterface >: ASTUserClass , ASTUserInterface |
+
*Apex method metrics are also applied to triggers by default (see #771). Finer capability checking is not available out of the box for now.
+ +What if you don’t want such a generalisation? The supports
method lets you
+define a predicate to check that the node is supported by your metric. For example,
+if your metric can only be computed on classes, you may override the default behaviour
+like so:
@Override
+public boolean supports(ASTAnyTypeDeclaration node) {
+ return node.getTypeKind() == TypeKind.CLASS;
+}
+
supports
method returns false
on a node, then
+ that node will never be passed as a parameter to computeFor
. That allows you
+ to write your computeFor
method without worrying about unsupported nodes.The supports
method already has a default implementation in the abstract base
+classes. Here’s the default behaviour by language and type of metric:
Language | +Java | +Apex | +
---|---|---|
Operation metrics | +supports constructors and non abstract methods | +supports any non abstract method (including triggers), except <init> , <clinit> , and clone |
+
Type declaration | +supports classes and enums | +supports classes | +
Here is a bunch of thing to do you may consider once your rule is “up and running”.
+ +Rule priority may, of course, changes a lot depending on the context of the project. However, you can use the following guidelines to assert the legitimate priority of your rule:
+ +For instance, let’s take the ExplicitCallToGC rule (“Do not explicitly trigger a garbage collection.”). Calling GC is a bad idea, but it doesn’t break the application. So we skip priority one. However, as explicit call to gc may really hinder application performances, we set for the priority 2.
+ +You should try to run the rule on a large code base, like the jdk source code for instance. This will help ensure that the rule does not raise exceptions when dealing with unusual constructs.
+ +If your rule is stateful, make sure that it is reinitialized correctly. The “-stress” command line option can be used as the files will then not be ordered but processed randomly. Running pmd with the “-stress” option several times and sorting the text output should produce identical results if the state information is correctly reset.
+ +When writing a new rule, using command line option “-benchmark” on a few rules can give an indication on how the rule compares to others. To get the full picture, use the rulesets/internal/all-java.xml ruleset with “-benchmark”.
+ +Rules which use the RuleChain to visit the AST are faster than rules which perform manual visitation of the AST. The difference is small for an individual Java rule, but when running 100s of rules, it is measurable. For XPath rules, the difference is extremely noticeable due to Jaxen overhead for AST navigation. Make sure your XPath rules using the RuleChain.
+ +(TODO How does one know except by running in a debugger or horrendous performance?).
+ + + + + + +Good rules have tests. At least a positive test case - a code example, that triggers the rule and reports +a violation - and a negative test case - a code example, that doesn’t trigger the rule - should be created. +Of course, the more tests, the better the rule is verified. If the rule is more complex or defines properties, +with which the behavior can be modified, then these different cases can also be tested.
+ +And if there is a bug fix for a rule, be it a false positive or a false negative case, it should be accompanied +with an additional test case, so that the bug is not accidentally reintroduced later on.
+ +PMD’s built-in rules are organized in rulesets, where all rules belonging to the same category are placed +in a single ruleset, such as “category/java/bestpractices.xml”. +Each category-ruleset has a single abstract base test class, from which the individual test classes inherit. +We have one test class per rule, which executes all test cases for a single rule. The actual test cases are +stored in separate XML files, for each rule a separate file is used.
+ +All the test classes inherit from net.sourceforge.pmd.testframework.PmdRuleTst
,
+which provides the seamless integration with JUnit. This base class determines the language, the category name
+and the rule name from the concrete test class. It then searches the test code on its own.
+E.g. the individual rule test class
+net.sourceforge.pmd.lang.java.rule.bestpractices.AbstractClassWithoutAbstractMethodTest
tests the
+rule with the name “AbstractClassWithoutAbstractMethod”, which is in the category “bestpractices” for the
+language “java”.
The test code (see below Test XML Reference) describes the test case completely with +the expected behavior like number of expected rule violations, where the violations are expected, and so on.
+ +When you are running the test class in your IDE (e.g. Eclipse or IntelliJ IDEA) you can also select a single +test case and just execute this one.
+ +The PmdRuleTst
class searches the XML file, that describes the test cases for a certain rule
+using the following convention:
+The XML file is a test resource, so it is searched in the tree under src/test/resources
.
The sub package xml
of the test class’s package should contain a file with the same name as the rule’s name
+which is under test.
For example, to test the rule “AbstractClassWithoutAbstractMethod”, the fully qualified test class is:
+ +net.sourceforge.pmd.lang.java.rule.bestpractices.AbstractClassWithoutAbstractMethodTest
+
The test code for the rule can be found in the file:
+ +src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/AbstractClassWithoutAbstractMethod.xml
+
In general, the class name and file name pattern for the test class and data is this:
+ +net.sourceforge.pmd.lang.<Language Terse Name>.rule.<Category Name>.<Rule Name>Test
+src/test/resources/net/sourceforge/pmd/lang/<Language Terse Name>/rule/<Category Name>/xml/<Rule Name>.xml
+
<RuleName>.xml
. Search for a class <Rule Name>Test
to find the
+unit test class for the given rule.This class inherits from PmdRuleTst
and is located in the package “bestpractices”, since the rule
+belongs to the category “Best Practices”:
package net.sourceforge.pmd.lang.java.rule.bestpractices;
+
+import net.sourceforge.pmd.testframework.PmdRuleTst;
+
+public class AbstractClassWithoutAbstractMethodTest extends PmdRuleTst {
+ // no additional unit tests
+}
+
@Test
to
+this test class.This is a stripped down example which just contains two test cases.
+ +<?xml version="1.0" encoding="UTF-8"?>
+<test-data
+ xmlns="http://pmd.sourceforge.net/rule-tests"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests https://pmd.sourceforge.io/rule-tests_1_0_0.xsd">
+
+ <test-code>
+ <description>concrete class</description>
+ <expected-problems>0</expected-problems>
+ <code><![CDATA[
+public class Foo {}
+ ]]></code>
+ </test-code>
+
+ <test-code>
+ <description>failure case</description>
+ <expected-problems>1</expected-problems>
+ <expected-linenumbers>1</expected-linenumbers>
+ <code><![CDATA[
+public abstract class Foo {}
+ ]]></code>
+ </test-code>
+</test-data>
+
Each test case is in an own <test-code>
element. The first defines 0 expected problems, means this code doesn’t
+trigger the rule. The second test case expects 1 problem. Since the rule violations also report the exact AST node,
+you can verify the line number, too.
The root element is <test-data>
. It can contain one or more <test-code>
and <code-fragment>
elements.
+Each <test-code>
element defines a single test case. <code-fragment>
elements are used to share code snippets
+between different test cases.
<test-code>
attributesThe <test-code>
elements understands three optional attributes:
reinitializeRule: By default, it’s true
, so each test case starts with a fresh instantiated rule. Set it
+to false
to reproduce cases, where the previous run has influences.
regressionTest: By default, it’s true
. Set it to false
, to ignore and skip a test case.
useAuxClasspath: By default, it’s true
. Set it to false
to reproduce issues which only
+appear without type resolution.
<test-code>
children<description>
: Short description of the test case. This will be the JUnit test name in the report.
+If applicable, this description should contain a reference to the bug number, this test case reproduces.
<rule-property>
: Optional rule properties, if the rule is configurable. Just add multiple elements, to
+set multiple properties for one test case. For an example, see below.
<expected-problems>
: The the raw number of expected rule violations, that this rule is expected to report.
+For false-positive test cases, this is always “0”. For false-negative test cases, it can be any positive number.
<expected-linenumbers>
: Optional element. It’s a comma separated list of line numbers.
+If there are rule violations reported, then this allows you to
+assert the line numbers. Useful if multiple violations should be detected and to be sure that
+false positives and negatives don’t erase each other.
<expected-messages>
: Optional element, with <message>
elements as children.
+Can be used to validate the correct error message, e.g. if the error message references a variable name.
<code>
: Either the <code>
element or the <code-ref>
element is required. It provides the actual code
+snippet on which the rule is executed. The code itself is usually wrapped in a “CDATA” section, so that no
+further XML escapes (entity references such as <) are necessary.
<code-ref id=...>
: Alternative to <code>
. References a <code-fragment>
defined earlier in the file.
+This allows you to share the same code snippet with several test cases. The attribute id
must match the
+id of the references code fragment.
<source-type>
: Optional element that specifies a specific language version. This can be used
+to select a specific parser version for parsing the code snippet. If not given, the default version of
+the rule’s language is used. This element can almost always be omitted.
<code-fragment>
The code fragment has just one required attribute: id. This is used to reference it via a <code-ref>
element
+inside a <test-code>
. Similar like the <code>
element, the content of <code-fragment>
is usually wrapped
+in a “CDATA” section, so that no further XML escapes (entity references such as <) are necessary.
<?xml version="1.0" encoding="UTF-8"?>
+<test-data
+ xmlns="http://pmd.sourceforge.net/rule-tests"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests https://pmd.sourceforge.io/rule-tests_1_0_0.xsd">
+
+ <test-code reinitializeRule="true" regressionTest="true" useAuxClasspath="true">
+ <description>Just a description, will be used as the test name for JUnit in the reports</description>
+ <rule-property name="somePropName">propValue</rule-property> <!-- optional -->
+ <expected-problems>2</expected-problems>
+ <expected-linenumbers>5,14</expected-linenumbers> <!-- optional -->
+ <expected-messages> <!-- optional -->
+ <message>Violation message 1</message>
+ <message>Violation message 2</message>
+ </expected-messages>
+ <code><![CDATA[
+public class ConsistentReturn {
+ public Boolean foo() {
+ }
+}
+ ]]></code>
+ <source-type>java 1.5</source-type> <!-- optional -->
+ </test-code>
+
+ <code-fragment id="codeSnippet1"><![CDATA[
+public class ConsistentReturn {
+ public Boolean foo() {
+ }
+}
+ ]]></code-fragment>
+
+ <test-code>
+ <description>test case using a code fragment</description>
+ <expected-problems>0</expected-problems>
+ <code-ref id="codeSnippet1"/>
+ </test-code>
+</test-data>
+
It is also possible to use the test framework for custom rules developed outside the PMD source base.
+Therefore you just need to reference the dependency net.sourceforge.pmd:pmd-test
.
For maven, you can use this snippet:
+ +<dependency>
+ <groupId>net.sourceforge.pmd</groupId>
+ <artifactId>pmd-test</artifactId>
+ <version>6.30.0-SNAPSHOT</version>
+ <scope>test</scope>
+</dependency>
+
Then proceed as described earlier: create your test class, create your test cases and run the unit test.
+ +There is one difference however: Since your package structure is probably different, you’ll need to register +the rule test manually, as SimpleAggregatorTst will fail to determine it correctly from the package and class names:
+ +package com.example.pmd.rules;
+
+import net.sourceforge.pmd.testframework.SimpleAggregatorTst;
+
+public class CustomRuleTest extends SimpleAggregatorTst {
+ @Override
+ public void setUp() {
+ addRule("com/example/pmd/ruleset.xml", "CustomRule");
+ }
+}
+
This will then search for a rule named “CustomRule” in the ruleset, that is located in “src/main/resources” under +the path “com/example/pmd/ruleset.xml”.
+ +The test data should be placed in an xml file located in “src/test/resources” under the path +“com/example/pmd/rules/xml/CustomRule.xml”.
+ +The framework uses a custom JUnit test runner under the hood, among a couple of utility classes:
+ +PmdRuleTst
: This is the base class for tests in PMD’s code base. It is a subclass of RuleTst
and just
+contains the logic to determine the test resources based on the test class name.
SimpleAggregatorTst
: This is a more generic base class for the test classes and defines
+the custom JUnit test runner. It doesn’t register any test cases on its own.
+It itself is a subclass of RuleTst
.
RuleTst
: contains the logic to parse the XML files and provide a list of TestDescriptor
s. Each test descriptor
+describes a single test case. It also contains the logic to execute such a test descriptor and assert the results.
PMDTestRunner
: A custom JUnit test runner, that combines two separate test runners: The custom RuleTestRunner
+and the standard JUnit4
test runner. This combination allows you to add additional standard unit test methods
+annotated with @Test
to your test class.
Note: Since the test class is executed through two test runners, it is actually instantiated twice. Be aware
+of this, if you do any initialization in the constructor. Also, the static hooks @BeforeClass
and @AfterClass
+will be executed twice.
RuleTestRunner
: This test runner executes the test descriptors with the help of RuleTst
.
This page covers the specifics of writing a rule in Java. The basic development +process is very similar to the process for XPath rules, which is described in +Your First Rule.
+ +Basically, you open the designer, look at the structure of the AST, and refine +your rule as you add test cases.
+ +In this page we’ll talk about rules for the Java language, but the process is +very similar for other languages.
+ +To write a rule in Java you’ll have to:
+Rule
. Each
+language implementation provides a base rule class to ease your pain,
+e.g. AbstractJavaRule
.Most base rule classes use a Visitor pattern +to explore the AST.
+ +When a rule is applied to a file, it’s handed the root of the AST and told
+to traverse all the tree to look for violations. Each rule defines a specific
+visit
method for each type of node for of the language, which
+by default just visits the children.
So the following rule would traverse the whole tree and do nothing:
+ +public class MyRule extends AbstractJavaRule {
+ // all methods are default implementations!
+}
+
Generally, a rule wants to check for only some node types. In our XPath example
+in Your First Rule,
+we wanted to check for some VariableDeclaratorId
nodes. That’s the XPath name,
+but in Java, you’ll get access to the ASTVariableDeclaratorId
+full API.
If you want to check for some specific node types, you can override the
+corresponding visit
method:
public class MyRule extends AbstractJavaRule {
+
+ @Override
+ public Object visit(ASTVariableDeclaratorId node, Object data) {
+ // This method is called on each node of type ASTVariableDeclaratorId
+ // in the AST
+
+ if (node.getType() == short.class) {
+ // reports a violation at the position of the node
+ // the "data" parameter is a context object handed to by your rule
+ // the message for the violation is the message defined in the rule declaration XML element
+ addViolation(data, node);
+ }
+
+ // this calls back to the default implementation, which recurses further down the subtree
+ return super.visit(node, data);
+ }
+}
+
The super.visit(node, data)
call is super common in rule implementations,
+because it makes the traversal continue by visiting all the descendants of the
+current node.
Sometimes you have checked all you needed and you’re sure that the descendants
+of a node may not contain violations. In that case, you can avoid calling the
+super
implementation and the traversal will not continue further down. This
+means that your callbacks (visit
implementations) won’t be called on the rest
+of the subtree. The siblings of the current node may be visited
+recursively nevertheless.
If you don’t care about the order in which the nodes are traversed (e.g. your +rule doesn’t maintain any state between visits), then you can monumentally +speed-up your rule by using the rulechain.
+ +That mechanism doesn’t recurse on all the tree, instead, your rule will only be +passed the nodes it is interested in. To use the rulechain correctly:
+addRuleChainVisit
+in its constructor.super.visit
in the methods.When starting execution, PMD will instantiate a new instance of your rule. +If PMD is executed in multiple threads, then each thread is using its own +instance of the rule. This means, that the rule implementation does not need to care about +threading issues, as PMD makes sure, that a single instance is not used concurrently +by multiple threads.
+ +However, for performance reasons, the rule instances are used for multiple files.
+This means, that the constructor of the rule is only executed once (per thread)
+and the rule instance is reused. If you rely on a proper initialization of instance
+properties, you can do the initialization e.g. in the visit-method of the ASTCompilationUnit
+node - which is visited first and only once per file. However, this
+solution would only work for rules written for the Java language. A language
+independent way is to override the method start
of the rule.
+The start method is called exactly once per file.
Exactly once:
+ +For each thread, a deep copy of the rule is created. Each thread is given +a different set of files to analyse. Then, for each such file, for each +rule copy:
+ + + + + + + + +The information on this page has been split into several separate pages. Please update your bookmarks:
+ +To go further:
+PMD is a framework to perform code analysis. You can create your own rules to +check for patterns specific to your codebase, or the coding practices of your +team.
+ +Before running rules, PMD parses the source file into a data structure called an +abstract syntax tree (AST). This tree represents the syntactic structure of the +code, and encodes syntactic relations between source code elements. For instance, +in Java, method declarations belong to a class: in the AST, the nodes representing +method declarations will be descendants of a node representing the declaration of +their enclosing class. This representation is thus much richer than the original +source code (which, for a program, is just a chain of characters), or the token +chain produced by a lexer (which is e.g. what Checkstyle works on). For example:
+ +Sample code (Java) | +AST | +
---|---|
+
+
|
+
+
+
|
+
Conceptually, PMD rules work by matching a “pattern” against the AST of a +file. +Rules explore the AST and find nodes that satisfy some conditions that are characteristic +of the specific thing the rule is trying to flag. Rules then report a violation on these nodes.
+ +ASTs are represented by Java classes deriving from Node
.
+Each PMD language has its own set of such classes, and its own rules about how
+these classes relate to one another, based on the grammar of the language. For
+example, all Java AST nodes extend JavaNode
.
The structure of the AST can be discovered through
+PMD supports two ways to define rules: using an XPath query, or using a +Java visitor. XPath rules are much easier to set up, since they’re defined +directly in your ruleset XML, and are expressive enough for nearly any task.
+ +On the other hand, some parts of PMD’s API are only accessible from Java, e.g. +accessing the usages of a declaration. And Java rules allow you to do some +complicated processing, to which an XPath rule couldn’t scale.
+ +In the end, choosing one strategy or the other depends on the difficulty of what +your rule does. I’d advise to keep to XPath unless you have no other choice.
+ +New rules must be declared in a ruleset before they’re referenced. This is the
+case for both XPath and Java rules. To do this, the rule
element is used, but
+instead of mentioning the ref
attribute, it mentions the class
attribute,
+with the implementation class of your rule.
net.sourceforge.pmd.lang.rule.XPathRule
Example:
+ +<rule name="MyJavaRule"
+ language="java"
+ message="Violation!"
+ class="com.me.MyJavaRule" >
+ <description>
+ Description
+ </description>
+ <priority>3</priority>
+</rule>
+
language
attribute will be required on all rule
+ elements that declare a new rule. Some base rule classes set the language implicitly in their
+ constructor, and so this is not required in all cases for the rule to work. But this
+ behavior will be discontinued in PMD 7, so missing language
attributes are
+ reported beginning with PMD 6.27.0 as a forward compatibility warning.To learn how to write a rule:
+ +To go further:
+This page describes some points of XPath rule support in more details. See +also the tutorial about how to write an XPath rule.
+ + + +PMD supports three XPath versions for now: 1.0, 2.0, and 1.0 compatibility mode.
+The version can be specified with the version
property in the rule definition, like so:
<property version="2.0" /> <!-- or "1.0", or "1.0 compatibility" -->
+
The default has always been version 1.0.
+ +As of PMD version 6.22.0, XPath versions 1.0 and the 1.0 compatibility mode are +deprecated. XPath 2.0 is superior in many ways, for example for its support for +type checking, sequence values, or quantified expressions. For a detailed +but approachable review of the features of XPath 2.0 and above, see the Saxon documentation.
+ +It is recommended that you migrate to 2.0 before 7.0.0, but we expect +to be able to provide an automatic migration tool when releasing 7.0.0. +See the migration guide below.
+ +XPath rules view the AST as an XML-like DOM, which is what the XPath language is +defined on. Concretely, this means:
+getXPathNodeName
+for the given node@SimpleName
of the Java node EnumDeclaration
is backed
+by the Java getter getSimpleName
.To represent attributes, we must map Java values to XPath Data Model (XDM) values. The conversion +depends on the XPath version used.
+ +On XPath 1.0 we map every Java value to an xs:string
value by using the toString
+of the object. Since XPath 1.0 allows many implicit conversions this works, but it
+causes some incompatibilities with XPath 2.0 (see the section about migration further
+ down).
XPath 2.0 is a strongly typed language, and so we use more precise type annotations.
+In the following table we refer to the type conversion function as conv
, a
+function from Java types to XDM types.
Java type T |
+ XSD type conv(T) |
+
---|---|
int |
+ xs:integer |
+
long |
+ xs:integer |
+
double |
+ xs:decimal |
+
float |
+ xs:decimal |
+
boolean |
+ xs:boolean |
+
String |
+ xs:string |
+
Character |
+ xs:string |
+
Enum<E> |
+ xs:string (uses Object::toString ) |
+
List<E> |
+ conv(E)* (a sequence type) ⚠️ List support is deprecated with 6.25.0. See below. |
+
The same conv
function is used to translate rule property values to XDM values.
List<E>
has been deprecated
+with PMD 6.25.0 and will be removed completely with PMD 7. The reason is that newer Saxon
+versions don’t support sequences as attributes anymore. Lists are still possible in Java-based
+rules but not with XPath.
+
+Multivalued rule properties
+are still supported.XPath 1.0 and 2.0 have some incompatibilities. The XPath 2.0 specification +describes them precisely. Those are however mostly corner cases and XPath +rules usually don’t feature any of them.
+ +The incompatibilities that are most relevant to migrating your rules are not +caused by the specification, but by the different engines we use to run +XPath 1.0 and 2.0 queries. Here’s a list of known incompatibilities:
+ +fn:
and string:
should not be mentioned explicitly.
+In XPath 2.0 mode, the engine will complain about an undeclared namespace, but
+the functions are in the default namespace. Removing the namespace prefixes fixes it.
+ fn:substring("Foo", 1)
→ substring("Foo", 1)
typeIs
must be prefixed
+with the namespace of the declaring module (pmd-java
).
+ typeIs("Foo")
→ pmd-java:typeIs("Foo")
"true"
and "false"
. In 2.0 mode though, boolean values are truly represented
+as boolean values, which in XPath may only be obtained through the functions
+true()
and false()
.
+If your XPath 1.0 rule tests an attribute like @Private="true"
, then it just
+needs to be changed to @Private=true()
when migrating. A type error will warn
+you that you must update the comparison. More is explained on issue #1244.
+ "true"
, 'true'
→ true()
"false"
, 'false'
→ false()
@BeginLine > "1"
+worked —that’s not the case in 2.0 mode.
+ @ArgumentCount > '1'
→ @ArgumentCount > 1
/Foo
matches the children of the root named Foo
.
+In XPath 2.0, that expression matches the root, if it is named Foo
. Consider the following tree:
+ Foo
+└─ Foo
+└─ Foo
+
Then /Foo
will match the root in XPath 2, and the other nodes (but not the root) in XPath 1.
+See eg an issue caused by this in Apex,
+with nested classes.
PMD provides some language-specific XPath functions to access semantic +information from the AST.
+ +On XPath 2.0, the namespace of custom PMD function must be explicitly mentioned.
+ + + +Java functions are in the namespace pmd-java
.
Function name | +Description (click for details) | ++ | |
---|---|---|---|
typeIs | +Tests a node's static type | ++ + | +|
+
+
+
+
+
+
+
+
+ + pmd-java:typeIs(xs:string) as xs:boolean ++ +
+
+
+
|
+ |||
typeIsExactly | +Tests a node's static type, ignoring subtypes | ++ + | +|
+
+
+
+
+
+
+
+
+ + pmd-java:typeIsExactly(xs:string) as xs:boolean ++ +
+
+
+
|
+ |||
metric | +Computes and returns the value of a metric | ++ + | +|
+
+
+
+
+
+
+
+
+ + pmd-java:metric(xs:string) as xs:decimal? ++ +
+
+
+
|
+
typeOf
function which is
+deprecated and whose usages should be replaced with uses of typeIs
or
+typeIsExactly
. That one will be removed with PMD 7.0.0.This page is a gentle introduction to rule writing, and the Rule Designer.
+ +Using the designer is useful both to write Java +rules and XPath rules, but it’s more specifically geared towards XPath rules. +This page uses a simple XPath rule to illustrate the common workflow. We assume +here that you already know what XPath is and how to read basic XPath queries. W3C +has a good tutorial here if +you don’t (in the context of XML only), and the Saxon documentation +features a comprehensive but approachable description of the syntax of XPath +expressions.
+ +The rule designer is a tool that packs a lot of features to help you develop XPath +rules quickly and painlessly. Basically, it allows you to examine the AST of a code +snippet and evaluate an XPath expression against it.
+ +Like for PMD and CPD, you can launch it using run.sh designer
on Linux/Unix
+and designer.bat
on Windows. The interface looks like the following:
The zone (2) is the main editor. When you write a code snippet in the + code area to the left, you’ll see that the tree to the right will be updated + automatically: it’s the AST of the code. + Note that the code snippet must be a syntactically valid compilation unit for the + language you’ve chosen, e.g. for Java, a compilation unit necessarily has a top-level + type declaration.
+ +If you select a node in the AST, its specific properties will also be displayed +in the panel (1): they’re the XPath attributes of the node. More on that later.
+ +The zone (3) is the XPath editor. If you enter an XPath query in that area, +it will be evaluated on the current AST and the results will be displayed in the +list to the bottom right.
+ +The basic development process is straightforward:
+ +Each time you test your rule against a different snippet, it’s a good idea to +save it to make test cases.
+ +In the following sections, we walk through several examples to refine your rule.
+ +Let’s say you want to prevent your coding team from naming variables of type
+short
after your boss, whose name is Bill. You try the designer on the following
+ offending code snippet:
+public class KeepingItSerious {
+
+ public void method() {
+ short bill; // LocalVariableDeclaration
+ }
+
+}
+
+
Examining the AST, you find out that the LocalVariableDeclaration has a VariableDeclaratorId
+descendant, whose Image
XPath attribute is exactly bill
. You thus write your first attempt
+in the XPath editor:
//VariableDeclaratorId[@Image = "bill"]
+
You can see the XPath result list is updated with the variable declarator.
+If you try the query against the following updated snippet though, you can
+see that the field declaration id is matched even though it’s not of type short
.
public class KeepingItSerious {
+
+ Delegator bill; // FieldDeclaration
+
+ public void method() {
+ short bill; // LocalVariableDeclaration
+ }
+
+}
+
You thus refine your XPath expression with an additional predicate, +based on your examination of the Type node of the field and local variable +declaration nodes.
+ +//VariableDeclaratorId[@Image = "bill" and ../../Type[@TypeImage = "short"]]
+
You estimate that your rule is now production ready, and you’d like to use it in your ruleset.
+The File > Export XPath to rule...
allows you to do that in a few clicks: just enter some
+additional metadata for your rule, and the popup will generate an XML element that you can
+copy-paste into your ruleset XML. The resulting element looks like so:
<rule name="DontCallBossShort"
+ language="java"
+ message="Boss wants to talk to you."
+ class="net.sourceforge.pmd.lang.rule.XPathRule" >
+ <description>
+TODO
+ </description>
+ <priority>3</priority>
+ <properties>
+ <property name="xpath">
+ <value>
+<![CDATA[
+//VariableDeclaratorId[../../Type[@TypeImage="short"] and @Image = "bill"]
+]]>
+ </value>
+ </property>
+ </properties>
+</rule>
+
You can notice that your XPath expression ends up inside a property +of a rule of type XPathRule, which is how XPath rules are implemented.
+ + + + + + +Ever since PMD 5.6.0, PMD has been able to perform Incremental Analysis.
+ +When performing Incremental Analysis for the first time, PMD will cache analysis data and results. +This allows subsequent analysis to only look into those files that are new / have changed. For +a typical development environment, where you only change a few files at a time, this can reduce +analysis time dramatically.
+ +The generated report will be exactly the same as it would if running without incremental analysis. +Files included in the final report will reflect exactly those files in your filesystem. Even if +untouched, files with violations will be listed with full detail. Therefore, its usage is highly recommended.
+ +Incremental analysis is enabled automatically once a location to store the cache has been defined.
+From command-line that is done through the -cache
argument, but support for the feature is
+available for tools integrating PMD such as Ant,
+Maven, and Gradle.
By default, PMD will suggest to use an analysis cache by logging a warning.
+If you’d like to disable this warning, or ignore the analysis cache for a
+few runs, you can use the -no-cache
switch.
On the following reasons, the complete cache file is considered invalid:
+ +auxclasspath
changed. The auxclasspath is used during
+type resolution. A changed auxclasspath can result for rules, that use type resolution, in different
+violations. Usually, if the auxclasspath is correct and type resolution works, the rules report less false-positives.
+To make sure, the correct violations are reported, the cache is considered invalid, if the auxclasspath has changed.The cache file consists of a header and a body. The header stores the information which is used to decided +whether the whole cache file is valid or not (see above). The following information is stored:
+ +The body contains an entry for every file that has been analyzed. For every file, the following information +is stored:
+ +You can think of the cache as a Map where the filepath is used as the key +and the violations found in previous runs are the value.
+ +The cache is in the end just a file with serialized data (binary). The implementation is
+FileAnalysisCache
.
When analyzing a file, PMD records the checksum of the file content and stores this +together with the violations in the cache file. When running PMD with the cache file, +PMD looks up the file in the cache and compares the checksums. +If the checksums match, then the file is not even parsed, the rules +are not executed and the violations for this file are entirely used from the cache. +If the checksum doesn’t match, then the cached violations are discarded (if there are any) +and the file is fully processed: the file is parsed and all the rules are run for it. +After we are done, the cache is updated with the new violations.
+ +This is possible. As long as the same PMD version and same ruleset is used on both branches. +Also note, that if the branch uses a different dependencies, the auxclasspath is different on both +classes, which invalidates the cache completely. If you project uses e.g. Maven for dependency +management and your branch uses different dependencies (either different version or completely different +artifacts), then the auxclasspath is changed.
+ +If files have been renamed on the branch, these files will be analyzed again since PMD uses +the file names to assign existing rule violations from the cache. Also, if the full path name +of the file changes, because the other branch is checked out at a different location, then all +the cached files don’t match.
+ +Apart from these restrictions, PMD will only analyze files that changed between runs. +If your previous run was on branch A and then you run on branch B using the same cache file, +it will only look at files that are different between the 2 branches.
+ +This is only possible, if the other machine uses the exact same path names. That means that +your project needs to be checked out into the same directory structure.
+ +Additionally, all the other restrictions apply (same PMD version, same ruleset, same auxclasspath, +same execution classpath).
+ +See also issue #2063 [core] Support sharing incremental analysis cache file across different machines.
+ + + + + + +A zip archiver, e.g.:
+ + +PMD is distributed as a zip archive, which includes both PMD and CPD. +You can download the latest binary distribution from the github releases page.
+ +Unzip it into any directory, optionally add the bin
subdirectory in your PATH
, and you’re good to go!
run.sh
, located inside the bin/
+ directory of the PMD distribution. The first argument is the name of the utility you want
+ to execute (‘pmd’, ‘designer’, …), e.g. PMD is launched via run.sh pmd
. The rest of
+ the arguments are specific to the utility used.pmd.bat
, cpd.bat
.The PMD command (pmd.bat
or run.sh pmd
) requires two options:
-d <path>
: path to the sources to analyse. This can be a file name, a directory, or a jar or zip file containing the
+sources.-R <path>
: the ruleset file you want to use. PMD uses xml configuration files, called rulesets, which specify
+which rules to execute on your sources. You can also run a single rule by referencing it using its category and
+name (more details here). For example, you can check for unnecessary
+modifiers on Java sources with -R category/java/codestyle.xml/UnnecessaryModifier
.rulesets/java/basic.xml
) are deprecated,
+ though you can still use them. PMD includes a quickstart ruleset for some languages (currently, Java)
+ as base configurations, which you can reference as e.g. rulesets/java/quickstart.xml
. You’re strongly
+ encouraged to create your own ruleset from the start though.Additionally, the following options, are specified most of the time even though they’re not required:
+-f <format>
: report format. PMD supports many report formats out of the box. You may want to start with the basic
+text
format (default) or xml
format. The supported formats are documented here.-auxclasspath <classpath>
: class path containing the compiled class files of the analysed Java sources, if any.
+Setting this up correctly allows PMD to do much deeper analysis using reflection. Some rules, such as MissingOverride,
+require it to function properly.The following shows a sample run of PMD with the text
format:
Like for PMD, CPD is started on Unix by run.sh cpd
and on Windows by cpd.bat
.
There are two required parameters:
+--files <path>
: path to the sources to analyse. This can be a file name, a
+directory or a jar or zip file containing the sources.--minimum-tokens <number>
: the minimum token length which should be reported as a duplicate.The following shows a sample run of CPD with the text
format:
The first step is to create a new empty ruleset. You can use the following template:
+ +<?xml version="1.0"?>
+
+<ruleset name="Custom Rules"
+ xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 https://pmd.sourceforge.io/ruleset_2_0_0.xsd">
+
+ <description>
+ My custom rules
+ </description>
+
+
+ <!-- Your rules will come here -->
+
+</ruleset>
+
To use the built-in rules PMD provides, you need to add some references to them. Here’s a +basic rule reference:
+ +<rule ref="category/java/errorprone.xml/EmptyCatchBlock" />
+
Adding that element into the ruleset
element adds the rule EmptyCatchBlock
+to your ruleset. This is a Java rule, so it will be executed on every Java file PMD encounters in
+its search space.
How to read the ref
attribute?
category/java/errorprone.xml
is a reference to the Java category errorprone
. Since PMD 6.0.0,
+all PMD built-in rules are sorted in one of eight categories, which are consistent across languages:
EmptyCatchBlock
is simply the name of the rule. If there were no rule with that name within the specified
+category, then PMD would fail before starting the analysis.How you can configure individual rules is described on Configuring Rules.
+ +You can also reference rules in bulk by referencing a complete category or ruleset, possibly excluding certain rules, like in the following:
+ +<rule ref="category/java/codestyle.xml">
+ <exclude name="WhileLoopsMustUseBraces"/>
+ <exclude name="IfElseStmtsMustUseBraces"/>
+</rule>
+
Here, the ref
attribute references a whole category. You can also use a file system path or classpath relative path. In any case, the path must address an accessible ruleset XML file.
/
character within PMD, so the same ruleset can be used on multiple platforms transparently.You can exclude some files from being processed by a ruleset using exclude patterns, with an optional overridding include pattern. A file will be excluded from processing when there is a matching exclude pattern, but no matching include pattern. This exclude/include technique works regardless of how PMD is used (e.g. command line, IDE, Ant), making it easier to keep application of your PMD rules consistent throughout your environment. Here is an example:
+ +<?xml version="1.0"?>
+<ruleset name="myruleset"
+ xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 https://pmd.sourceforge.io/ruleset_2_0_0.xsd">
+ <description>My ruleset</description>
+
+ <exclude-pattern>.*/some/package/.*</exclude-pattern>
+ <exclude-pattern>.*/some/other/package/FunkyClassNamePrefix.*</exclude-pattern>
+ <include-pattern>.*/some/package/ButNotThisClass.*</include-pattern>
+
+ <!-- Rules here ... -->
+
+</ruleset>
+
PMD can report the found rule violations in various formats. Some formats can +be customized further via properties. Violations might also be suppressed and there might +be processing errors or configuration errors. Not all report formats display all information.
+ +The header of the sections below are used to select the format on the command line, as
+arguments to the -format
option. When a format accepts properties,
+those can be specified with the -property
/ -P
option on the command-line.
-showsuppressed
is set.Renderer for Code Climate JSON format.
+ +This format is used when running PMD within Code Climate.
+The renderer will stream JSON objects, each object is a own issue (a PMD rule violation). Each issue
+is separated by the null character (\0
).
The format is specified here: https://github.com/codeclimate/platform/blob/master/spec/analyzers/SPEC.md.
+ +The code climate format doesn’t support suppressed violations. It also doesn’t report any errors. But it contains +the full rule details for each reported rule violation.
+ +Example:
+ +{"type":"issue","check_name":"GuardLogStatement","description":"Logger calls should be surrounded by log level guards.","content":{"body":"## GuardLogStatement\n\nSince: PMD 5.1.0\n\nPriority: Medium High\n\n[Categories](https://github.com/codeclimate/platform/blob/master/spec/analyzers/SPEC.md#categories): Style\n\n[Remediation Points](https://github.com/codeclimate/platform/blob/master/spec/analyzers/SPEC.md#remediation-points): 50000\n\nWhenever using a log level, one should check if the loglevel is actually enabled, or otherwise skip the associate String creation and manipulation.\n\n### Example:\n\n```java\n\n\n // Add this for performance\n if (log.isDebugEnabled() { ...\n log.debug('log something' + ' and ' + 'concat strings');\n\n \n``` \n\n### [PMD properties](https://pmd.github.io/pmd-6.22.0/pmd_userdocs_configuring_rules.html#rule-properties)\n\nName | Value | Description\n--- | --- | ---\nviolationSuppressRegex | | Suppress violations with messages matching a regular expression\nviolationSuppressXPath | | Suppress violations on nodes which match a given relative XPath expression.\nlogLevels | trace,debug,info,warn,error,log,finest,finer,fine,info,warning,severe | LogLevels to guard\nguardsMethods | isTraceEnabled,isDebugEnabled,isInfoEnabled,isWarnEnabled,isErrorEnabled,isLoggable | Method use to guard the log statement\n"},"categories":["Style"],"location":{"path":"/home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/RuleContext.java","lines":{"begin":124,"end":125}},"severity":"normal","remediation_points":50000}
+{"type":"issue","check_name":"ForLoopCanBeForeach","description":"This for loop can be replaced by a foreach loop","content":{"body":"## ForLoopCanBeForeach\n\nSince: PMD 6.0.0\n\nPriority: Medium\n\n[Categories](https://github.com/codeclimate/platform/blob/master/spec/analyzers/SPEC.md#categories): Style\n\n[Remediation Points](https://github.com/codeclimate/platform/blob/master/spec/analyzers/SPEC.md#remediation-points): 50000\n\nReports loops that can be safely replaced with the foreach syntax. The rule considers loops over lists, arrays and iterators. A loop is safe to replace if it only uses the index variable to access an element of the list or array, only has one update statement, and loops through *every* element of the list or array left to right.\n\n### Example:\n\n```java\n\n\npublic class MyClass {\n void loop(List<String> l) {\n for (int i = 0; i < l.size(); i++) { // pre Java 1.5\n System.out.println(l.get(i));\n }\n\n for (String s : l) { // post Java 1.5\n System.out.println(s);\n }\n }\n}\n\n \n``` \n\n### [PMD properties](https://pmd.github.io/pmd-6.22.0/pmd_userdocs_configuring_rules.html#rule-properties)\n\nName | Value | Description\n--- | --- | ---\nviolationSuppressRegex | | Suppress violations with messages matching a regular expression\nviolationSuppressXPath | | Suppress violations on nodes which match a given relative XPath expression.\n"},"categories":["Style"],"location":{"path":"/home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/benchmark/Benchmarker.java","lines":{"begin":58,"end":62}},"severity":"normal","remediation_points":50000}
+
Comma-separated values tabular format.
+ +This format only renders rule violations. Suppressed violations or errors are ignored.
+ +Example:
+ +"Problem","Package","File","Priority","Line","Description","Rule set","Rule"
+"1","net.sourceforge.pmd","/home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/RuleContext.java","2","124","Logger calls should be surrounded by log level guards.","Best Practices","GuardLogStatement"
+"1","net.sourceforge.pmd.benchmark","/home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/benchmark/Benchmarker.java","3","58","This for loop can be replaced by a foreach loop","Best Practices","ForLoopCanBeForeach"
+
This format can be configured to display only certain columns. In order to not show the problem counter and package
+columns, use these CLI parameters additionally: -property problem=false -property package=false
Properties:
+ +GNU Emacs integration.
+ +Example:
+ +/home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/RuleContext.java:124: Logger calls should be surrounded by log level guards.
+/home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/benchmark/Benchmarker.java:58: This for loop can be replaced by a foreach loop
+
HTML format.
+ +This renderer provides two properties to render a link to the source where the violations
+have been found. The following example has been created with -property linkPrefix=https://github.com/pmd/pmd/blob/master/ -property linePrefix=L -shortnames -d pmd
.
+If “linkPrefix” is not set, then “linePrefix” has no effect anyway: just the filename will
+be rendered, with no html link. Otherwise if “linePrefix” is not set, then the link will
+not contain a line number.
When using Maven JXR Plugin to generate a html view +of the project’s sources, then the property “htmlExtension” needs to be set to “true”. This will then replace the +normal source file extensions (e.g. “.java”) with “.html”, so that the generated html pages are referenced.
+ + + +Properties:
+ +IntelliJ IDEA integration.
+ +It has two ways of calling:
+ +run.sh pmd -d src/Foo.java -R rulesets/java/quickstart.xml -f ideaj -P fileName=src/Foo.java -P sourcePath=/home/pmd/src -P classAndMethodName=Foo
run.sh pmd -d src -R rulesets/java/quickstart.xml -f ideaj -P sourcePath=/home/pmd/src -P classAndMethodName=.method
Example:
+ +Logger calls should be surrounded by log level guards.
+ at Foo(:124)
+This for loop can be replaced by a foreach loop
+ at Foo(:58)
+
Properties:
+ +.method
when processing a directory.JSON format.
+ +This prints a single JSON object containing some header information, +and then the violations grouped by file. The root object fields are
+formatVersion
: an integer which will be incremented if we change the serialization formatpmdVersion
: the version of PMD that produced the reporttimestamp
: explicitfiles
: an array of objects (see the example)Summary HTML format.
+ +This is the html renderer but with an extra section, the summarizes the violations per rule.
+ + + +Properties:
+ +This is the default format.
+ +This format outputs one line per violation. At the end, processing errors, suppressed violations +and configuration errors are reported.
+ +Example:
+ +/home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/RuleContext.java:124: Logger calls should be surrounded by log level guards.
+/home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/benchmark/Benchmarker.java:58: This for loop can be replaced by a foreach loop
+/home/pmd/source/pmd-core/src/test/resources/net/sourceforge/pmd/cpd/files/file_with_ISO-8859-1_encoding.java - PMDException: Error while parsing /home/pmd/source/pmd-core/src/test/resources/net/sourceforge/pmd/cpd/files/file_with_ISO-8859-1_encoding.java
+CloseResource rule violation suppressed by Annotation in /home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java
+LoosePackageCoupling - No packages or classes specified
+
Text format, with color support (requires ANSI console support, e.g. xterm, rxvt, etc.).
+ +Example:
+ ++* file: ./pmd-core/src/main/java/net/sourceforge/pmd/RuleContext.java + src: RuleContext.java:124:125 + rule: GuardLogStatement + msg: Logger calls should be surrounded by log level guards. + code: LOG.warning("The method RuleContext::setSourceCodeFilename(String) has been deprecated and will be removed." + +* file: ./pmd-core/src/main/java/net/sourceforge/pmd/benchmark/Benchmarker.java + src: Benchmarker.java:58:62 + rule: ForLoopCanBeForeach + msg: This for loop can be replaced by a foreach loop + code: for (int i = 0; i < args.length; i++) { + + + +Summary: + +net.sourceforge.pmd.RuleContext : 1 +net.sourceforge.pmd.benchmark.Benchmarker : 1 +* file: ./pmd-core/src/test/resources/net/sourceforge/pmd/cpd/files/file_with_ISO-8859-1_encoding.java + err: PMDException: Error while parsing /home/pmd/source/pmd-core/src/test/resources/net/sourceforge/pmd/cpd/files/file_with_ISO-8859-1_encoding.java +net.sourceforge.pmd.PMDException: Error while parsing /home/pmd/source/pmd-core/src/test/resources/net/sourceforge/pmd/cpd/files/file_with_ISO-8859-1_encoding.java + at net.sourceforge.pmd.SourceCodeProcessor.processSourceCodeWithoutCache(SourceCodeProcessor.java:110) + at net.sourceforge.pmd.SourceCodeProcessor.processSourceCode(SourceCodeProcessor.java:89) + at net.sourceforge.pmd.SourceCodeProcessor.processSourceCode(SourceCodeProcessor.java:51) + at net.sourceforge.pmd.processor.PmdRunnable.call(PmdRunnable.java:78) + at net.sourceforge.pmd.processor.PmdRunnable.call(PmdRunnable.java:24) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) + at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630) + at java.base/java.lang.Thread.run(Thread.java:832) +Caused by: net.sourceforge.pmd.lang.java.ast.ParseException: Encountered " "-" "- "" at line 6, column 30. +Was expecting one of: + "extends" ... + "implements" ... + "{" ... + "<" ... + + at net.sourceforge.pmd.lang.java.ast.JavaParser.generateParseException(JavaParser.java:12713) + at net.sourceforge.pmd.lang.java.ast.JavaParser.jj_consume_token(JavaParser.java:12597) + at net.sourceforge.pmd.lang.java.ast.JavaParser.ClassOrInterfaceBody(JavaParser.java:1554) + at net.sourceforge.pmd.lang.java.ast.JavaParser.ClassOrInterfaceDeclaration(JavaParser.java:732) + at net.sourceforge.pmd.lang.java.ast.JavaParser.TypeDeclaration(JavaParser.java:639) + at net.sourceforge.pmd.lang.java.ast.JavaParser.CompilationUnit(JavaParser.java:373) + at net.sourceforge.pmd.lang.java.AbstractJavaParser.parse(AbstractJavaParser.java:62) + at net.sourceforge.pmd.SourceCodeProcessor.parse(SourceCodeProcessor.java:121) + at net.sourceforge.pmd.SourceCodeProcessor.processSource(SourceCodeProcessor.java:185) + at net.sourceforge.pmd.SourceCodeProcessor.processSourceCodeWithoutCache(SourceCodeProcessor.java:107) + ... 10 more + + +* rule: LoosePackageCoupling + err: No packages or classes specified + +* errors: 2 +* warnings: 2 ++ +
Properties:
+ +false
or 0
. Default: yes.TextPad integration.
+ +Example:
+ +/home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/RuleContext.java(124, GuardLogStatement): Logger calls should be surrounded by log level guards.
+/home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/benchmark/Benchmarker.java(58, ForLoopCanBeForeach): This for loop can be replaced by a foreach loop
+
Vladimir Bossicard HTML format.
+ +XML format.
+ +This format is a XML document, that can be validated by a XSD schema. The schema is report_2_0_0.xsd.
+ +Example:
+ +<?xml version="1.0" encoding="UTF-8"?>
+<pmd xmlns="http://pmd.sourceforge.net/report/2.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://pmd.sourceforge.net/report/2.0.0 https://pmd.sourceforge.io/report_2_0_0.xsd"
+ version="6.22.0" timestamp="2020-04-11T19:17:03.207">
+<file name="/home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/RuleContext.java">
+<violation beginline="124" endline="125" begincolumn="9" endcolumn="111" rule="GuardLogStatement" ruleset="Best Practices" package="net.sourceforge.pmd" class="RuleContext" method="setSourceCodeFilename" externalInfoUrl="https://pmd.github.io/pmd-6.22.0/pmd_rules_java_bestpractices.html#guardlogstatement" priority="2">
+Logger calls should be surrounded by log level guards.
+</violation>
+</file>
+<file name="/home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/benchmark/Benchmarker.java">
+<violation beginline="58" endline="62" begincolumn="9" endcolumn="9" rule="ForLoopCanBeForeach" ruleset="Best Practices" package="net.sourceforge.pmd.benchmark" class="Benchmarker" method="findBooleanSwitch" externalInfoUrl="https://pmd.github.io/pmd-6.22.0/pmd_rules_java_bestpractices.html#forloopcanbeforeach" priority="3">
+This for loop can be replaced by a foreach loop
+</violation>
+</file>
+<error filename="/home/pmd/source/pmd-core/src/test/resources/net/sourceforge/pmd/cpd/files/file_with_ISO-8859-1_encoding.java" msg="PMDException: Error while parsing /home/pmd/source/pmd-core/src/test/resources/net/sourceforge/pmd/cpd/files/file_with_ISO-8859-1_encoding.java">
+<![CDATA[net.sourceforge.pmd.PMDException: Error while parsing /home/pmd/source/pmd-core/src/test/resources/net/sourceforge/pmd/cpd/files/file_with_ISO-8859-1_encoding.java
+ at net.sourceforge.pmd.SourceCodeProcessor.processSourceCodeWithoutCache(SourceCodeProcessor.java:110)
+ at net.sourceforge.pmd.SourceCodeProcessor.processSourceCode(SourceCodeProcessor.java:89)
+ at net.sourceforge.pmd.SourceCodeProcessor.processSourceCode(SourceCodeProcessor.java:51)
+ at net.sourceforge.pmd.processor.PmdRunnable.call(PmdRunnable.java:78)
+ at net.sourceforge.pmd.processor.PmdRunnable.call(PmdRunnable.java:24)
+ at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
+ at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
+ at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
+ at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
+ at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
+ at java.base/java.lang.Thread.run(Thread.java:832)
+Caused by: net.sourceforge.pmd.lang.java.ast.ParseException: Encountered " "-" "- "" at line 6, column 30.
+Was expecting one of:
+ "extends" ...
+ "implements" ...
+ "{" ...
+ "<" ...
+
+ at net.sourceforge.pmd.lang.java.ast.JavaParser.generateParseException(JavaParser.java:12713)
+ at net.sourceforge.pmd.lang.java.ast.JavaParser.jj_consume_token(JavaParser.java:12597)
+ at net.sourceforge.pmd.lang.java.ast.JavaParser.ClassOrInterfaceBody(JavaParser.java:1554)
+ at net.sourceforge.pmd.lang.java.ast.JavaParser.ClassOrInterfaceDeclaration(JavaParser.java:732)
+ at net.sourceforge.pmd.lang.java.ast.JavaParser.TypeDeclaration(JavaParser.java:639)
+ at net.sourceforge.pmd.lang.java.ast.JavaParser.CompilationUnit(JavaParser.java:373)
+ at net.sourceforge.pmd.lang.java.AbstractJavaParser.parse(AbstractJavaParser.java:62)
+ at net.sourceforge.pmd.SourceCodeProcessor.parse(SourceCodeProcessor.java:121)
+ at net.sourceforge.pmd.SourceCodeProcessor.processSource(SourceCodeProcessor.java:185)
+ at net.sourceforge.pmd.SourceCodeProcessor.processSourceCodeWithoutCache(SourceCodeProcessor.java:107)
+ ... 10 more
+]]>
+</error>
+<suppressedviolation filename="/home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java" suppressiontype="annotation" msg="Ensure that resources like this OutputStreamWriter object are closed after use" usermsg=""/>
+<configerror rule="LoosePackageCoupling" msg="No packages or classes specified"/>
+</pmd>
+
Properties:
+ +XML with a XSL transformation applied.
+ +PMD provides one built-in stylesheet, that is used by default, if no other +stylesheet with the property “xsltFilename” is specified. It is called pmd-nicerhtml.xsl and can be used for customization.
+ +Example with pmd-nicerhtml.xsl
+ +Properties:
+ +Yet Another HTML format.
+ +This renderer creates an html file per analyzed source file, hence you need to specify a output directory. +The output directory must exist. If not specified, the html files are created in the current directory.
+ + + +Properties:
+ +PMD provides several methods by which Rule violations can be suppressed. +Follow these steps to help you determine which expression method works best +for you:
+ +Is the thing you need to suppress universally appealing to other +users of PMD, or is it a false positive? Can you modify the Rule to +support this specific suppression via a configuration property, or to +fix the false positive? If you can do this, then please do so, and +submit a patch back to the PMD project. Since PMD is built by users +for users, your help would be greatly appreciated by everyone. If you +cannot…
+Can you use Annotations or the NOPMD marker to work around your +particular issue on a case by case basis? If not…
+Can a regular expression matching the violation message work +around your particular issue? If not…
+Can a XPath query on the violation node work around your particular +issue? If not…
+Your last and final option is to see the first point about +changing the Rule, but you do not need to submit a patch back to the +PMD project.
+If you need to modify the Rule, see How to write a rule. +Otherwise, the other suppression methods are explained in the following sections.
+ +When using Java 1.5 or later, you can use annotations to suppress PMD warnings, like this:
+ +// This will suppress all the PMD warnings in this class
+@SuppressWarnings("PMD")
+public class Bar {
+ void bar() {
+ int foo;
+ }
+}
+
When using Apex make sure to use single quotes instead of double quotes
+ +// This will suppress all the PMD warnings in this class
+@SuppressWarnings('PMD')
+
Or you can suppress one rule with an annotation like this:
+ +// This will suppress UnusedLocalVariable warnings in this class
+@SuppressWarnings("PMD.UnusedLocalVariable")
+public class Bar {
+ void bar() {
+ int foo;
+ }
+}
+
Multiple rules can be suppressed by providing multiple values, ie:
+ +@SuppressWarnings({"PMD.UnusedLocalVariable", "PMD.UnusedPrivateMethod"})
+
For Apex, the syntax for this is slightly different:
+ +@SuppressWarnings('PMD.UnusedLocalVariable, PMD.UnusedPrivateMethod')
+
PMD Java also obeys the JDK annotation @SuppressWarnings(“unused”), which will apply to all rules in the unused ruleset.
+ +// This will suppress UnusedLocalVariable and UnusedPrivateMethod warnings in this class
+@SuppressWarnings("unused")
+public class Bar {
+ void bar() {
+ int foo;
+ }
+ private void foobar(){}
+}
+
Alternatively, you can tell PMD to ignore a specific line by using the “NOPMD” marker in a comment, like this:
+ +public class Bar {
+ // 'bar' is accessed by a native method, so we want to suppress warnings for it
+ private int bar; //NOPMD
+}
+
You can use whatever text string you want to suppress warnings, by using the -suppressmarker
CLI option.
+For example, here’s how to use TURN_OFF_WARNINGS
as the suppressor:
$ cat Foo.java
+public class Foo {
+ void bar() {
+ int x = 2; // TURN_OFF_WARNINGS
+ }
+}
+
+$ ./run.sh pmd -d Foo.java -f text -R java-unusedcode -suppressmarker TURN_OFF_WARNINGS
+No problems found!
+UnusedLocalVariable rule violation suppressed by //NOPMD in /home/tom/pmd/pmd/bin/Foo.java
+
Note that PMD expects the //NOPMD marker to be on the same line as the violation. So, for
+example, if you want to suppress an “empty if
statement” warning, you’ll need to place it on
+the line containing the if
keyword, e.g.:
$ cat ~/tmp/Foo.java
+public class Foo {
+ void bar() {
+ int x = 42;
+ if (x > 5) { // NOPMD
+ }
+ }
+}
+$ java net.sourceforge.pmd.PMD -d ~/tmp/Foo.java -f text -R java-basic
+No problems found!
+
A message placed after the NOPMD marker will get placed in the report, e.g.:
+ +public class Foo {
+ void bar() {
+ try {
+ bar();
+ } catch (FileNotFoundException e) {} // NOPMD - this surely will never happen
+ }
+}
+
If a particular rule consistently reports a warning in a particular context, you can fall +back to disabling the rule for all these contexts using one of two rule properties +that are defined on every rule. Depending on what you’re after, you can suppress +violations for specific messages using regular expressions, or specific nodes +using an XPath expression.
+ +violationSuppressRegex
This property defines a regular expression to match against the +message of the violation. If the regular expression matches, +then the violation will be suppressed.
+ +For example, to suppress reporting specifically named parameters which +are unused:
+ +<rule ref="rulesets/java/unusedcode.xml/UnusedFormalParameter">
+ <properties>
+ <property name="violationSuppressRegex" value=".*'mySpecialParameterName'.*"/>
+ </properties>
+</rule>
+
Note for message based suppression to work, you must know how to write +a regular expression that matches the message of violations you wish to +suppress. Regular expressions are explained in the JavaDoc for standard +Java class java.util.regex.Pattern.
+ +This technique of course relies on how the rule’s message is implemented. +Some rules always report the same message, in which case this property is +of no use.
+ +violationSuppressXPath
This property defines an XPath query to be executed using the +violation node as the context node. If the XPath query matches anything, +then the violation will be suppressed. Note that the query shouldn’t be finding +the violation nodes to suppress, but rather, finding a non-empty sequence of nodes +when evaluated with the violation node as a context node.
+ +The XPath version used by those queries is XPath 1.0, so it doesn’t support various XPath 2.0 +features. This will be updated with PMD 7.0.0.
+ +For example, to suppress reporting specifically “String” parameters which are unused:
+ +<rule ref="rulesets/java/unusedcode.xml/UnusedFormalParameter">
+ <properties>
+ <property name="violationSuppressXPath" value=".[typeIs('java.lang.String')]"/>
+ </properties>
+</rule>
+
Note the use of .
to refer to the context node. Using //
at the start of the
+expression should be avoided, as it would test all nodes in the file, and suppress
+more violations than expected.
Another example, to suppress violations occurring in classes whose name contains Bean
:
<property name="violationSuppressXPath" value="./ancestor::ClassOrInterfaceDeclaration[contains(@Image, 'Bean')]"/>
+
You can also use regex for string comparison. The next example suppresses violations in classes ending with Bean
:
<property name="violationSuppressXPath" value="./ancestor::ClassOrInterfaceDeclaration[matches(@Image, '^.*Bean$')]"/>
+
Note here the usage of the ./ancestor::
axis instead of //
. The latter would match
+any ClassOrInterfaceDeclaration in the file, while the former matches only class
+declaration nodes that enclose the violation node, which is usually what you’d want.
Note for XPath based suppression to work, you must know how to write +an XPath query that matches the AST structure of the nodes of the +violations you wish to suppress. XPath queries are explained in +XPath Rule tutorial.
+ + + + + + +Codacy automates code reviews and monitors code quality on every commit and pull request. +It gives visibility into the technical debt and it can track code style and security issues, code coverage, code duplication, cyclomatic complexity and enforce best practices. +Codacy is static analysis without the hassle.
+ +With Codacy you have PMDJava analysis out-of-the-box, and it is free for open source projects.
+ +IDE | +Homepage | +Source Code | +Maintainers | +
---|---|---|---|
BlueJ | ++ | pmd-bluej | +Tom Copeland | +
CodeGuide | ++ | N/A | +Austin Moore | +
Eclipse | ++ | github: pmd/pmd-eclipse | +Philippe Herlin | +
qa-Eclipse | ++ | qa-Eclipse | +Christian Wulf | +
eclipse-pmd | +http://acanda.github.io/eclipse-pmd/ | +github: acanda/eclipse-pmd | +Philip Graf | +
Emacs | ++ | github: pmd/pmd-emacs | +Nascif Abousalh Neto | +
Gel | ++ | github: pmd/pmd-misc/pmd-gel | +Andrei Lumianski | +
Gradle | +Gradle: The PMD Plugin | +github: gradle/gradle | +Gradle.org | +
IntelliJ IDEA | ++ | github: amitdev/PMD-Intellij | +Amit Dev | +
IntelliJ IDEA - QAPlug | +http://qaplug.com/ | +N/A | +Jakub Sławiński | +
JBuilder | ++ | github: pmd/pmd-misc/pmd-jbuilder | +Tom Copeland | +
JCreator | ++ | N/A | +Brant Gurganus | +
JDeveloper | ++ | github: pmd/pmd-jdeveloper | +Torsten Kleiber | +
JEdit | +jEdit - PMD Plugin | +sourceforge: jedit/PMDPlugin | +Jiger Patel, Dale Anson | +
NetBeans | +SQE | +github: sqe-team/sqe | +N/A | +
TextPad | ++ | N/A | +Jeff Epstein | +
WebLogic Workshop 8.1.x | ++ | N/A | +Kevin Conaway | +
A general note - most plugins include the PMD jar files, which has the rulesets +inside it. So even though the rulesets parameter that some plugins +use (i.e., “rulesets/java/unusedcode.xml”) looks like a filesystem reference, it’s really +being used by a getResourceAsStream() call to load it out of the PMD jar files.
+ +BlueJ is a teaching IDE. To install the PMD extension for BlueJ, download
+the PMDExtension jar file
+and place it in your bluej/lib/extensions/
directory.
To install the PMD plugin for Eclipse:
+ +Alternatively, you can download the latest zip file and follow the above procedures +except for using “New local site” and browsing to the downloaded zip file.
+ +To configure PMD, select “Windows”->”Preferences”, then select PMD.
+ +To run PMD, right-click on a project node and select “PMD”->”Check code with PMD”.
+ +To run the duplicate code detector, right-click on a project node and +select “PMD”->”Find suspect cut and paste”. The report will be placed in a “reports” directory +in a file called “cpd-report.txt”.
+ +To find additional help for other features, please read included help by selecting +Help->Help Contents and browse the “How to…” section in the “PMD Plugin Documentation” book.
+ +After installing an update, if you get an Exception such as +“java.lang.RuntimeException: Couldn’t find that class xxxxx”, +try deleting the ruleset.xml file in the .metadata/plugins/net.sourceforge.pmd.eclipse directory in your workspace.
+ +To get Eclipse to not flag the @SuppressWarnings(“PMD”) annotation, look +under the menu headings Java -> Compiler -> Errors/Warnings -> Annotations -> Unhandled Warning Token.
+ +Integration with GNU Emacs is performed through an ELisp package, pmd.el. +It supports two commands, “pmd-current-buffer” and “pmd-current-dir”. +The output is captured in a compilation buffer which allows the user to “jump” +directly to the source code position associated with the PMD warnings.
+ +Here’s how to set up the Gel plugin:
+ +That’s pretty much it. Now you can open a Java project and click on Plugins->PMD and +a configuration panel will pop up. You can pick which ruleset you want to run and +you can also pick whether you want to run PMD on the current file or on every +source file in your project.
+ +You can use an integrated plugin or just use it as an IDEA “External Tool”.
+ +Amit Dev wrote an integrated plugin for IDEA; you can download that +from the IntelliJ plugins site.
+ +Here’s how to set it up as an “External Tool”:
+ +c:\pmd\bin\pmd.bat
-d "$FilePath$" -f ideaj -R rulesets/java/quickstart.xml -P sourcePath="$Sourcepath$" -P classAndMethodName=$FileClass$.method -P fileName=$FileName$
That’s pretty much it. Now you can right click on a source directory and select PMD, +it’ll run recursively on the source files, and the results should +be displayed in a window and hyperlinked into the correct file and line of code. I usually +right-click on the message window title bar and unselect “autohide” so the window doesn’t go +away every time I fix something in the code window.
+ +QAPlug is an Intellij IDEA plugin to manage code quality. It integrates no less than Checkstyle, FindBugs, and PMD.
+ +The plugin is available at http://www.qaplug.com/.
+ +Also available at the JetBrains site, QAPlug-PMD +and QAPlug.
+ +To enable this OpenTool in JBuilder:
+ +jbuilder/lib/ext/
directoryWhat you can do:
+ +When running PMD, the results will be displayed in the MessageView under a tab called PMD Results. If you click on a +violation message within this view, you will be taken to the line in the source code where the violation was detected.
+ +Things still to do:
+ +To run PMD on a project, just pick pmd from the Tools menu.
+ +To install the PMD plugin for JDeveloper:
+ +To run the PMD plugin for JDeveloper:
+ +The way I use the JEdit plugin is:
+ +Note that you can select individual rules by going to Utilities->Global Options->Plugin Options->PMD. +Also, you can change the plugin to prompt you for a directory to check by going to that same menu and +selecting the “Ask for Directory” checkbox.
+ +The SQE project includes PMD integration for NetBeans.
+ +Assumptions
+ +D:\java\jdk\_142\
. This means that D:\java\jdk\_142\bin\java.exe
exists.D:\java\pmd-bin-\
.
+This means that D:\java\pmd-bin-\lib\pmd-.jar
(among other jar files
+in the same directory) exist.To integrate into TextPad
+ +D:\java\jdk_142\bin\java.exe
and click the Open button. In the center pane of the Preferences dialog,
+an item “Java” has now been added, and is currently selected.+
’ directly to its left.-classpath D:\java\pmd-bin-\lib\pmd-.jar;D:\java\pmd-bin-\lib\asm-3.2.jar;D:\java\pmd-bin-\lib\jaxen-1.1.1.jar net.sourceforge.pmd.PMD -d <i><b>$FileDir</b></i> -f net.sourceforge.pmd.renderers.TextPadRenderer -R E:\directory\my_pmd_ruleset.xml -debug
$FileDir
Checked
Checked
^\([^(]+\)(\([0-9]+\),
1
2
$FileDir
’ with ‘$File
’,
+in the Parameters textbox.E:\directory\my_pmd_ruleset.xml
’
+with the ruleset of your choice. For example, basic
.Ctrl+Page Up
Ctrl+Page Down
To run PMD against a single Java file
+ +Ctrl+Page Down
. This opens an empty, read-only text document (titled “Command Results”).
+When PMD completes its analysis, this document will be populated with a listing of violated rules
+(or “Command completed successfully” indicating no violations).To run PMD against a directory of Java files
+ +Ctrl+Page Up
. This opens an empty, read-only text document (titled “Command Results”).
+When PMD completes its analysis, this document will be populated with a listing of violated rules
+(or “Command completed successfully” indicating no violations).Because directory analysis may take a while, you may choose to cancel this operation. Do so by closing +the (blank Command Results) document, and then confirming that, “yes, I do really want to exit the tool”.
+ +Please see the WebLogic Workshop plugin project home page for more information.
+ + + + + + +Runs a set of static code analysis rules on some source code files and generates a list of problems found.
+ +Before you can use the pmd
task in your ant build.xml
file, you need to install PMD and its libraries into
+ant’s classpath, as described in Optional Tasks.
First you need to download PMD’s binary distribution zip file.
+Then you can either copy all “*.jar” files from PMD’s lib folder into one of ANT’s library folders
+(ANT_HOME/lib
, ${user.home}/.ant/lib
) or using the -lib
command line parameter.
However, the preferred way is to define a <classpath>
for pmd itself and use this classpath when
+adding the PMD Task. Assuming, you have extracted the PMD zip file to /home/joe/pmd-bin-6.30.0-SNAPSHOT
,
+then you can make use of the PMD Task like this:
<taskdef name="pmd" classname="net.sourceforge.pmd.ant.PMDTask">
+ <classpath>
+ <fileset dir="/home/joe/pmd-bin-6.30.0-SNAPSHOT/lib">
+ <include name="*.jar"/>
+ </fileset>
+ </classpath>
+</taskdef>
+
Alternatively, a path can be defined and used via classpathref
:
<path id="pmd.classpath">
+ <fileset dir="/home/joe/pmd-bin-6.30.0-SNAPSHOT/lib">
+ <include name="*.jar"/>
+ </fileset>
+</path>
+<taskdef name="pmd" classname="net.sourceforge.pmd.ant.PMDTask" classpathref="pmd.classpath" />
+
The examples below won’t repeat this taskdef element, as this is always required.
+ +Attribute | +Description | +Required | +
---|---|---|
rulesetfiles | ++ A comma delimited list of ruleset files ('rulesets/java/quickstart.xml,config/my-ruleset.xml'). + If you write your own ruleset files, you can put them on the classpath and plug them in here. + | +Yes, unless the ruleset nested element is used | +
failonerror | +Whether or not to fail the build if any errors occur while processing the files | +No | +
failOnRuleViolation | +Whether or not to fail the build if PMD finds any problems | +No | +
minimumPriority | +The rule priority threshold; rules with lower priority than they will not be used | +No | +
shortFilenames | +Places truncated filenames in the report. This can reduce your report file size by 15%-20%. | +No | +
failuresPropertyName | +A property name to plug the number of rule violations into when the task finishes | +No | +
encoding | +The character set encoding (e.g. UTF-8) to use when reading the source code files | +No | +
suppressMarker | +The series of characters to use to tell PMD to skip lines - the default is NOPMD. | +No | +
maxRuleViolations | ++ Whether or not to fail the build if PMD finds more than the value of this attribute. + Note that setting this attribute does not require to set the failOnRuleViolation to true. + | +No | +
cacheLocation | ++ The location of the analysis cache file to be used. + Setting this property enables Incremental Analysis, which can greatly improve analysis time without loosing analysis quality. + Its use is strongly recommended. + | +No | +
noCache | ++ Setting this property to true disables Incremental Analysis, even if cacheLocation is provided. + You can use this to explicitly turn off suggestions to use incremental analysis, or for testing purposes. + | +No | +
formatter
nested element - specifies the format of and the files to which the report is written. You can
+configure multiple formatters.
Name | Values |
---|---|
type | +xml,ideaj,textcolor,text,textpad,emacs,csv,html,xslt,yahtml,summaryhtml,vbhtml,codeclimate | +
showSuppressed | +Whether to show suppressed warnings; "false" is the default. | +
toFile | +A filename to which to write the report | +
toConsole | +Whether to output the report to the console; "false" is the default. | +
+ The
|
+
classpath
nested element - useful for specifying custom rules. More details on the classpath
+element are in the Ant documentation for path-like structures and there’s
+an example below.
auxclasspath
nested element - extra classpath used for type resolution. Some rules make use of type resolution
+in order to avoid false positives. The auxclasspath
is configured also with path-like structures. It should contain the compiled classes of the project that is being analyzed and all the compile time
+dependencies.
sourceLanguage
nested element - specify which language (Java, Ecmascript, XML,…)
+and the associated version (1.5, 1.6,…). This element is optional. The language is determined by file extension
+automatically and the latest language version is used.
ruleset
nested element - another way to specify rulesets. You can specify multiple elements. Here’s an example:
<target name="pmd">
+ <taskdef name="pmd" classname="net.sourceforge.pmd.ant.PMDTask"/>
+ <pmd shortFilenames="true">
+ <ruleset>rulesets/java/quickstart.xml</ruleset>
+ <ruleset>config/my-ruleset.xml</ruleset>
+ <fileset dir="/usr/local/j2sdk1.4.1_01/src/">
+ <include name="java/lang/*.java"/>
+ </fileset>
+ </pmd>
+</target>
+
fileset
nested element - specify the actual java source files, that PMD should analyze. You can use multiple
+fileset elements. See FileSet for the syntax and usage.
PMD selects the language automatically using the file extension. If multiple versions of a language are +supported, PMD uses the latest version as default. This is currently the case for Java only, which has +support for multiple versions.
+ +If a languages supports multiple versions, you can select a specific version here, so that e.g. rules, that only apply
+to specific versions, are not executed. E.g. the rule UseTryWithResources
only makes
+sense with Java 1.7 and later. If your project uses Java 1.5, then you should configure the sourceLanguage
+accordingly and this rule won’t be executed.
The specific version of a language to be used is selected via the sourceLanguage
+nested element. Possible values are:
<sourceLanguage name="apex" version="48"/>
+<sourceLanguage name="ecmascript" version="3"/>
+<sourceLanguage name="java" version="1.3"/>
+<sourceLanguage name="java" version="1.4"/>
+<sourceLanguage name="java" version="1.5"/>
+<sourceLanguage name="java" version="5"/> <!-- alias for 1.5 -->
+<sourceLanguage name="java" version="1.6"/>
+<sourceLanguage name="java" version="6"/> <!-- alias for 1.6 -->
+<sourceLanguage name="java" version="1.7"/>
+<sourceLanguage name="java" version="7"/> <!-- alias for 1.7 -->
+<sourceLanguage name="java" version="1.8"/>
+<sourceLanguage name="java" version="8"/> <!-- alias for 1.8 -->
+<sourceLanguage name="java" version="9"/>
+<sourceLanguage name="java" version="1.9"/> <!-- alias for 9 -->
+<sourceLanguage name="java" version="10"/>
+<sourceLanguage name="java" version="1.10"/> <!-- alias for 10 -->
+<sourceLanguage name="java" version="11"/>
+<sourceLanguage name="java" version="12"/>
+<sourceLanguage name="java" version="13"/>
+<sourceLanguage name="java" version="13-preview"/>
+<sourceLanguage name="java" version="14"/> <!-- this is the default -->
+<sourceLanguage name="java" version="14-preview"/>
+<sourceLanguage name="jsp" version=""/>
+<sourceLanguage name="modelica" version=""/>
+<sourceLanguage name="pom" version=""/>
+<sourceLanguage name="plsql" version=""/>
+<sourceLanguage name="scala" version="2.10"/>
+<sourceLanguage name="scala" version="2.11"/>
+<sourceLanguage name="scala" version="2.12"/>
+<sourceLanguage name="scala" version="2.13"/> <!-- this is the default -->
+<sourceLanguage name="vf" version=""/>
+<sourceLanguage name="vm" version=""/>
+<sourceLanguage name="wsdl" version=""/>
+<sourceLanguage name="xml" version=""/>
+<sourceLanguage name="xsl" version=""/>
+
Several folks (most recently, Wouter Zelle) have written XSLT scripts +which you can use to transform the XML report into nifty HTML. To do this, +make sure you use the XML formatter in the PMD task invocation, i.e.:
+ +<formatter type="xml" toFile="${tempbuild}/report_pmd.xml">
+ <param name="encoding" value="UTF-8" /> <!-- enforce UTF-8 encoding for the XML -->
+</formatter>
+
Then, after the end of the PMD task, do this:
+ +<xslt in="${tempbuild}/report_pmd.xml" style="${pmdConfig}/wz-pmd-report.xslt" out="${pmdOutput}/report_pmd.html" />
+
Running one ruleset to produce a HTML report (and printing the report to the console as well) using a file cache
+ +<target name="pmd">
+ <pmd rulesetfiles="rulesets/java/quickstart.xml" cacheLocation="build/pmd/pmd.cache">
+ <formatter type="html" toFile="pmd_report.html" toConsole="true"/>
+ <fileset dir="C:\j2sdk1.4.1_01\src\java\lang\">
+ <include name="**/*.java"/>
+ </fileset>
+ </pmd>
+</target>
+
Running multiple rulesets to produce an XML report with the same analysis cache
+ +<target name="pmd">
+ <pmd rulesetfiles="rulesets/java/quickstart.xml,config/my-ruleset.xml" cacheLocation="build/pmd/pmd.cache">
+ <formatter type="xml" toFile="c:\pmd_report.xml"/>
+ <fileset dir="C:\j2sdk1.4.1_01\src\java\lang\">
+ <include name="**/*.java"/>
+ </fileset>
+ </pmd>
+</target>
+
Using a custom renderer. For this to work, you need to add you custom renderer to the classpath of PMD. This +need to be configured when defining the task:
+ +<path id="pmd.classpath">
+ <fileset dir="/home/joe/pmd-bin-6.30.0-SNAPSHOT/lib">
+ <include name="*.jar"/>
+ </fileset>
+ <!-- the custom renderer is expected to be in /home/joe/pmd-addons/com/company/MyRenderer.class -->
+ <pathelement location="/home/joe/pmd-addons" />
+</path>
+<taskdef name="pmd" classname="net.sourceforge.pmd.ant.PMDTask" classpathref="pmd.classpath" />
+
+<target name="pmd">
+ <pmd rulesetfiles="rulesets/java/quickstart.xml">
+ <formatter type="com.mycompany.MyRenderer" toFile="foo.html"/>
+ <fileset dir="/path/to/java/src">
+ <include name="**/*.java"/>
+ </fileset>
+ </pmd>
+</target>
+
Full build file example using the correct auxclasspath configuration. +Your project needs to be compiled first which happens in the target “compile”:
+ +<project name="MyProject" default="pmd" basedir=".">
+ <property name="src" location="src"/>
+ <property name="build" location="build"/>
+ <path id="project.dependencies">
+ <pathelement location="lib/third-party.jar"/>
+ <pathelement location="lib/xyz.jar"/>
+ </path>
+ <path id="pmd.classpath">
+ <fileset dir="/home/joe/pmd-bin-6.30.0-SNAPSHOT/lib">
+ <include name="*.jar"/>
+ </fileset>
+ </path>
+ <taskdef name="pmd" classname="net.sourceforge.pmd.ant.PMDTask" classpathref="pmd.classpath" />
+
+ <target name="init">
+ <mkdir dir="${build}"/>
+ </target>
+
+ <target name="compile" depends="init">
+ <javac srcdir="${src}" destdir="${build}" classpathref="project.dependencies"
+ source="1.8" target="1.8" />
+ </target>
+
+ <target name="pmd" depends="compile">
+ <pmd cacheLocation="${build}/pmd.cache">
+ <auxclasspath>
+ <pathelement location="${build}"/>
+ <path refid="project.dependencies"/>
+ </auxclasspath>
+ <ruleset>rulesets/java/quickstart.xml</ruleset>
+ <formatter type="html" toFile="${build}/pmd_report.html"/>
+ <sourceLanguage name="java" version="1.8"/>
+ <fileset dir="${src}">
+ <include name="**/*.java"/>
+ </fileset>
+ </pmd>
+ </target>
+
+ <target name="clean">
+ <delete dir="${build}"/>
+ </target>
+</project>
+
You can run pmd then with ant pmd
.
[tom@hal bin]$ ant -v pmd
+Apache Ant version 1.6.2 compiled on July 16 2004
+Buildfile: build.xml
+Detected Java version: 1.4 in: /usr/local/j2sdk1.4.2_03/jre
+Detected OS: Linux
+parsing buildfile build.xml with URI = file:/home/tom/data/pmd/pmd/bin/build.xml
+Project base dir set to: /home/tom/data/pmd/pmd
+Build sequence for target `pmd' is [pmd]
+Complete build sequence is [pmd, copy, cppjavacc, cpd, delete,
+ compile, clean, jar, dist, cpdjnlp, jjtree, javadoc, test, tomserver]
+
+pmd:
+ [pmd] Using the normal ClassLoader
+ [pmd] Using these rulesets: rulesets/java/quickstart.xml
+ [pmd] Using rule AvoidMessageDigestField
+ [pmd] Using rule AvoidStringBufferField
+ [pmd] Using rule AvoidUsingHardCodedIP
+ [pmd] Using rule CheckResultSet
+ [pmd] Using rule ConstantsInInterface
+ ...
+ [pmd] Processing file /usr/local/java/src/java/lang/ref/Finalizer.java
+ [pmd] Processing file /usr/local/java/src/java/lang/ref/FinalReference.java
+ [pmd] Processing file /usr/local/java/src/java/lang/ref/PhantomReference.java
+ [pmd] Processing file /usr/local/java/src/java/lang/ref/Reference.java
+ [pmd] Processing file /usr/local/java/src/java/lang/ref/ReferenceQueue.java
+ [pmd] Processing file /usr/local/java/src/java/lang/ref/SoftReference.java
+ [pmd] Processing file /usr/local/java/src/java/lang/ref/WeakReference.java
+ [pmd] 0 problems found
+
+BUILD SUCCESSFUL
+Total time: 2 seconds
+[tom@hal bin]$
+
An HTML report with the “linkPrefix” and “linePrefix” properties:
+ +<target name="pmd">
+ <taskdef name="pmd" classname="net.sourceforge.pmd.ant.PMDTask"/>
+ <pmd rulesetfiles="rulesets/java/quickstart.xml" shortFilenames="true">
+ <formatter type="html" toFile="pmd_report.html">
+ <param name="linkPrefix" value="https://maven.apache.org/plugins/maven-pmd-plugin/xref/"/>
+ <param name="linePrefix" value="L"/>
+ </formatter>
+ <fileset dir="/usr/local/j2sdk1.4.1_01/src/">
+ <include name="java/lang/*.java"/>
+ </fileset>
+ </pmd>
+</target>
+
Memory usage has been reduced significantly starting with the PMD 4.0 release. +When testing all Java rules on the jdk 1.6 source code (about 7000 classes), +the allocated heap space does not go over 60M.
+ +However, on very large projects, the Ant task may still fail with a OutOfMemoryError. +To prevent this from happening, increase the maximum memory usable by ant using the ANT_OPTS variable +(adjust the size according to your available memory):
+ +On Windows:
+ +set ANT_OPTS=-Xmx1024m -Xms512m
+
On Linux
+ +export ANT_OPTS="-Xmx1024m -Xms512m"
+
PMD can be integrate through some of the Continuous Integration tools that exist now. +Here is a list of known (to us) plugin to do so.
+ +Hafner Ullrich has developed a PMD plugin for Hudson. +Please check the plugin homepage for more info.
+ +Continuum does not have a plugin for PMD per see, but can failed the build according to the +result of the PMD maven plugin.
+ + + + + + + + +The Gradle Build Tool provides a PMD Plugin +that can be added to your build configuration. Technically it is based on the Ant Task.
+ +In your build.gradle
add the following:
plugins {
+ id 'pmd'
+}
+
Configuration of a custom ruleset looks like this:
+ +pmd {
+ ruleSetFiles = files("custom-pmd-ruleset.xml")
+ ruleSets = []
+}
+
Note: The ruleSets
array is explicitly set to empty to avoid using the default configuration.
If you want to fail the build for pmd violations, you need to set ignoreFailures
:
pmd {
+ ignoreFailures = false
+}
+
More configuration options are documented on PMD Extension.
+ +If you want to use a newer PMD version than the default one provided with gradle, you can do so
+with the property toolVersion
:
pmd {
+ toolVersion = "6.21.0"
+}
+
Source code for Gradles PMD Plugin is available here:
+ +The easiest way to run PMD is to just use a build plugin in your favorite build tool +like Apache Ant, Apache Maven or +Gradle.
+ +There are also many integrations for IDEs available, see Tools.
+ +If you have your own build tool or want to integrate PMD in a different way, you can call PMD programmatically, +as described here.
+ +You’ll need to add the dependency to the language, you want to analyze. For Java, it will be
+net.sourceforge.pmd:pmd-java
. If you use Maven, you can add a new (compile time) dependency like this:
<dependency>
+ <groupId>net.sourceforge.pmd</groupId>
+ <artifactId>pmd-java</artifactId>
+ <version>${pmdVersion}</version>
+</dependency>
+
Note: You’ll need to select a specific version. This is done in the example via the property pmdVersion
.
This will transitively pull in the artifact pmd-core
which contains the API.
The easiest way is to call PMD with the same interface as from command line. The main class is
+net.sourceforge.pmd.PMD
:
import net.sourceforge.pmd.PMD;
+
+public class Example {
+ public static void main(String[] args) {
+ String[] pmdArgs = {
+ "-d", "/home/workspace/src/main/java/code",
+ "-R", "rulesets/java/quickstart.xml",
+ "-f", "xml",
+ "-r", "/home/workspace/pmd-report.xml"
+ };
+ PMD.main(pmdArgs);
+ }
+}
+
It uses the same options as described in PMD CLI reference.
+ +This is very similar:
+ +import net.sourceforge.pmd.PMD;
+import net.sourceforge.pmd.PMDConfiguration;
+
+public class PmdExample {
+
+ public static void main(String[] args) {
+ PMDConfiguration configuration = new PMDConfiguration();
+ configuration.setInputPaths("/home/workspace/src/main/java/code");
+ configuration.setRuleSets("rulesets/java/quickstart.xml");
+ configuration.setReportFormat("xml");
+ configuration.setReportFile("/home/workspace/pmd-report.xml");
+
+ PMD.doPMD(configuration);
+ }
+}
+
This gives you more control over which files are processed, but is also more complicated. +You can also provide your own listeners and renderers.
+ +First we create a PMDConfiguration
. This is currently the only way to specify a ruleset:
PMDConfiguration configuration = new PMDConfiguration();
+configuration.setMinimumPriority(RulePriority.MEDIUM);
+configuration.setRuleSets("rulesets/java/quickstart.xml");
+
In order to support type resolution, PMD needs to have access to the compiled classes and dependencies
+as well. This is called “auxclasspath” and is also configured here.
+Note: you can specify multiple class paths separated by :
on Unix-systems or ;
under Windows.
configuration.prependClasspath("/home/workspace/target/classes:/home/.m2/repository/my/dependency.jar");
+
Then we need a ruleset factory. This is created using the configuration, taking the minimum priority into +account:
+ +RuleSetFactory ruleSetFactory = RulesetsFactoryUtils.createFactory(configuration);
+
PMD operates on a list of DataSource
. You can assemble a own list of FileDataSource
, e.g.
List<DataSource> files = Arrays.asList(new FileDataSource(new File("/path/to/src/MyClass.java")));
+
For reporting, you can use a built-in renderer, e.g. XMLRenderer
. Note, that you must manually initialize
+the renderer by setting a suitable Writer
and calling start()
. After the PMD run, you need to call
+end()
and flush()
. Then your writer should have received all output.
StringWriter rendererOutput = new StringWriter();
+Renderer xmlRenderer = new XMLRenderer("UTF-8");
+xmlRenderer.setWriter(rendererOutput);
+xmlRenderer.start();
+
Create a RuleContext
. This is the context instance, that is available then in the rule implementations.
+Note: when running in multi-threaded mode (which is the default), the rule context instance is cloned for
+each thread.
RuleContext ctx = new RuleContext();
+
Optionally register a report listener. This allows you to react immediately on found violations. You could also
+use such a listener to implement your own renderer. The listener must implement the interface
+ThreadSafeReportListener
and can be registered via ctx.getReport().addListener(...)
.
ctx.getReport().addListener(new ThreadSafeReportListener() {
+ public void ruleViolationAdded(RuleViolation ruleViolation) {
+ }
+ public void metricAdded(Metric metric) {
+ }
+
Now, all the preparations are done, and PMD can be executed. This is done by calling
+PMD.processFiles(...)
. This method call takes the configuration, the ruleset factory, the files
+to process, the rule context and the list of renderers. Provide an empty list, if you don’t want to use
+any renderer. Note: The auxclasspath needs to be closed explicitly. Otherwise the class or jar files may
+remain open and file resources are leaked.
try {
+ PMD.processFiles(configuration, ruleSetFactory, files, ctx,
+ Collections.singletonList(renderer));
+} finally {
+ ClassLoader auxiliaryClassLoader = configuration.getClassLoader();
+ if (auxiliaryClassLoader instanceof ClasspathClassLoader) {
+ ((ClasspathClassLoader) auxiliaryClassLoader).close();
+ }
+}
+
After the call, you need to finish the renderer via end()
and flush()
.
+Then you can check the rendered output.
renderer.end();
+renderer.flush();
+System.out.println("Rendered Report:");
+System.out.println(rendererOutput.toString());
+
Here is a complete example:
+ +import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.nio.file.FileSystems;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.PathMatcher;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import net.sourceforge.pmd.PMD;
+import net.sourceforge.pmd.PMDConfiguration;
+import net.sourceforge.pmd.RuleContext;
+import net.sourceforge.pmd.RulePriority;
+import net.sourceforge.pmd.RuleSetFactory;
+import net.sourceforge.pmd.RuleViolation;
+import net.sourceforge.pmd.RulesetsFactoryUtils;
+import net.sourceforge.pmd.ThreadSafeReportListener;
+import net.sourceforge.pmd.renderers.Renderer;
+import net.sourceforge.pmd.renderers.XMLRenderer;
+import net.sourceforge.pmd.stat.Metric;
+import net.sourceforge.pmd.util.ClasspathClassLoader;
+import net.sourceforge.pmd.util.datasource.DataSource;
+import net.sourceforge.pmd.util.datasource.FileDataSource;
+
+public class PmdExample2 {
+
+ public static void main(String[] args) throws IOException {
+ PMDConfiguration configuration = new PMDConfiguration();
+ configuration.setMinimumPriority(RulePriority.MEDIUM);
+ configuration.setRuleSets("rulesets/java/quickstart.xml");
+ configuration.prependClasspath("/home/workspace/target/classes");
+ RuleSetFactory ruleSetFactory = RulesetsFactoryUtils.createFactory(configuration);
+
+ List<DataSource> files = determineFiles("/home/workspace/src/main/java/code");
+
+ Writer rendererOutput = new StringWriter();
+ Renderer renderer = createRenderer(rendererOutput);
+ renderer.start();
+
+ RuleContext ctx = new RuleContext();
+
+ ctx.getReport().addListener(createReportListener()); // alternative way to collect violations
+
+ try {
+ PMD.processFiles(configuration, ruleSetFactory, files, ctx,
+ Collections.singletonList(renderer));
+ } finally {
+ ClassLoader auxiliaryClassLoader = configuration.getClassLoader();
+ if (auxiliaryClassLoader instanceof ClasspathClassLoader) {
+ ((ClasspathClassLoader) auxiliaryClassLoader).close();
+ }
+ }
+
+ renderer.end();
+ renderer.flush();
+ System.out.println("Rendered Report:");
+ System.out.println(rendererOutput.toString());
+ }
+
+ private static ThreadSafeReportListener createReportListener() {
+ return new ThreadSafeReportListener() {
+ @Override
+ public void ruleViolationAdded(RuleViolation ruleViolation) {
+ System.out.printf("%-20s:%d %s%n", ruleViolation.getFilename(),
+ ruleViolation.getBeginLine(), ruleViolation.getDescription());
+ }
+
+ @Override
+ public void metricAdded(Metric metric) {
+ // ignored
+ }
+ };
+ }
+
+ private static Renderer createRenderer(Writer writer) {
+ XMLRenderer xml = new XMLRenderer("UTF-8");
+ xml.setWriter(writer);
+ return xml;
+ }
+
+ private static List<DataSource> determineFiles(String basePath) throws IOException {
+ Path dirPath = FileSystems.getDefault().getPath(basePath);
+ PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:*.java");
+
+ List<DataSource> files = new ArrayList<>();
+
+ Files.walkFileTree(dirPath, new SimpleFileVisitor<Path>() {
+ @Override
+ public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) throws IOException {
+ if (matcher.matches(path.getFileName())) {
+ System.out.printf("Using %s%n", path);
+ files.add(new FileDataSource(path.toFile()));
+ } else {
+ System.out.printf("Ignoring %s%n", path);
+ }
+ return super.visitFile(path, attrs);
+ }
+ });
+ System.out.printf("Analyzing %d files in %s%n", files.size(), basePath);
+ return files;
+ }
+}
+
When adding the maven-pmd-plugin to your pom.xml, you need to select a version. To figure out the +latest available version, have a look at the official maven-pmd-plugin documentation.
+ +As of March 2020, the current plugin version is 3.13.0.
+ +The version of the plugin should be specified in <build><pluginManagement/></build>
and if using the project
+report additionally in <reporting><plugins/></reporting>
elements. Here’s an example for the pluginManagement
+section:
<build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-pmd-plugin</artifactId>
+ <version>3.13.0</version>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+
When defining the version in the pluginManagment section, then it doesn’t need to be specified in the normal plugins +section. However, it should additionally be specified in the reporting section.
+ +More information, see Guide to Configuring Plugin-ins.
+ +To include the PMD report in the project reports section add the following lines under +the reports element in your pom.xml:
+ +<project>
+ ...
+ <reporting>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-pmd-plugin</artifactId>
+ <version>3.13.0</version>
+ </plugin>
+ </plugins>
+ </reporting>
+ ...
+</project>
+
This will add an entry to the ‘project reports’ section with the PMD report when you build the maven site.
+ +To run PMD on a Maven project without adding it as a report, simply run
+ +mvn pmd:pmd
+
The PMD plugin writes the report in XML which will then be formatted into more readable HTML.
+ +You can also run PMD automatically when building your project. You even let the build fail, if
+PMD finds some violations. Therefore the check
goal is used:
<project>
+ ...
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-pmd-plugin</artifactId>
+ <version>3.13.0</version> <!-- or use version from pluginManagement -->
+ <configuration>
+ <!-- failOnViolation is actually true by default, but can be disabled -->
+ <failOnViolation>true</failOnViolation>
+ <!-- printFailingErrors is pretty useful -->
+ <printFailingErrors>true</printFailingErrors>
+ </configuration>
+ <executions>
+ <execution>
+ <goals>
+ <goal>check</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ ...
+</project>
+
This will run PMD automatically during the verify
phase of the build. You can additionally run CPD, if
+you add cpd-check
as a goal.
To specify a ruleset, simply edit the previous configuration:
+ + <reporting>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-pmd-plugin</artifactId>
+ <version>3.13.0</version>
+ <configuration>
+ <rulesets>
+ <ruleset>/rulesets/java/quickstart.xml</ruleset>
+ <ruleset>d:\rulesets\my-ruleset.xml</ruleset>
+ <ruleset>http://localhost/design.xml</ruleset>
+ </rulesets>
+ </configuration>
+ </plugin>
+ </plugins>
+ </reporting>
+
The value of the ‘ruleset’ element can either be a relative address, an absolute address or even an url.
+ +A clean strategy for customizing which rules to use for a project is to write a ruleset file. +In this file you can define which rules to use, add custom rules, and +customizing which rules to include/exclude from official rulesets. More information on +writing a ruleset can be found here. +Note that if you include other rulesets in your own rulesets, you have to be sure that the plugin +will be able to resolve those other ruleset references.
+ +When using the Maven PMD plugin 3.8 or later along with PMD 5.6.0 or later, you can enable incremental analysis to +speed up PMD’s execution while retaining the quality of the analysis. You can additionally customize where the cache is stored::
+ + <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-pmd-plugin</artifactId>
+ <version>3.13.0</version> <!-- or use version from pluginManagement -->
+ <configuration>
+ <!-- enable incremental analysis -->
+ <analysisCache>true</analysisCache>
+ <!-- analysisCacheLocation: optional - points to the following location by default -->
+ <analysisCacheLocation>${project.build.directory}/pmd/pmd.cache</analysisCacheLocation>
+ </configuration>
+ </plugin>
+
The Maven PMD plugin allows you to configure CPD, targetJDK, and the use of XRef to link +the report to html source files, and the file encoding:
+ + <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-pmd-plugin</artifactId>
+ <version>3.13.0</version> <!-- or use version from pluginManagement -->
+ <configuration>
+ <linkXRef>true</linkXRef>
+ <sourceEncoding>ISO-8859-1</sourceEncoding>
+ <minimumTokens>30</minimumTokens>
+ <targetJdk>1.4</targetJdk>
+ </configuration>
+ </plugin>
+
The Maven PMD plugin comes with a specific PMD version, which is documented on the +plugin project page.
+ +Given that the newer PMD version is compatible, you can override the PMD version, that the +Maven plugin will use and benefit from the latest bugfixes and enhancements:
+ +<project>
+ <properties>
+ <pmdVersion>...choose your version...</pmdVersion>
+ </properties>
+...
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-pmd-plugin</artifactId>
+ <version>3.13.0</version>
+ <dependencies>
+ <dependency>
+ <groupId>net.sourceforge.pmd</groupId>
+ <artifactId>pmd-core</artifactId>
+ <version>${pmdVersion}</version>
+ </dependency>
+ <dependency>
+ <groupId>net.sourceforge.pmd</groupId>
+ <artifactId>pmd-java</artifactId>
+ <version>${pmdVersion}</version>
+ </dependency>
+ <dependency>
+ <groupId>net.sourceforge.pmd</groupId>
+ <artifactId>pmd-javascript</artifactId>
+ <version>${pmdVersion}</version>
+ </dependency>
+ <dependency>
+ <groupId>net.sourceforge.pmd</groupId>
+ <artifactId>pmd-jsp</artifactId>
+ <version>${pmdVersion}</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+...
+</project>
+
For more information, please see the well documented PMD plugin project page here: +http://maven.apache.org/plugins/maven-pmd-plugin/index.html. +Also, the bug tracker for this plugin is here.
+ +This section is about the maven 1 PMD plugin.
+ +To include the PMD report in the project reports section add the following line under +the reports element in your project.xml:
+ +<report>maven-pmd-plugin</report>
+
This will add an entry to the ‘project reports’ section with the PMD report.
+ +To run PMD on a Maven project without adding it as a report, simply run
+ +maven pmd xdoc
+
The PMD plugin writes the report in XML which will then be formatted into more readable HTML.
+ +To specify a set of official, built-in rulesets to be used set them in the property +maven.pmd.rulesets. You can include this setting in your project.properties file.
+ +A clean strategy for customizing which rules to use for a project is to write a ruleset file. +In this file you can define which rules to use, add custom rules, and +customizing which rules to include/exclude from official rulesets. More information on +writing a ruleset can be found here.
+ +Add to the root of your Maven project a pmd.xml file which contains the ruleset mentioned in +the previous paragraph. Add the following property to your project now:
+ +maven.pmd.rulesetfiles = ${basedir}/pmd.xml
+
See the PMD plugin project page here: +http://maven.apache.org/maven-1.x/plugins/pmd/
+ + + + + + +File | Problem |
---|---|
pmd-core/src/test/resources/net/sourceforge/pmd/cpd/files/file_with_ISO-8859-1_encoding.java | +net.sourceforge.pmd.PMDException: Error while parsing pmd-core/src/test/resources/net/sourceforge/pmd/cpd/files/file_with_ISO-8859-1_encoding.java + at net.sourceforge.pmd.SourceCodeProcessor.processSourceCodeWithoutCache(SourceCodeProcessor.java:110) + at net.sourceforge.pmd.SourceCodeProcessor.processSourceCode(SourceCodeProcessor.java:89) + at net.sourceforge.pmd.SourceCodeProcessor.processSourceCode(SourceCodeProcessor.java:51) + at net.sourceforge.pmd.processor.PmdRunnable.call(PmdRunnable.java:78) + at net.sourceforge.pmd.processor.PmdRunnable.call(PmdRunnable.java:24) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) + at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630) + at java.base/java.lang.Thread.run(Thread.java:832) +Caused by: net.sourceforge.pmd.lang.java.ast.ParseException: Encountered " "-" "- "" at line 6, column 30. +Was expecting one of: + "extends" ... + "implements" ... + "{" ... + "<" ... + + at net.sourceforge.pmd.lang.java.ast.JavaParser.generateParseException(JavaParser.java:12713) + at net.sourceforge.pmd.lang.java.ast.JavaParser.jj_consume_token(JavaParser.java:12597) + at net.sourceforge.pmd.lang.java.ast.JavaParser.ClassOrInterfaceBody(JavaParser.java:1554) + at net.sourceforge.pmd.lang.java.ast.JavaParser.ClassOrInterfaceDeclaration(JavaParser.java:732) + at net.sourceforge.pmd.lang.java.ast.JavaParser.TypeDeclaration(JavaParser.java:639) + at net.sourceforge.pmd.lang.java.ast.JavaParser.CompilationUnit(JavaParser.java:373) + at net.sourceforge.pmd.lang.java.AbstractJavaParser.parse(AbstractJavaParser.java:62) + at net.sourceforge.pmd.SourceCodeProcessor.parse(SourceCodeProcessor.java:121) + at net.sourceforge.pmd.SourceCodeProcessor.processSource(SourceCodeProcessor.java:185) + at net.sourceforge.pmd.SourceCodeProcessor.processSourceCodeWithoutCache(SourceCodeProcessor.java:107) + ... 10 more + |
+
File | Line | Rule | NOPMD or Annotation | Reason |
---|---|---|---|---|
pmd-core/src/main/java/net/sourceforge/pmd/PMD.java | +505 | +CloseResource | +Annotation | ++ |
Rule | Problem |
---|---|
LoosePackageCoupling | +No packages or classes specified | +
+ |
+ PMD 6.22.0 Report. Generated on 2020-04-11 - 19:23:45+ |
+
Files | +Total | +
+ Priority 1
+ |
+
+ Priority 2
+ |
+
+ Priority 3
+ |
+
+ Priority 4
+ |
+
+ Priority 5
+ |
+
---|---|---|---|---|---|---|
2 | +2 | +0 | +1 | +1 | +0 | +0 | +
Rule | +Violations | +Severity | +
---|---|---|
+ [Best Practices] GuardLogStatement | +1 | +
+ 2
+ |
+
+ [Best Practices] ForLoopCanBeForeach | +1 | +
+ 3
+ |
+
File | +
+ 5
+ |
+
+ 4
+ |
+
+ 3
+ |
+
+ 2
+ |
+
+ 1
+ |
+
---|---|---|---|---|---|
+ /home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/RuleContext.java + | +0 | +0 | +0 | +1 | +0 | +
+ /home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/benchmark/Benchmarker.java + | +0 | +0 | +1 | +0 | +0 | +
Violation | +Error Description | +Line | +
---|---|---|
+ 2
+ |
+ + [Best Practices.GuardLogStatement] + - + +Logger calls should be surrounded by log level guards. + + | +124 - 125 | +
Violation | +Error Description | +Line | +
---|---|---|
+ 3
+ |
+ + [Best Practices.ForLoopCanBeForeach] + - + +This for loop can be replaced by a foreach loop + + | +58 - 62 | +
Rule name | Number of violations |
---|---|
GuardLogStatement | 1 |
ForLoopCanBeForeach | 1 |
File | Problem |
---|---|
pmd-core/src/test/resources/net/sourceforge/pmd/cpd/files/file_with_ISO-8859-1_encoding.java | +net.sourceforge.pmd.PMDException: Error while parsing pmd-core/src/test/resources/net/sourceforge/pmd/cpd/files/file_with_ISO-8859-1_encoding.java + at net.sourceforge.pmd.SourceCodeProcessor.processSourceCodeWithoutCache(SourceCodeProcessor.java:110) + at net.sourceforge.pmd.SourceCodeProcessor.processSourceCode(SourceCodeProcessor.java:89) + at net.sourceforge.pmd.SourceCodeProcessor.processSourceCode(SourceCodeProcessor.java:51) + at net.sourceforge.pmd.processor.PmdRunnable.call(PmdRunnable.java:78) + at net.sourceforge.pmd.processor.PmdRunnable.call(PmdRunnable.java:1) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) + at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) + at java.base/java.lang.Thread.run(Thread.java:834) +Caused by: net.sourceforge.pmd.lang.java.ast.ParseException: Encountered " "-" "- "" at line 6, column 30. +Was expecting one of: + "extends" ... + "implements" ... + "{" ... + "<" ... + + at net.sourceforge.pmd.lang.java.ast.JavaParser.generateParseException(JavaParser.java:12731) + at net.sourceforge.pmd.lang.java.ast.JavaParser.jj_consume_token(JavaParser.java:12615) + at net.sourceforge.pmd.lang.java.ast.JavaParser.ClassOrInterfaceBody(JavaParser.java:1574) + at net.sourceforge.pmd.lang.java.ast.JavaParser.ClassOrInterfaceDeclaration(JavaParser.java:779) + at net.sourceforge.pmd.lang.java.ast.JavaParser.TypeDeclaration(JavaParser.java:686) + at net.sourceforge.pmd.lang.java.ast.JavaParser.CompilationUnit(JavaParser.java:420) + at net.sourceforge.pmd.lang.java.AbstractJavaParser.parse(AbstractJavaParser.java:62) + at net.sourceforge.pmd.SourceCodeProcessor.parse(SourceCodeProcessor.java:121) + at net.sourceforge.pmd.SourceCodeProcessor.processSource(SourceCodeProcessor.java:185) + at net.sourceforge.pmd.SourceCodeProcessor.processSourceCodeWithoutCache(SourceCodeProcessor.java:107) + ... 10 more + |
+
File | Line | Rule | NOPMD or Annotation | Reason |
---|---|---|---|---|
pmd-core/src/main/java/net/sourceforge/pmd/PMD.java | +505 | +CloseResource | +Annotation | ++ |
Rule | Problem |
---|---|
LoosePackageCoupling | +No packages or classes specified | +
/home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/RuleContext.java | |
124 | Logger calls should be surrounded by log level guards. |
/home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/benchmark/Benchmarker.java | |
58 | This for loop can be replaced by a foreach loop |
Problems found | |
/home/pmd/source/pmd-core/src/test/resources/net/sourceforge/pmd/cpd/files/file_with_ISO-8859-1_encoding.java | net.sourceforge.pmd.PMDException: Error while parsing /home/pmd/source/pmd-core/src/test/resources/net/sourceforge/pmd/cpd/files/file_with_ISO-8859-1_encoding.java + at net.sourceforge.pmd.SourceCodeProcessor.processSourceCodeWithoutCache(SourceCodeProcessor.java:110) + at net.sourceforge.pmd.SourceCodeProcessor.processSourceCode(SourceCodeProcessor.java:89) + at net.sourceforge.pmd.SourceCodeProcessor.processSourceCode(SourceCodeProcessor.java:51) + at net.sourceforge.pmd.processor.PmdRunnable.call(PmdRunnable.java:78) + at net.sourceforge.pmd.processor.PmdRunnable.call(PmdRunnable.java:24) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) + at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630) + at java.base/java.lang.Thread.run(Thread.java:832) +Caused by: net.sourceforge.pmd.lang.java.ast.ParseException: Encountered " "-" "- "" at line 6, column 30. +Was expecting one of: + "extends" ... + "implements" ... + "{" ... + "<" ... + + at net.sourceforge.pmd.lang.java.ast.JavaParser.generateParseException(JavaParser.java:12713) + at net.sourceforge.pmd.lang.java.ast.JavaParser.jj_consume_token(JavaParser.java:12597) + at net.sourceforge.pmd.lang.java.ast.JavaParser.ClassOrInterfaceBody(JavaParser.java:1554) + at net.sourceforge.pmd.lang.java.ast.JavaParser.ClassOrInterfaceDeclaration(JavaParser.java:732) + at net.sourceforge.pmd.lang.java.ast.JavaParser.TypeDeclaration(JavaParser.java:639) + at net.sourceforge.pmd.lang.java.ast.JavaParser.CompilationUnit(JavaParser.java:373) + at net.sourceforge.pmd.lang.java.AbstractJavaParser.parse(AbstractJavaParser.java:62) + at net.sourceforge.pmd.SourceCodeProcessor.parse(SourceCodeProcessor.java:121) + at net.sourceforge.pmd.SourceCodeProcessor.processSource(SourceCodeProcessor.java:185) + at net.sourceforge.pmd.SourceCodeProcessor.processSourceCodeWithoutCache(SourceCodeProcessor.java:107) + ... 10 more + |
Configuration problems found | |
LoosePackageCoupling | No packages or classes specified |
Method | Violation | ||||||
---|---|---|---|---|---|---|---|
findBooleanSwitch |
|
Method | Violation | ||||||
---|---|---|---|---|---|---|---|
setSourceCodeFilename |
|
Package | Class | # |
---|---|---|
Aggregate | - | 2 |
net | - | 2 |
net.sourceforge | - | 2 |
net.sourceforge.pmd | - | 2 |
net.sourceforge.pmd | RuleContext | 1 |
net.sourceforge.pmd.benchmark | - | 1 |
net.sourceforge.pmd.benchmark | Benchmarker | 1 |
The following pages and posts are tagged with
+Title | Type | Excerpt |
---|---|---|
How to add a new CPD language | +Page | +How to add a new CPD language | +
Adding PMD support for a new language | +Page | +How to add a new language to PMD. | +
Adding support for metrics to a language | +Page | +PMD's Java module has an extensive framework for the calculation of metrics, which allows rule developers to implement and use new code metrics very simply. ... | +
Creating XML dump of the AST | +Page | +Creating a XML representation of the AST allows to analyze the AST with other tools. | +
Building PMD from source | +Page | +Note: TODO add IDE specific indications Compiling PMD JDK 11 or higher Note: While Java 11 is required for building, running PMD only requires Java 7 (or Java 8 for Apex... | +
Developer Resources | +Page | +The next version of PMD will be developed in parallel with this release. We will release additional bugfix versions as needed. Source Code The complete source code can be found on github: github.com/pmd/pmd - main PMD repository. Includes all the code to support all languages, including this... | +
How PMD Works | +Page | +Processing overview of the different steps taken by PMD. | +
Pmdtester | +Page | +Introduction Pmdtester is a regression testing tool that ensures no new problems and unexpected behaviors will be introduced to PMD after fixing an issue. It can also be used to verify, that new rules work as expected. It has been integrated into travis CI and is actually used automatically... | +
Roadmap | +Page | +TODO: Update Future direction projects, plans Google Summer of Code Future directions Want to know what’s coming? Or, better, wanna contribute ? Here is the page listing what are our plans - when we have ones, for the future of PMD. It also give you hints at... | +
Rule deprecation policy | +Page | +Describes when and how rules are deprecated | +
Writing documentation | +Page | +PMD's documentation uses [Jekyll](https://jekyllrb.com/) with the [I'd rather be writing Jekyll Theme](http://idratherbewriting.com/documentation-theme-jekyll/index.html). Here are some quick tips. ## Format The pages are in general in [Github Flavored Markdown](https://kramdown.gettalong.org/parser/gfm.html). ## Structure The documentation sources can be found in two places based on how they are generated: - the ones that are... | +
The following pages and posts are tagged with
+Title | Type | Excerpt |
---|---|---|
How to add a new CPD language | +Page | +How to add a new CPD language | +
Adding PMD support for a new language | +Page | +How to add a new language to PMD. | +
Adding support for metrics to a language | +Page | +PMD's Java module has an extensive framework for the calculation of metrics, which allows rule developers to implement and use new code metrics very simply. ... | +
Index of Apex code metrics | +Page | +Index of the code metrics available out of the box to Apex rule developers. | +
Defining rule properties | +Page | +Learn how to define your own properties both for Java and XPath rules. | +
The rule designer | +Page | +Learn about the usage and features of the rule designer. | +
Index of Java code metrics | +Page | +Index of the code metrics available out of the box to Java rule developers. | +
Using and defining code metrics for custom rules | +Page | +Since version 6.0.0, PMD is enhanced with the ability to compute code metrics on Java and Apex source (the so-called Metrics Framework). This framework provi... | +
Rule guidelines | +Page | +Rule Guidelines, or the last touches to a rule | +
Testing your rules | +Page | +Learn how to use PMD's simple test framework for unit testing rules. | +
Writing a custom rule | +Page | +Learn how to write a custom rule for PMD | +
Writing a custom rule | +Page | +The information on this page has been split into several separate pages. Please update your bookmarks: * [Introduction to writing rules](pmd_userdocs_extending_writing_rules_intro.html) * [Your First Rule](pmd_userdocs_extending_your_first_rule.html) introduces the basic development process of a rule with a running example * [Writing XPath Rules](pmd_userdocs_extending_writing_xpath_rules.html) explains a bit more about XPath rules and our... | +
Introduction to writing PMD rules | +Page | +Writing your own PMD rules | +
Writing XPath rules | +Page | +This page describes XPath rule support in more details | +
Your first rule XPath | +Page | +Introduction to rule writing through an example. | +
The following pages and posts are tagged with
+Title | Type | Excerpt |
---|---|---|
Configuring rules | +Page | +Learn how to configure your rules directly from the ruleset XML. | +
Installation and basic CLI usage | +Page | +Sums up the first steps to set up a CLI installation and get started using PMD | +
Making rulesets | +Page | +A ruleset is an XML configuration file, which describes a collection of rules to be executed in a PMD run. PMD includes built-in rulesets to run quick analys... | +
Introduction to writing PMD rules | +Page | +Writing your own PMD rules | +
The following pages and posts are tagged with
+Title | Type | Excerpt |
---|
The following pages and posts are tagged with
+Title | Type | Excerpt |
---|---|---|
Adding support for metrics to a language | +Page | +PMD's Java module has an extensive framework for the calculation of metrics, which allows rule developers to implement and use new code metrics very simply. ... | +
Index of Apex code metrics | +Page | +Index of the code metrics available out of the box to Apex rule developers. | +
Index of Java code metrics | +Page | +Index of the code metrics available out of the box to Java rule developers. | +
Using and defining code metrics for custom rules | +Page | +Since version 6.0.0, PMD is enhanced with the ability to compute code metrics on Java and Apex source (the so-called Metrics Framework). This framework provi... | +
The following pages and posts are tagged with
+Title | Type | Excerpt |
---|
The following pages and posts are tagged with
+Title | Type | Excerpt |
---|---|---|
Apex Rules | +Page | +Index of all built-in rules available for Apex | +
Ecmascript Rules | +Page | +Index of all built-in rules available for Ecmascript | +
Java Rules | +Page | +Index of all built-in rules available for Java | +
Java Server Pages Rules | +Page | +Index of all built-in rules available for Java Server Pages | +
Modelica Rules | +Page | +Index of all built-in rules available for Modelica | +
PLSQL Rules | +Page | +Index of all built-in rules available for PLSQL | +
Maven POM Rules | +Page | +Index of all built-in rules available for Maven POM | +
Scala Rules | +Page | +Index of all built-in rules available for Scala | +
Salesforce VisualForce Rules | +Page | +Index of all built-in rules available for Salesforce VisualForce | +
VM Rules | +Page | +Index of all built-in rules available for VM | +
XML Rules | +Page | +Index of all built-in rules available for XML | +
XSL Rules | +Page | +Index of all built-in rules available for XSL | +
The following pages and posts are tagged with
+Title | Type | Excerpt |
---|---|---|
Ant Task Usage | +Page | +PMD Description Runs a set of static code analysis rules on some source code files and generates a list of problems found. Installation Before you can use the pmd task in your ant build.xml file, you need to install PMD and its libraries... | +
Continuous Integrations plugins | +Page | +Introduction PMD can be integrate through some of the Continuous Integration tools that exist now. Here is a list of known (to us) plugin to do so. Hudson Plugin Hafner Ullrich has developed a PMD plugin for Hudson. Please check the plugin homepage for more info. <h2... | +
Gradle | +Page | +The Gradle Build Tool provides a PMD Plugin that can be added to your build configuration. Technically it is based on the Ant Task. Example In your build.gradle add the following: plugins { id 'pmd' } Custom ruleset... | +
PMD Java API | +Page | +The easiest way to run PMD is to just use a build plugin in your favorite build tool like Apache Ant, Apache Maven or Gradle. There are also many integrations for IDEs available, see Tools. If you have your own build tool or want to integrate... | +
Maven PMD Plugin | +Page | +Maven 2 and 3 Running the pmd plugin Choosing the plugin version When adding the maven-pmd-plugin to your pom.xml, you need to select a version. To figure out the latest available version, have a look at the official maven-pmd-plugin documentation. As of March 2020, the current... | +
Tools / Integrations | +Page | +## Automated Code Review ### Codacy [Codacy](https://www.codacy.com/) automates code reviews and monitors code quality on every commit and pull request. It gives visibility into the technical debt and it can track code style and security issues, code coverage, code duplication, cyclomatic complexity and enforce best practices. Codacy is static analysis... | +
The following pages and posts are tagged with
+Title | Type | Excerpt |
---|
The following pages and posts are tagged with
+Title | Type | Excerpt |
---|---|---|
Ant Task Usage | +Page | +PMD Description Runs a set of static code analysis rules on some source code files and generates a list of problems found. Installation Before you can use the pmd task in your ant build.xml file, you need to install PMD and its libraries... | +
Best Practices | +Page | +Choose the rules that are right for you Running every existing rule will result in a huge number of rule violations, most of which will be unimportant. Having to sort through a thousand line report to find the few you’re really interested in takes all the fun out of... | +
Continuous Integrations plugins | +Page | +Introduction PMD can be integrate through some of the Continuous Integration tools that exist now. Here is a list of known (to us) plugin to do so. Hudson Plugin Hafner Ullrich has developed a PMD plugin for Hudson. Please check the plugin homepage for more info. <h2... | +
PMD CLI reference | +Page | +Full reference for PMD's command-line interface, including options, output formats and supported languages | +
Configuring rules | +Page | +Learn how to configure your rules directly from the ruleset XML. | +
Finding duplicated code with CPD | +Page | +Learn how to use CPD, the copy-paste detector shipped with PMD. | +
Report formats for CPD | +Page | +Overview of the built-in report formats for CPD | +
Defining rule properties | +Page | +Learn how to define your own properties both for Java and XPath rules. | +
The rule designer | +Page | +Learn about the usage and features of the rule designer. | +
Gradle | +Page | +The Gradle Build Tool provides a PMD Plugin that can be added to your build configuration. Technically it is based on the Ant Task. Example In your build.gradle add the following: plugins { id 'pmd' } Custom ruleset... | +
Incremental Analysis | +Page | +Explains how to use incremental analysis to speed up analysis | +
Installation and basic CLI usage | +Page | +Sums up the first steps to set up a CLI installation and get started using PMD | +
PMD Java API | +Page | +The easiest way to run PMD is to just use a build plugin in your favorite build tool like Apache Ant, Apache Maven or Gradle. There are also many integrations for IDEs available, see Tools. If you have your own build tool or want to integrate... | +
Making rulesets | +Page | +A ruleset is an XML configuration file, which describes a collection of rules to be executed in a PMD run. PMD includes built-in rulesets to run quick analys... | +
Maven PMD Plugin | +Page | +Maven 2 and 3 Running the pmd plugin Choosing the plugin version When adding the maven-pmd-plugin to your pom.xml, you need to select a version. To figure out the latest available version, have a look at the official maven-pmd-plugin documentation. As of March 2020, the current... | +
Using and defining code metrics for custom rules | +Page | +Since version 6.0.0, PMD is enhanced with the ability to compute code metrics on Java and Apex source (the so-called Metrics Framework). This framework provi... | +
Report formats for PMD | +Page | +Overview of the built-in report formats for PMD | +
Rule guidelines | +Page | +Rule Guidelines, or the last touches to a rule | +
Suppressing warnings | +Page | +Learn how to suppress some rule violations, from the source code using annotations or comments, or globally from the ruleset | +
Testing your rules | +Page | +Learn how to use PMD's simple test framework for unit testing rules. | +
Tools / Integrations | +Page | +## Automated Code Review ### Codacy [Codacy](https://www.codacy.com/) automates code reviews and monitors code quality on every commit and pull request. It gives visibility into the technical debt and it can track code style and security issues, code coverage, code duplication, cyclomatic complexity and enforce best practices. Codacy is static analysis... | +
Writing a custom rule | +Page | +Learn how to write a custom rule for PMD | +
Writing a custom rule | +Page | +The information on this page has been split into several separate pages. Please update your bookmarks: * [Introduction to writing rules](pmd_userdocs_extending_writing_rules_intro.html) * [Your First Rule](pmd_userdocs_extending_your_first_rule.html) introduces the basic development process of a rule with a running example * [Writing XPath Rules](pmd_userdocs_extending_writing_xpath_rules.html) explains a bit more about XPath rules and our... | +
Introduction to writing PMD rules | +Page | +Writing your own PMD rules | +
Writing XPath rules | +Page | +This page describes XPath rule support in more details | +
Your first rule XPath | +Page | +Introduction to rule writing through an example. | +
This page is purposely separated out from the rest of theme so you can see the bare minimum code to add to a page, without all the other theme's code getting in the way.
+ +Content in the tooltips (actually "popovers" according to Bootstrap lingo) can be pulled in dynamically by placing the JSON file on a remote host.
+ +Basketball
+ +Baseball
+ +Football
+ +Soccer
+ diff --git a/tooltips.json b/tooltips.json new file mode 100644 index 0000000000..73773c9ef3 --- /dev/null +++ b/tooltips.json @@ -0,0 +1,29 @@ +{ +"entries": +[ + +{ +"doc_id": "baseball", +"body": "Baseball is considered America's pasttime sport, though that may be more of a historical term than a current one. There's a lot more excitement about football than baseball. A baseball game is somewhat of a snooze to watch, for the most part." +} , + +{ +"doc_id": "basketball", +"body": "Basketball is a sport involving two teams of five players each competing to put a ball through a small circular rim 10 feet above the ground. Basketball requires players to be in top physical condition, since they spend most of the game running back and forth along a 94-foot-long floor." +} , + +{ +"doc_id": "football", +"body": "No doubt the most fun sport to watch, football also manages to accrue the most injuries with the players. From concussions to blown knees, football players have short sport lives." +} , + +{ +"doc_id": "soccer", +"body": "If there's one sport that dominates the world landscape, it's soccer. However, US soccer fans are few and far between. Apart from the popularity of soccer during the World Cup, most people don't even know the name of the professional soccer organization in their area." +} + +] +} + + +