New DynamicXPathRule class to speed up XPath based rules by providing a base type for the XPath expression.

git-svn-id: https://pmd.svn.sourceforge.net/svnroot/pmd/trunk@4862 51baf565-9d33-0410-a72c-fc3788e3496d
This commit is contained in:
Xavier Le Vourch
2006-12-06 06:32:17 +00:00
parent 2b2869b853
commit 81a8aea958
20 changed files with 459 additions and 207 deletions

View File

@ -47,6 +47,7 @@ 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.
Performance Refactoring, XPath rules re-written as Java:
AssignmentInOperand
AvoidDollarSigns

File diff suppressed because it is too large Load Diff

View File

@ -11,7 +11,8 @@ The Braces Ruleset contains a collection of braces rules.
<rule name="IfStmtsMustUseBraces"
message="Avoid using if statements without curly braces"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="IfStatement"
externalInfoUrl="http://pmd.sourceforge.net/rules/braces.html#IfStmtsMustUseBraces">
<description>
Avoid using if statements without using curly braces.
@ -20,7 +21,7 @@ Avoid using if statements without using curly braces.
<property name="xpath">
<value>
<![CDATA[
//IfStatement[count(*) < 3][not(Statement/Block)]
.[count(*) < 3][not(Statement/Block)]
]]>
</value>
</property>
@ -41,7 +42,8 @@ Avoid using if statements without using curly braces.
<rule name="WhileLoopsMustUseBraces"
message="Avoid using 'while' statements without curly braces"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="WhileStatement"
externalInfoUrl="http://pmd.sourceforge.net/rules/braces.html#WhileLoopsMustUseBraces">
<description>
Avoid using 'while' statements without using curly braces.
@ -50,7 +52,7 @@ Avoid using 'while' statements without using curly braces.
<property name="xpath">
<value>
<![CDATA[
//WhileStatement[not(Statement/Block)]
.[not(Statement/Block)]
]]>
</value>
</property>
@ -69,7 +71,8 @@ public void doSomething() {
<rule name="IfElseStmtsMustUseBraces"
message="Avoid using 'if...else' statements without curly braces"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="Statement"
externalInfoUrl="http://pmd.sourceforge.net/rules/braces.html#IfElseStmtsMustUseBraces">
<description>
Avoid using if..else statements without using curly braces.
@ -78,7 +81,7 @@ Avoid using if..else statements without using curly braces.
<property name="xpath">
<value>
<![CDATA[
//Statement
.
[parent::IfStatement[@Else='true']]
[not(child::Block)]
[not(child::IfStatement)]
@ -105,7 +108,8 @@ Avoid using if..else statements without using curly braces.
<rule name="ForLoopsMustUseBraces"
message="Avoid using 'for' statements without curly braces"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="ForStatement"
externalInfoUrl="http://pmd.sourceforge.net/rules/braces.html#ForLoopsMustUseBraces">
<description>
Avoid using 'for' statements without using curly braces.
@ -114,7 +118,7 @@ Avoid using 'for' statements without using curly braces.
<property name="xpath">
<value>
<![CDATA[
//ForStatement[not(Statement/Block)]
.[not(Statement/Block)]
]]>
</value>
</property>

View File

@ -11,7 +11,8 @@ The Clone Implementation ruleset contains a collection of rules that find questi
<rule name="ProperCloneImplementation"
message="Object clone() should be implemented with super.clone()"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="MethodDeclarator"
externalInfoUrl="http://pmd.sourceforge.net/rules/clone.html#ProperCloneImplementation">
<description>
Object clone() should be implemented with super.clone().
@ -20,7 +21,7 @@ Object clone() should be implemented with super.clone().
<property name="xpath">
<value>
<![CDATA[
//ClassOrInterfaceDeclaration//MethodDeclarator
.
[@Image = 'clone']
[count(FormalParameters/*) = 0]
[count(../Block//*[
@ -48,7 +49,8 @@ class Foo{
<rule name="CloneThrowsCloneNotSupportedException"
message="clone() method should throw CloneNotSupportedException"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="MethodDeclaration"
externalInfoUrl="http://pmd.sourceforge.net/rules/clone.html#CloneThrowsCloneNotSupportedException">
<description>
The method clone() should throw a CloneNotSupportedException.
@ -57,7 +59,7 @@ The method clone() should throw a CloneNotSupportedException.
<property name="xpath">
<value>
<![CDATA[
.//MethodDeclaration
.
[
MethodDeclarator/@Image = 'clone'
and count(MethodDeclarator/FormalParameters/*) = 0
@ -86,7 +88,8 @@ and count(NameList/Name[contains
<rule name="CloneMethodMustImplementCloneable"
message="clone() method should be implemented only if implementing Cloneable interface"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="ClassOrInterfaceDeclaration"
externalInfoUrl="http://pmd.sourceforge.net/rules/clone.html#CloneMethodMustImplementCloneable">
<description>
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.
@ -95,7 +98,7 @@ The method clone() should only be implemented if the class implements the Clonea
<property name="xpath">
<value>
<![CDATA[
//ClassOrInterfaceDeclaration
.
[not(./ImplementsList/ClassOrInterfaceType
[@Image='Cloneable'])]
/ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration

View File

@ -15,7 +15,8 @@ most people really dislike :-)
<rule name="UnnecessaryConstructor"
message="Avoid unnecessary constructors - the compiler will generate these for you"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="ClassOrInterfaceBody"
externalInfoUrl="http://pmd.sourceforge.net/rules/controversial.html#UnnecessaryConstructor">
<description>
This rule detects when a constructor is not necessary; i.e., when there's only one constructor,
@ -25,8 +26,7 @@ it's public, has an empty body, and takes no arguments.
<property name="xpath">
<value>
<![CDATA[
//ClassOrInterfaceDeclaration
/ClassOrInterfaceBody[count(ClassOrInterfaceBodyDeclaration/ConstructorDeclaration)=1]
.[count(ClassOrInterfaceBodyDeclaration/ConstructorDeclaration)=1]
/ClassOrInterfaceBodyDeclaration/ConstructorDeclaration
[@Public='true']
[not(FormalParameters/*)]
@ -154,7 +154,8 @@ public class Foo {
<rule name="AtLeastOneConstructor"
message="Each class should declare at least one constructor"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="ClassOrInterfaceDeclaration"
externalInfoUrl="http://pmd.sourceforge.net/rules/controversial.html#AtLeastOneConstructor">
<description>
Each class should declare at least one constructor.
@ -163,7 +164,7 @@ Each class should declare at least one constructor.
<property name="xpath">
<value>
<![CDATA[
//ClassOrInterfaceDeclaration
.
[not(ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/ConstructorDeclaration)]
[@Interface='false']
]]>
@ -227,7 +228,8 @@ public class Foo {
<rule name="CallSuperInConstructor"
message="It is a good practice to call super() in a constructor"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="ClassOrInterfaceDeclaration"
externalInfoUrl="http://pmd.sourceforge.net/rules/controversial.html#CallSuperInConstructor">
<description>
It is a good practice to call super() in a constructor. If super() is not called but
@ -237,7 +239,7 @@ It is a good practice to call super() in a constructor. If super() is not called
<property name="xpath">
<value>
<![CDATA[
//ClassOrInterfaceDeclaration[ count (ExtendsList/*) > 0 ]
.[ count (ExtendsList/*) > 0 ]
/ClassOrInterfaceBody
/ClassOrInterfaceBodyDeclaration
/ConstructorDeclaration[ count (.//ExplicitConstructorInvocation)=0 ]
@ -265,7 +267,8 @@ public class Foo extends Bar{
<rule name="UnnecessaryParentheses"
message="This statement may have some unnecessary parentheses"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="ReturnStatement"
externalInfoUrl="http://pmd.sourceforge.net/rules/controversial.html#UnnecessaryParentheses">
<description>
Sometimes expressions are wrapped in unnecessary parentheses,
@ -275,7 +278,7 @@ making them look like a function call.
<property name="xpath">
<value>
<![CDATA[
//ReturnStatement
.
/Expression
/PrimaryExpression
/PrimaryPrefix
@ -319,7 +322,8 @@ public class Foo {
<rule name="DefaultPackage"
message="Use explicit scoping instead of the default package private level"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="ClassOrInterfaceDeclaration"
externalInfoUrl="http://pmd.sourceforge.net/rules/controversial.html#DefaultPackage">
<description>
Use explicit scoping instead of the default package private level.
@ -327,7 +331,7 @@ Use explicit scoping instead of the default package private level.
<properties>
<property name="xpath">
<value><![CDATA[
//ClassOrInterfaceDeclaration[@Interface='false']
.[@Interface='false']
/ClassOrInterfaceBody
/ClassOrInterfaceBodyDeclaration
/FieldDeclaration[@PackagePrivate='true']
@ -340,7 +344,8 @@ Use explicit scoping instead of the default package private level.
<rule name="BooleanInversion"
message="Use bitwise inversion to invert boolean values"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="AssignmentOperator"
externalInfoUrl="http://pmd.sourceforge.net/rules/controversial.html#BooleanInversion">
<description>
Use bitwise inversion to invert boolean values - it's the fastest way to do this.
@ -350,7 +355,7 @@ See http://www.javaspecialists.co.za/archive/newsletter.do?issue=042&amp;locale=
<property name="xpath">
<value>
<![CDATA[
//AssignmentOperator[@Image="="]/../Expression/UnaryExpressionNotPlusMinus[@Image="!"]
.[@Image="="]/../Expression/UnaryExpressionNotPlusMinus[@Image="!"]
]]>
</value>
</property>

File diff suppressed because it is too large Load Diff

View File

@ -12,7 +12,8 @@ These rules deal with different problems that can occur with finalizers.
<rule name="EmptyFinalizer"
message="Avoid empty finalize methods"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="MethodDeclaration"
externalInfoUrl="http://pmd.sourceforge.net/rules/finalizers.html#EmptyFinalizer">
<description>
If the finalize() method is empty, then it does not need to exist.
@ -21,7 +22,7 @@ If the finalize() method is empty, then it does not need to exist.
<property name="xpath">
<value>
<![CDATA[
//MethodDeclaration[MethodDeclarator[@Image='finalize'][not(FormalParameters/*)]]
.[MethodDeclarator[@Image='finalize'][not(FormalParameters/*)]]
/Block[count(*)=0]
]]>
</value>
@ -39,7 +40,8 @@ public class Foo {
<rule name="FinalizeOnlyCallsSuperFinalize"
message="Finalize should do something besides just calling super.finalize()"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="MethodDeclaration"
externalInfoUrl="http://pmd.sourceforge.net/rules/finalizers.html#FinalizeOnlyCallsSuperFinalize">
<description>
If the finalize() is implemented, it should do something besides just calling
@ -49,7 +51,7 @@ super.finalize().
<property name="xpath">
<value>
<![CDATA[
//MethodDeclaration[MethodDeclarator[@Image="finalize"][not(FormalParameters/*)]]
.[MethodDeclarator[@Image="finalize"][not(FormalParameters/*)]]
/Block[count(BlockStatement)=1]
/BlockStatement[
Statement/StatementExpression/PrimaryExpression
@ -73,7 +75,8 @@ public class Foo {
<rule name="FinalizeOverloaded"
message="Finalize methods should not be overloaded"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="MethodDeclaration"
externalInfoUrl="http://pmd.sourceforge.net/rules/finalizers.html#FinalizeOverloaded">
<description>
Methods named finalize() should not have parameters. It is
@ -84,7 +87,7 @@ not be called by the VM.
<property name="xpath">
<value>
<![CDATA[
//MethodDeclaration
.
/MethodDeclarator[@Image='finalize'][FormalParameters[count(*)>0]]
]]>
</value>
@ -104,7 +107,8 @@ public class Foo {
<rule name="FinalizeDoesNotCallSuperFinalize"
message="Last statement in finalize method should be a call to super.finalize()"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="MethodDeclaration"
externalInfoUrl="http://pmd.sourceforge.net/rules/finalizers.html#FinalizeDoesNotCallSuperFinalize">
<description>
If the finalize() is implemented, its last action should be to call super.finalize.
@ -115,7 +119,7 @@ If the finalize() is implemented, its last action should be to call super.finali
<!-- in english: a method declaration of finalize(), with no arguments, containing
a block whose last statement is NOT a call to super.finalize -->
<![CDATA[
//MethodDeclaration[MethodDeclarator[@Image='finalize'][not(FormalParameters/*)]]
.[MethodDeclarator[@Image='finalize'][not(FormalParameters/*)]]
/Block
/BlockStatement[last()]
[not(Statement/StatementExpression/PrimaryExpression/PrimaryPrefix[@Image='finalize'])]
@ -141,7 +145,8 @@ public class Foo {
<rule name="FinalizeShouldBeProtected"
message="If you override finalize(), make it protected"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="MethodDeclaration"
externalInfoUrl="http://pmd.sourceforge.net/rules/finalizers.html#FinalizeShouldBeProtected">
<description>
If you override finalize(), make it protected. If you make
@ -151,7 +156,7 @@ If you override finalize(), make it protected. If you make
<property name="xpath">
<value>
<![CDATA[
//MethodDeclaration[@Protected="false"]
.[@Protected="false"]
/MethodDeclarator[@Image="finalize"]
[not(FormalParameters/*)]
]]>

View File

@ -8,7 +8,8 @@
<rule name="UseProperClassLoader"
message="In J2EE, getClassLoader() might not work as expected. Use Thread.currentThread().getContextClassLoader() instead."
class="net.sourceforge.pmd.rules.XPathRule">
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="PrimarySuffix">
<description>
In J2EE getClassLoader() might not work as expected. Use Thread.currentThread().getContextClassLoader() instead.
</description>
@ -16,7 +17,7 @@
<property name="xpath">
<value>
<![CDATA[
//PrimarySuffix[@Image='getClassLoader']
.[@Image='getClassLoader']
]]>
</value>
</property>
@ -31,4 +32,4 @@ public class Foo {
</example>
</rule>
</ruleset>
</ruleset>

View File

@ -49,7 +49,8 @@ provide getFoo and setFoo methods.
<rule name="MissingSerialVersionUID"
message="Classes implementing Serializable should set a serialVersionUID"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="ClassOrInterfaceDeclaration"
externalInfoUrl="http://pmd.sourceforge.net/rules/javabeans.html#MissingSerialVersionUID">
<description>
Classes that are serializable should provide a serialVersionUID field.
@ -58,7 +59,7 @@ Classes that are serializable should provide a serialVersionUID field.
<property name="xpath">
<value>
<![CDATA[
//ClassOrInterfaceDeclaration
.
[
count(ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration
/FieldDeclaration/VariableDeclarator/VariableDeclaratorId[@Image='serialVersionUID']) = 0
@ -84,4 +85,4 @@ public class Foo implements java.io.Serializable {
</example>
</rule>
</ruleset>
</ruleset>

View File

@ -11,7 +11,8 @@ These rules deal with different problems that can occur with JUnit tests.
<rule name="JUnitStaticSuite"
message="You have a suite() method that is not both public and static, so JUnit won't call it to get your TestSuite. Is that what you wanted to do?"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="MethodDeclaration"
externalInfoUrl="http://pmd.sourceforge.net/rules/junit.html#JUnitStaticSuite">
<description>
The suite() method in a JUnit test needs to be both public and static.
@ -20,7 +21,7 @@ The suite() method in a JUnit test needs to be both public and static.
<property name="xpath">
<value>
<![CDATA[
//MethodDeclaration[not(@Static='true') or not(@Public='true')]
.[not(@Static='true') or not(@Public='true')]
[MethodDeclarator/@Image='suite']
[MethodDeclarator/FormalParameters/@ParameterCount=0]
]]>
@ -42,7 +43,8 @@ public class Foo extends TestCase {
<rule name="JUnitSpelling"
message="You may have misspelled a JUnit framework method (setUp or tearDown)"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="MethodDeclarator"
externalInfoUrl="http://pmd.sourceforge.net/rules/junit.html#JUnitSpelling">
<description>
Some JUnit framework methods are easy to misspell.
@ -51,7 +53,7 @@ Some JUnit framework methods are easy to misspell.
<property name="xpath">
<value>
<![CDATA[
//MethodDeclarator[(not(@Image = 'setUp')
.[(not(@Image = 'setUp')
and translate(@Image, 'SETuP', 'setUp') = 'setUp')
or (not(@Image = 'tearDown')
and translate(@Image, 'TEARdOWN', 'tearDown') = 'tearDown')]
@ -144,7 +146,8 @@ public class CarTest {
<rule name="UnnecessaryBooleanAssertion"
message="assertTrue(true) or similar statements are unnecessary"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="StatementExpression"
externalInfoUrl="http://pmd.sourceforge.net/rules/junit.html#UnnecessaryBooleanAssertion">
<description>
A JUnit test assertion with a boolean literal is unnecessary since it always will eval to the same thing.
@ -155,7 +158,7 @@ statements like assertTrue(true) and assertFalse(false). If you just want a tes
<property name="xpath">
<value>
<![CDATA[
//StatementExpression
.
[
.//Name[@Image='assertTrue' or @Image='assertFalse']
and
@ -190,7 +193,8 @@ public class SimpleTest extends TestCase {
<rule name="UseAssertEqualsInsteadOfAssertTrue"
message="Use assertEquals(x, y) instead of assertTrue(x.equals(y))"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="PrimaryExpression"
externalInfoUrl="http://pmd.sourceforge.net/rules/junit.html#UseAssertEqualsInsteadOfAssertTrue">
<description>
This rule detects JUnit assertions in object equality. These assertions
@ -200,7 +204,7 @@ should be made by more specific methods, like assertEquals.
<property name="xpath">
<value>
<![CDATA[
//PrimaryExpression[
.[
PrimaryPrefix/Name[@Image = 'assertTrue']
][
PrimarySuffix/Arguments/ArgumentList/Expression/PrimaryExpression/PrimaryPrefix/Name
@ -226,7 +230,8 @@ public class FooTest extends TestCase {
<rule name="UseAssertSameInsteadOfAssertTrue"
message="Use assertSame(x, y) instead of assertTrue(x==y), or assertNotSame(x,y) vs assertFalse(x==y)"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="PrimaryExpression"
externalInfoUrl="http://pmd.sourceforge.net/rules/junit.html#UseAssertSameInsteadOfAssertTrue">
<description>
This rule detects JUnit assertions in object references equality. These assertions
@ -236,7 +241,7 @@ should be made by more specific methods, like assertSame, assertNotSame.
<property name="xpath">
<value>
<![CDATA[
//PrimaryExpression [
.[
PrimaryPrefix/Name
[@Image = 'assertTrue' or @Image = 'assertFalse']
]
@ -263,7 +268,8 @@ public class FooTest extends TestCase {
<rule name="UseAssertNullInsteadOfAssertTrue"
message="Use assertNull(x) instead of assertTrue(x==null), or assertNotNull(x) vs assertFalse(x==null)"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="PrimaryExpression"
externalInfoUrl="http://pmd.sourceforge.net/rules/junit.html#UseAssertNullInsteadOfAssertTrue">
<description>
This rule detects JUnit assertions in object references equality. These assertions
@ -273,7 +279,7 @@ public class FooTest extends TestCase {
<property name="xpath">
<value>
<![CDATA[
//PrimaryExpression[
.[
PrimaryPrefix/Name[@Image = 'assertTrue' or @Image = 'assertFalse']
][
PrimarySuffix/Arguments/ArgumentList[
@ -302,7 +308,8 @@ public class FooTest extends TestCase {
<rule name="SimplifyBooleanAssertion"
message="assertTrue(!expr) can be replaced by assertFalse(expr)"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="StatementExpression"
externalInfoUrl="http://pmd.sourceforge.net/rules/junit.html#SimplifyBooleanAssertion">
<description>
Avoid negation in an assertTrue or assertFalse test.
@ -315,7 +322,7 @@ assertFalse(expr);
<property name="xpath">
<value>
<![CDATA[
//StatementExpression
.
[
.//Name[@Image='assertTrue' or @Image='assertFalse']
and

View File

@ -11,7 +11,8 @@ The Jakarta Commons Logging ruleset contains a collection of rules that find que
<rule name="UseCorrectExceptionLogging"
message="Use the correct logging statement for logging exceptions"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="CatchStatement"
externalInfoUrl="http://pmd.sourceforge.net/rules/logging-jakarta-commons.html#UseCorrectExceptionLogging">
<description>
To make sure the full stacktrace is printed out, use the logging statement with 2 arguments: a String and a Throwable.
@ -19,7 +20,7 @@ To make sure the full stacktrace is printed out, use the logging statement with
<properties>
<property name="xpath">
<value><![CDATA[
//CatchStatement/Block/BlockStatement/Statement/StatementExpression
./Block/BlockStatement/Statement/StatementExpression
/PrimaryExpression[PrimaryPrefix/Name[starts-with(@Image,
concat(//ClassOrInterfaceBodyDeclaration/FieldDeclaration
[Type//ClassOrInterfaceType[@Image='Log']]
@ -46,7 +47,8 @@ public class Main {
<rule name="ProperLogger"
message="Logger should be defined private static final and have the correct class"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="ClassOrInterfaceBodyDeclaration"
externalInfoUrl="http://pmd.sourceforge.net/rules/logging-jakarta-commons.html#ProperLogger">
<description>
Logger should normally be defined private static final and have the correct class.
@ -57,7 +59,7 @@ public class Main {
<property name="xpath">
<value>
<![CDATA[
//ClassOrInterfaceBodyDeclaration[FieldDeclaration//ClassOrInterfaceType[@Image='Log']
.[FieldDeclaration//ClassOrInterfaceType[@Image='Log']
and
not(FieldDeclaration[@Final='true'][@Static='true'][@Private='true'][//VariableDeclaratorId[@Image=$staticLoggerName]]
//ArgumentList//ClassOrInterfaceType/@Image = ancestor::ClassOrInterfaceDeclaration/@Image)

View File

@ -32,7 +32,8 @@ class Foo{
<rule name="LoggerIsNotStaticFinal"
message="The Logger variable declaration does not contain the static and final modifiers"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="VariableDeclarator"
externalInfoUrl="http://pmd.sourceforge.net/rules/logging-java.html#LoggerIsNotStaticFinal">
<description>
In most cases, the Logger can be declared static and final.
@ -41,7 +42,7 @@ In most cases, the Logger can be declared static and final.
<property name="xpath">
<value>
<![CDATA[
//VariableDeclarator
.
[parent::FieldDeclaration]
[../Type/ReferenceType
/ClassOrInterfaceType[@Image='Logger']
@ -101,7 +102,8 @@ first -->
<rule name="SystemPrintln"
message="System.out.print is used"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="Name"
externalInfoUrl="http://pmd.sourceforge.net/rules/logging-java.html#SystemPrintln">
<description>
System.(out|err).print is used, consider using a logger.
@ -110,7 +112,7 @@ System.(out|err).print is used, consider using a logger.
<property name="xpath">
<value>
<![CDATA[
//Name[
.[
starts-with(@Image, 'System.out.print')
or
starts-with(@Image, 'System.err.print')
@ -136,7 +138,8 @@ class Foo{
<rule name="AvoidPrintStackTrace"
message="Avoid printStackTrace(); use a logger call instead."
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="PrimaryExpression"
externalInfoUrl="http://pmd.sourceforge.net/rules/logging-java.html#AvoidPrintStackTrace">
<description>
Avoid printStackTrace(); use a logger call instead.
@ -145,7 +148,7 @@ Avoid printStackTrace(); use a logger call instead.
<property name="xpath">
<value>
<![CDATA[
//PrimaryExpression
.
[PrimaryPrefix/Name[contains(@Image,'printStackTrace')]]
[PrimarySuffix[not(boolean(Arguments/ArgumentList/Expression))]]
]]>

View File

@ -13,7 +13,8 @@ Contains rules about migrating from one JDK version to another. Don't use these
<rule name="ReplaceVectorWithList"
message="Consider replacing this Vector with the newer java.util.List"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="Type"
externalInfoUrl="http://pmd.sourceforge.net/rules/migrating.html#ReplaceVectorWithList">
<description>
Consider replacing Vector usages with the newer java.util.ArrayList if expensive threadsafe operation is not required.
@ -22,7 +23,7 @@ Contains rules about migrating from one JDK version to another. Don't use these
<property name="xpath">
<value>
<![CDATA[
//Type/ReferenceType/ClassOrInterfaceType[@Image='Vector']
./ReferenceType/ClassOrInterfaceType[@Image='Vector']
]]>
</value>
</property>
@ -41,7 +42,8 @@ public class Foo {
<rule name="ReplaceHashtableWithMap"
message="Consider replacing this Hashtable with the newer java.util.Map"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="Type"
externalInfoUrl="http://pmd.sourceforge.net/rules/migrating.html#ReplaceHashtableWithMap">
<description>
Consider replacing this Hashtable with the newer java.util.Map
@ -50,7 +52,7 @@ public class Foo {
<property name="xpath">
<value>
<![CDATA[
//Type/ReferenceType/ClassOrInterfaceType[@Image='Hashtable']
./ReferenceType/ClassOrInterfaceType[@Image='Hashtable']
]]>
</value>
</property>
@ -69,7 +71,8 @@ public class Foo {
<rule name="ReplaceEnumerationWithIterator"
message="Consider replacing this Enumeration with the newer java.util.Iterator"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="ImplementsList"
externalInfoUrl="http://pmd.sourceforge.net/rules/migrating.html#ReplaceEnumerationWithIterator">
<description>
Consider replacing this Enumeration with the newer java.util.Iterator
@ -78,7 +81,7 @@ public class Foo {
<property name="xpath">
<value>
<![CDATA[
//ImplementsList/ClassOrInterfaceType[@Image='Enumeration']
./ClassOrInterfaceType[@Image='Enumeration']
]]>
</value>
</property>
@ -101,14 +104,15 @@ public class Foo implements Enumeration {
<rule name="AvoidEnumAsIdentifier"
message="Avoid using enum as an identifier; it's a reserved word in JDK 1.5"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="VariableDeclaratorId"
externalInfoUrl="http://pmd.sourceforge.net/rules/migrating.html#AvoidEnumAsIdentifier">
<description>Finds all places 'enum' is used as an identifier is used.</description>
<properties>
<property name="xpath">
<value>
<![CDATA[
//VariableDeclaratorId[@Image='enum']
.[@Image='enum']
]]>
</value>
</property>
@ -127,14 +131,15 @@ public class Foo implements Enumeration {
<rule name="AvoidAssertAsIdentifier"
message="Avoid using assert as an identifier; it's a reserved word in JDK 1.4"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="VariableDeclaratorId"
externalInfoUrl="http://pmd.sourceforge.net/rules/migrating.html#AvoidAssertAsIdentifier">
<description>Finds all places 'assert' is used as an identifier is used.</description>
<properties>
<property name="xpath">
<value>
<![CDATA[
//VariableDeclaratorId[@Image='assert']
.[@Image='assert']
]]>
</value>
</property>
@ -153,13 +158,14 @@ public class Foo implements Enumeration {
<rule name="IntegerInstantiation"
message="Avoid instantiating Integer objects. Call Integer.valueOf() instead."
class="net.sourceforge.pmd.rules.XPathRule">
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="PrimaryPrefix">
<description>In JDK 1.5, calling new Integer() causes memory allocation. Integer.valueOf() is more memory friendly.</description>
<properties>
<property name="xpath">
<value>
<![CDATA[
//PrimaryPrefix
.
/AllocationExpression
[not (ArrayDimsAndInits)
and (ClassOrInterfaceType/@Image='Integer'

View File

@ -12,7 +12,8 @@ The Naming Ruleset contains a collection of rules about names - too long, too sh
<rule name="ShortVariable"
message="Avoid variables with short names like {0}"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="VariableDeclaratorId"
externalInfoUrl="http://pmd.sourceforge.net/rules/naming.html#ShortVariable">
<description>
Detects when a field, local, or parameter has a very short name.
@ -21,7 +22,7 @@ Detects when a field, local, or parameter has a very short name.
<property name="xpath" pluginname="true">
<value>
<![CDATA[
//VariableDeclaratorId[string-length(@Image) < 3]
.[string-length(@Image) < 3]
[not(ancestor::ForInit)]
[not((ancestor::FormalParameter) and (ancestor::TryStatement))]
]]>
@ -46,7 +47,8 @@ public class Something {
<rule name="LongVariable"
message="Avoid excessively long variable names like {0}"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="VariableDeclaratorId"
externalInfoUrl="http://pmd.sourceforge.net/rules/naming.html#LongVariable">
<description>
Detects when a field, formal or local variable is declared with a long name.
@ -57,7 +59,7 @@ Detects when a field, formal or local variable is declared with a long name.
<property name="xpath" pluginname="true">
<value>
<![CDATA[
//VariableDeclaratorId[string-length(@Image) > $minimum]
.[string-length(@Image) > $minimum]
]]>
</value>
</property>
@ -79,7 +81,8 @@ public class Something {
<rule name="ShortMethodName"
message="Avoid using short method names"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="MethodDeclarator"
externalInfoUrl="http://pmd.sourceforge.net/rules/naming.html#ShortMethodName">
<description>
Detects when very short method names are used.
@ -89,7 +92,7 @@ Detects when very short method names are used.
<property name="xpath">
<value>
<![CDATA[
//MethodDeclarator[string-length(@Image) < 3]
.[string-length(@Image) < 3]
]]>
</value>
</property>
@ -167,7 +170,8 @@ public class Foo {}
<rule name="AbstractNaming"
message="Abstract classes should be named 'AbstractXXX'"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="ClassOrInterfaceDeclaration"
externalInfoUrl="http://pmd.sourceforge.net/rules/naming.html#AbstractNaming">
<description>
Abstract classes should be named 'AbstractXXX'.
@ -177,7 +181,7 @@ Abstract classes should be named 'AbstractXXX'.
<property name="xpath">
<value>
<![CDATA[
//ClassOrInterfaceDeclaration
.
[@Abstract='true' and @Interface='false']
[not (starts-with(@Image,'Abstract'))]
]]>
@ -250,7 +254,8 @@ public class Foo {
<rule name="SuspiciousConstantFieldName"
message="The field name indicates a constant but its modifiers do not"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="ClassOrInterfaceDeclaration"
externalInfoUrl="http://pmd.sourceforge.net/rules/naming.html#SuspiciousConstantFieldName">
<description>
A field name is all in uppercase characters, which in Sun's Java naming
@ -260,7 +265,7 @@ conventions indicate a constant. However, the field is not final.
<property name="xpath">
<value>
<![CDATA[
//ClassOrInterfaceDeclaration[@Interface='false']
.[@Interface='false']
/ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/FieldDeclaration
[@Final='false']
[VariableDeclarator/VariableDeclaratorId[upper-case(@Image)=@Image]]
@ -284,7 +289,8 @@ public class Foo {
<rule
name="SuspiciousEqualsMethodName"
message="The method name and parameter number are suspiciously close to equals(Object)"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="MethodDeclarator"
externalInfoUrl="http://pmd.sourceforge.net/rules/naming.html#SuspiciousEqualsMethodName">
<description>
The method name and parameter number are suspiciously close to
@ -295,7 +301,7 @@ method.
<property name="xpath">
<value>
<![CDATA[
//MethodDeclarator [
.[
(
@Image = 'equals'
and count(FormalParameters/*) = 1
@ -391,7 +397,8 @@ public class Foo {
<rule name="NoPackage"
message="All classes and interfaces must belong to a named package"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="ClassOrInterfaceDeclaration"
externalInfoUrl="http://pmd.sourceforge.net/rules/naming.html#NoPackage">
<description>
Detects when a class or interface does not have a package definition.
@ -400,7 +407,7 @@ Detects when a class or interface does not have a package definition.
<property name="xpath" pluginname="true">
<value>
<![CDATA[
//ClassOrInterfaceDeclaration[count(preceding::PackageDeclaration) = 0]
.[count(preceding::PackageDeclaration) = 0]
]]>
</value>
</property>
@ -417,7 +424,8 @@ public class ClassInDefaultPackage {
<rule name="PackageCase"
message="Package name contains upper case characters"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="PackageDeclaration"
externalInfoUrl="http://pmd.sourceforge.net/rules/naming.html#PackageCase">
<description>
Detects when a package definition contains upper case characters.
@ -426,7 +434,7 @@ public class ClassInDefaultPackage {
<property name="xpath" pluginname="true">
<value>
<![CDATA[
//PackageDeclaration/Name[lower-case(@Image)!=@Image]
./Name[lower-case(@Image)!=@Image]
]]>
</value>
</property>
@ -443,7 +451,8 @@ public class SomeClass {
<rule name="MisleadingVariableName"
message="Avoid naming non-fields with the prefix 'm_'"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="VariableDeclaratorId"
externalInfoUrl="http://pmd.sourceforge.net/rules/naming.html#MisleadingVariableName">
<description>
Detects when a non-field has a name starting with 'm_'. This usually
@ -453,7 +462,7 @@ indicates a field and thus is confusing.
<property name="xpath" pluginname="true">
<value>
<![CDATA[
//VariableDeclaratorId
.
[starts-with(@Image, 'm_')]
[not (../../../FieldDeclaration)]
]]>

View File

@ -70,7 +70,8 @@ public class Something {
<rule name="UseArrayListInsteadOfVector"
message="Use ArrayList instead of Vector"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="AllocationExpression"
externalInfoUrl="http://pmd.sourceforge.net/rules/optimizations.html#UseArrayListInsteadOfVector">
<description>
ArrayList is a much better Collection implementation than Vector.
@ -79,7 +80,7 @@ ArrayList is a much better Collection implementation than Vector.
<property name="xpath">
<value>
<![CDATA[
//AllocationExpression
.
/ClassOrInterfaceType[@Image='Vector' or @Image='java.util.Vector']
]]>
</value>
@ -101,7 +102,8 @@ public class SimpleTest extends TestCase {
<rule name="SimplifyStartsWith"
message="This call to String.startsWith can be rewritten using String.charAt(0)"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="PrimaryExpression"
externalInfoUrl="http://pmd.sourceforge.net/rules/optimizations.html#SimplifyStartsWith">
<description>
Since it passes in a literal of length 1, this call to String.startsWith can be rewritten using String.charAt(0) to save some time.
@ -110,7 +112,7 @@ Since it passes in a literal of length 1, this call to String.startsWith can be
<property name="xpath">
<value>
<![CDATA[
//PrimaryExpression
.
[PrimaryPrefix/Name
[ends-with(@Image, '.startsWith')]]
[PrimarySuffix/Arguments/ArgumentList
@ -164,7 +166,8 @@ public class Foo {
<rule name="UseArraysAsList"
message="Use asList instead of tight loops"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="Statement"
externalInfoUrl="http://pmd.sourceforge.net/rules/optimizations.html#UseArraysAsList">
<description>
The class java.util.Arrays has a "asList" method that
@ -176,7 +179,7 @@ public class Foo {
<property name="xpath">
<value>
<![CDATA[
//Statement[
.[
(ForStatement) and (count(.//IfStatement)=0)
]
//StatementExpression[
@ -228,7 +231,8 @@ public class Foo {
<rule name="AvoidArrayLoops"
message="System.arrayCopy is more efficient"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="Statement"
externalInfoUrl="http://pmd.sourceforge.net/rules/optimizations.html#AvoidArrayLoops">
<description>
Instead of copying data between two arrays, use
@ -238,7 +242,7 @@ public class Foo {
<property name="xpath">
<value>
<![CDATA[
//Statement[(ForStatement or WhileStatement) and
.[(ForStatement or WhileStatement) and
count(*//AssignmentOperator[@Image = '='])=1
and
*/Statement

View File

@ -12,7 +12,8 @@ These are new rules that are still in progress.
<rule name="AvoidUsingOctalValues"
message="Do not start a literal by 0 unless it's an octal value"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="Literal"
externalInfoUrl="http://pmd.sourceforge.net/rules/basic.html#AvoidUsingOctalValues">
<description>
Integers literals should not start with zero.
@ -24,7 +25,7 @@ interprated as an octal.
<value>
<![CDATA[
//Literal
.
[(starts-with(@Image, 0))]
[not(substring(@Image, 2, 1) = 'x')]
[not(substring(@Image, 2, 1) = 'L')]

View File

@ -79,7 +79,8 @@ public class Foo {
<rule name="AvoidCatchingNPE"
message="Avoid catching NullPointerException; consider removing the cause of the NPE."
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="CatchStatement"
externalInfoUrl="http://pmd.sourceforge.net/rules/strictexception.html#AvoidCatchingNPE">
<description>
Code should never throw NPE under normal circumstances. A catch block may hide the original error, causing other more subtle errors in its wake.
@ -100,7 +101,7 @@ public class Foo {
<property name="xpath">
<value>
<![CDATA[
//CatchStatement/FormalParameter/Type
./FormalParameter/Type
/ReferenceType/ClassOrInterfaceType[@Image='NullPointerException']
]]>
</value>
@ -110,7 +111,8 @@ public class Foo {
<rule name="AvoidThrowingRawExceptionTypes"
message="Avoid throwing raw exception types."
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="AllocationExpression"
externalInfoUrl="http://pmd.sourceforge.net/rules/strictexception.html#AvoidThrowingRawExceptionTypes">
<description>
Avoid throwing certain exception types. Rather than throw a raw RuntimeException, Throwable,
@ -130,7 +132,7 @@ public void bar() throws Exception {
<property name="xpath">
<value>
<![CDATA[
//AllocationExpression
.
/ClassOrInterfaceType[
@Image='Throwable' or
@Image='Exception' or
@ -144,7 +146,8 @@ public void bar() throws Exception {
<rule name="AvoidThrowingNullPointerException"
message="Avoid throwing null pointer exceptions."
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="AllocationExpression"
externalInfoUrl="http://pmd.sourceforge.net/rules/strictexception.html#AvoidThrowingNullPointerException">
<description>
Avoid throwing a NullPointerException - it's confusing because most people will assume that the
@ -165,7 +168,7 @@ public class Foo {
<property name="xpath">
<value>
<![CDATA[
//AllocationExpression/ClassOrInterfaceType[@Image='NullPointerException']
./ClassOrInterfaceType[@Image='NullPointerException']
]]>
</value>
</property>
@ -174,7 +177,8 @@ public class Foo {
<rule name="AvoidRethrowingException"
message="A catch statement that catches an exception only to rethrow it should be avoided."
class="net.sourceforge.pmd.rules.XPathRule">
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="CatchStatement">
<description>
Catch blocks that merely rethrow a caught exception only add to code size and runtime complexity.
</description>
@ -195,7 +199,7 @@ public class Foo {
<property name="xpath">
<value>
<![CDATA[
//CatchStatement[FormalParameter
.[FormalParameter
/VariableDeclaratorId/@Image = Block/BlockStatement/Statement
/ThrowStatement/Expression/PrimaryExpression[count(PrimarySuffix)=0]/PrimaryPrefix/Name/@Image
and count(Block/BlockStatement/Statement) =1]

View File

@ -291,7 +291,8 @@ public String convert(int i) {
<rule name="StringBufferInstantiationWithChar"
message="Do not instantiate a StringBuffer with a char"
class="net.sourceforge.pmd.rules.XPathRule"
class="net.sourceforge.pmd.rules.DynamicXPathRule"
type="AllocationExpression"
externalInfoUrl="http://pmd.sourceforge.net/rules/strings.html#StringBufferInstantiationWithChar">
<description>
StringBuffer sb = new StringBuffer('c'); The
@ -302,7 +303,7 @@ StringBuffer size.
<property name="xpath">
<value>
<![CDATA[
//AllocationExpression/ClassOrInterfaceType
./ClassOrInterfaceType
[@Image='StringBuffer']
/../Arguments/ArgumentList/Expression/PrimaryExpression
/PrimaryPrefix/

View File

@ -21,6 +21,8 @@ import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;
import net.sourceforge.pmd.rules.DynamicXPathRule;
// Note that ruleset parsing may fail on JDK 1.6 beta
// due to this bug - http://www.netbeans.org/issues/show_bug.cgi?id=63257
@ -280,7 +282,14 @@ public class RuleSetFactory {
Element ruleElement = (Element) ruleNode;
String attribute = ruleElement.getAttribute("class");
Rule rule = (Rule) classLoader.loadClass(attribute).newInstance();
Class c;
if (attribute.equals("net.sourceforge.pmd.rules.DynamicXPathRule")) {
String type = ruleElement.getAttribute("type");
c = DynamicXPathRule.loadClass(classLoader, type);
} else {
c = classLoader.loadClass(attribute);
}
Rule rule = (Rule) c.newInstance();
rule.setName(ruleElement.getAttribute("name"));
rule.setMessage(ruleElement.getAttribute("message"));

View File

@ -0,0 +1,142 @@
package net.sourceforge.pmd.rules;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import net.sourceforge.pmd.AbstractRule;
import net.sourceforge.pmd.ast.ASTVariableDeclaratorId;
import net.sourceforge.pmd.ast.Node;
import net.sourceforge.pmd.ast.SimpleNode;
import net.sourceforge.pmd.jaxen.DocumentNavigator;
import net.sourceforge.pmd.jaxen.MatchesFunction;
import org.jaxen.BaseXPath;
import org.jaxen.JaxenException;
import org.jaxen.SimpleVariableContext;
import org.jaxen.XPath;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
public class DynamicXPathRule extends AbstractRule implements Opcodes {
protected DynamicXPathRule() {
}
private static HashMap classes = new HashMap();
public static synchronized Class loadClass(ClassLoader classloader, String type) {
Class c = (Class) classes.get(type);
if (c == null) {
byte bytecode[] = buildClass(type);
c = new ByteArrayClassLoader(classloader).loadClass(bytecode);
classes.put(type, c);
}
return c;
}
private static class ByteArrayClassLoader extends ClassLoader {
ByteArrayClassLoader(ClassLoader parent) {
super(parent);
}
Class loadClass(byte[] data) {
return defineClass(null, data, 0, data.length, null);
}
}
private static byte[] buildClass(String type) {
String className = "net/sourceforge/pmd/rules/" + type + "XPathRule";
String methodSig = "(Lnet/sourceforge/pmd/ast/AST" + type + ";Ljava/lang/Object;)Ljava/lang/Object;";
ClassWriter cw = new ClassWriter(0);
MethodVisitor mv;
cw.visit(V1_4, ACC_PUBLIC + ACC_SUPER, className, null, "net/sourceforge/pmd/rules/DynamicXPathRule", null);
mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "net/sourceforge/pmd/rules/DynamicXPathRule", "<init>", "()V");
mv.visitInsn(RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
mv = cw.visitMethod(ACC_PUBLIC, "visit", methodSig, null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ALOAD, 2);
mv.visitMethodInsn(INVOKEVIRTUAL, className, "evaluate", "(Lnet/sourceforge/pmd/ast/Node;Ljava/lang/Object;)V");
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ALOAD, 2);
mv.visitMethodInsn(INVOKESPECIAL, "net/sourceforge/pmd/rules/DynamicXPathRule", "visit", methodSig);
mv.visitInsn(ARETURN);
mv.visitMaxs(3, 3);
mv.visitEnd();
cw.visitEnd();
return cw.toByteArray();
}
private XPath xpath;
private boolean regexpFunctionRegistered;
/**
* Evaluate the AST with compilationUnit as root-node, against
* the XPath expression found as property with name "xpath".
* All matches are reported as violations.
*
* @param compilationUnit the Node that is the root of the AST to be checked
* @param data
*/
public void evaluate(Node compilationUnit, Object data) {
try {
initializeXPathExpression();
List results = xpath.selectNodes(compilationUnit);
for (Iterator i = results.iterator(); i.hasNext();) {
SimpleNode n = (SimpleNode) i.next();
if (n instanceof ASTVariableDeclaratorId && getBooleanProperty("pluginname")) {
addViolation(data, n, n.getImage());
} else {
addViolation(data, (SimpleNode) n, getMessage());
}
}
} catch (JaxenException ex) {
throw new RuntimeException(ex);
}
}
private void initializeXPathExpression() throws JaxenException {
if (xpath != null) {
return;
}
if (!regexpFunctionRegistered) {
MatchesFunction.registerSelfInSimpleContext();
regexpFunctionRegistered = true;
}
xpath = new BaseXPath(getStringProperty("xpath"), new DocumentNavigator());
if (properties.size() > 1) {
SimpleVariableContext vc = new SimpleVariableContext();
for (Iterator i = properties.entrySet().iterator(); i.hasNext();) {
Entry e = (Entry) i.next();
if (!"xpath".equals(e.getKey())) {
vc.setVariableValue((String) e.getKey(), e.getValue());
}
}
xpath.setVariableContext(vc);
}
}
}