﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-走自己的路-文章分类-Other Java and J2EE frameworks</title><link>http://www.blogjava.net/ldd600/category/30030.html</link><description>路漫漫其修远兮，吾将上下而求索</description><language>zh-cn</language><lastBuildDate>Thu, 29 May 2008 01:08:17 GMT</lastBuildDate><pubDate>Thu, 29 May 2008 01:08:17 GMT</pubDate><ttl>60</ttl><item><title>编写自定义的PMD规则</title><link>http://www.blogjava.net/ldd600/articles/198534.html</link><dc:creator>叱咤红人</dc:creator><author>叱咤红人</author><pubDate>Mon, 05 May 2008 10:46:00 GMT</pubDate><guid>http://www.blogjava.net/ldd600/articles/198534.html</guid><wfw:comment>http://www.blogjava.net/ldd600/comments/198534.html</wfw:comment><comments>http://www.blogjava.net/ldd600/articles/198534.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ldd600/comments/commentRss/198534.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ldd600/services/trackbacks/198534.html</trackback:ping><description><![CDATA[&nbsp;
<p><span style="font-family: 宋体">前提：</span></p>
<p style="margin-left: 21pt; text-indent: -21pt; tab-stops: list 21.0pt">1.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">了解</span>XPath<span style="font-family: 宋体">：</span>http://www.w3.org/TR/xpath</p>
<p style="margin-left: 21pt; text-indent: -21pt; tab-stops: list 21.0pt">2.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">对</span>PMD <span style="font-family: 宋体">的实现原理有一定的了解</span></p>
<p><span style="font-family: 宋体">简单介绍一下</span>pmd<span style="font-family: 宋体">的实现原理：</span></p>
<p style="margin-left: 21pt">Pmd<span style="font-family: 宋体">利用</span>javacc<span style="font-family: 宋体">和</span>EBNF<span style="font-family: 宋体">文法产生一个分析器，用来分析</span>java<span style="font-family: 宋体">源代码（文本）。又在</span><span style="font-size: 9pt; font-family: Verdana">JavaCC</span><span style="font-size: 9pt; font-family: 宋体">的基础上加入了语义的概念也就是</span><span style="font-size: 9pt; font-family: Verdana">JJTree</span><span style="font-size: 9pt; font-family: 宋体">，这样就把</span><span style="font-size: 9pt; font-family: Verdana">java source</span><span style="font-size: 9pt; font-family: 宋体">转换成了一个抽象语法树（</span><span style="font-size: 9pt; font-family: Verdana">AST</span><span style="font-size: 9pt; font-family: 宋体">），</span><span style="font-size: 9pt; font-family: Verdana">AST</span><span style="font-size: 9pt; font-family: 宋体">是一个结构化的对象层次结构。我们可以用访问者模式访问这个结构上的每个节点。从而找出哪个节点违反了哪些规则。</span></p>
<p><span style="font-family: 宋体">实现过程：</span></p>
<p style="margin-left: 63pt; text-indent: -21pt; tab-stops: list 63.0pt"><span style="font-size: 7.5pt; font-family: Wingdings">l<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 宋体">首先传一个文件名或者</span>Ruleset<span style="font-family: 宋体">给</span>pmd</p>
<p style="margin-left: 63pt; text-indent: -21pt; tab-stops: list 63.0pt"><span style="font-size: 7.5pt; font-family: Wingdings">l<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>Pmd<span style="font-family: 宋体">把该文件流传给自己生成的</span>javaCC<span style="font-family: 宋体">分析器</span></p>
<p style="margin-left: 63pt; text-indent: -21pt; tab-stops: list 63.0pt"><span style="font-size: 7.5pt; font-family: Wingdings">l<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 宋体">分析完毕后，</span>pmd<span style="font-family: 宋体">获得了分析生成的</span>AST<span style="font-family: 宋体">的一个引用</span></p>
<p style="margin-left: 63pt; text-indent: -21pt; tab-stops: list 63.0pt"><span style="font-size: 7.5pt; font-family: Wingdings">l<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>PMD<span style="font-family: 宋体">把</span>AST<span style="font-family: 宋体">处理成一个符号表，你可以在符号表里面查询一些有用的信息</span></p>
<p style="margin-left: 63pt; text-indent: -21pt; tab-stops: list 63.0pt"><span style="font-size: 7.5pt; font-family: Wingdings">l<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 宋体">每个</span>pmd<span style="font-family: 宋体">规则都会遍历整个</span>AST<span style="font-family: 宋体">并检验是否发生了错误</span></p>
<p style="margin-left: 63pt; text-indent: -21pt; tab-stops: list 63.0pt"><span style="font-size: 7.5pt; font-family: Wingdings">l<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 宋体">接着</span>pmd<span style="font-family: 宋体">产生一个报表，上面说明了有哪些地方违反了</span>pmd<span style="font-family: 宋体">规则</span></p>
<p><span style="font-family: 宋体">编写</span>pmd<span style="font-family: 宋体">规则有两种方法：</span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family: 宋体">用</span>java code<span style="font-family: 宋体">，需要了解</span>pmd<span style="font-family: 宋体">的</span>api<span style="font-family: 宋体">，需要进行深入研究，也常常用于一些比较复杂的</span>pmd<span style="font-family: 宋体">规则</span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family: 宋体">用</span>xpath<span style="font-family: 宋体">，对着产生的</span>AST<span style="font-family: 宋体">树，写就行了，上手比较快，写起来也比较简单</span></p>
<p><span style="font-family: 宋体">下面举一个用</span>XPath<span style="font-family: 宋体">实现的一个</span>PMD<span style="font-family: 宋体">规则：</span></p>
<p><span style="font-family: 宋体">在项目中，我们不希望</span>Application<span style="font-family: 宋体">的开发人员手动的调用</span>Toplink UnitOfWork<span style="font-family: 宋体">的</span>commit,</p>
<p>commitAndResume, commitAndResumeOnFailure'<span style="font-family: 宋体">方法，因为每次提交都会映像</span>performa<span style="font-family: 宋体">，我们的提交是放在自己编写的</span>framework<span style="font-family: 宋体">里面，在指定的位置提交。所以我们把规则的优先级设置为</span>3. <span style="font-family: 宋体">在</span>eclipse<span style="font-family: 宋体">的</span>pmd plugin<span style="font-family: 宋体">中，优先级为</span>3<span style="font-family: 宋体">会产生一个警告。</span></p>
<p>1<span style="font-family: 宋体">首先将</span>D:"local_lib"pmd-bin-4.2"bin <span style="font-family: 宋体">加到系统环境变量的</span>path<span style="font-family: 宋体">中</span></p>
<p>2<span style="font-family: 宋体">打开</span>cmd <span style="font-family: 宋体">运行</span> designer <span style="font-family: 宋体">分析器</span></p>
<p>3<span style="font-family: 宋体">左上角</span>source code<span style="font-family: 宋体">可以把你写好的</span>java source copy<span style="font-family: 宋体">过来主要就在这个</span>java source code<span style="font-family: 宋体">基础上不断修正你的</span>pmd<span style="font-family: 宋体">规则。</span></p>
<p>4xpath query<span style="font-family: 宋体">：用来编写自定义的</span>xpath expression<span style="font-family: 宋体">（先不忙写</span>xpath expression<span style="font-family: 宋体">）</span></p>
<p>5<span style="font-family: 宋体">点击</span>go<span style="font-family: 宋体">，就会在左下角的</span>Abstract syntax Tree<span style="font-family: 宋体">中产生</span>AST<span style="font-family: 宋体">，你可以选择</span>AST<span style="font-family: 宋体">上的某个节点，左下角的下面一个框中就会出现该节点的一些信息。是在符号表中查询得到的。</span></p>
<p>6<span style="font-family: 宋体">．</span>DFA<span style="font-family: 宋体">是</span>pmd4<span style="font-family: 宋体">的新功能，用于编写更复杂的</span>pmd<span style="font-family: 宋体">规则，不光是某个</span>source code<span style="font-family: 宋体">级别了，</span>pmd4<span style="font-family: 宋体">使用了</span>asm<span style="font-family: 宋体">读取字节码，并作分析，处理类文件之间的依赖性。在实际使用中，特别是在特定应用中，这个功能是相当有用的。还可以用来简化一些现有的规则。</span></p>
<p>7<span style="font-family: 宋体">根据生成的</span>AST<span style="font-family: 宋体">编写</span>xpath expression<span style="font-family: 宋体">。对于上文提到的</span>source<span style="font-family: 宋体">检查规则编写了一个</span>xpath</p>
<p>Expression<span style="font-family: 宋体">，在编写</span>xpath expression<span style="font-family: 宋体">的过程中需要反复的修改源代码并且反复的修改</span>xpath expression<span style="font-family: 宋体">这样才能满足所有的需要，反复的点击</span>go<span style="font-family: 宋体">。</span></p>
<p><span style="font-family: 宋体">最后写好的规则大致如下：</span></p>
<p>//PrimaryExpression[</p>
<p>&nbsp;&nbsp; (PrimaryPrefix/Name[ends-with(@Image, 'commit') or ends-with(@Image, 'commitAndResume') or ends-with(@Image, 'commitAndResumeOnFailure')] and substring-before(PrimaryPrefix/Name/@Image, '.') = //VariableDeclaratorId[../..//ClassOrInterfaceType[@Image = </p>
<p>'UnitOfWork']]/@Image) or (PrimarySuffix[ends-with(@Image, 'commit') or ends-with(@Image, 'commitAndResume') or ends-with(@Image, 'commitAndResumeOnFailure')] and (PrimarySuffix[ends-with(@Image, 'getActiveUnitOfWork')] or PrimarySuffix[ends-with(@Image, 'acquireUnitOfWork')]))&nbsp;&nbsp;&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; and&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //ImportDeclaration/Name[</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; contains(@Image,'oracle.toplink.sessions.UnitOfWork') or contains(@Image, 'oracle.toplink.sessions')]</p>
<p>]</p>
<p>8<span style="font-family: 宋体">．将写好的</span>xpath expression<span style="font-family: 宋体">转换成</span>pmd rule<span style="font-family: 宋体">。</span>Designer<span style="font-family: 宋体">可以自动生成点击菜单</span>actions<span style="font-family: 宋体">下面的</span>create rule xml<span style="font-family: 宋体">。</span></p>
<p>9<span style="font-family: 宋体">．最后将生成的</span>rule<span style="font-family: 宋体">添加到</span>ruleset<span style="font-family: 宋体">中，并最好在大批量的代码中进行验证。</span></p>
 <img src ="http://www.blogjava.net/ldd600/aggbug/198534.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ldd600/" target="_blank">叱咤红人</a> 2008-05-05 18:46 <a href="http://www.blogjava.net/ldd600/articles/198534.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>