new ruleset for Android platform

git-svn-id: https://pmd.svn.sourceforge.net/svnroot/pmd/branches/pmd/4.2.x@6803 51baf565-9d33-0410-a72c-fc3788e3496d
This commit is contained in:
Xavier Le Vourch 2009-01-27 23:52:27 +00:00
parent 9b4b50560d
commit e26de08062
11 changed files with 332 additions and 2 deletions

View File

@ -0,0 +1,20 @@
package test.net.sourceforge.pmd.rules.android;
import org.junit.Before;
import test.net.sourceforge.pmd.testframework.SimpleAggregatorTst;
public class AndroidRulesTest extends SimpleAggregatorTst {
@Before
public void setUp() {
addRule("android", "CallSuperFirst");
addRule("android", "CallSuperLast");
addRule("android", "ProtectLogD");
addRule("android", "ProtectLogV");
}
public static junit.framework.Test suite() {
return new junit.framework.JUnit4TestAdapter(AndroidRulesTest.class);
}
}

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<test-data>
<test-code>
<description><![CDATA[
Success
]]></description>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class MyActivity extends Activity {
@Override
protected void onCreate(final Bundle state) {
super.onCreate(state);
foo();
}
}
]]></code>
</test-code>
<test-code>
<description><![CDATA[
Failure
]]></description>
<expected-problems>1</expected-problems>
<code><![CDATA[
public class MyActivity extends Activity {
@Override
protected void onCreate(final Bundle state) {
foo();
}
}
]]></code>
</test-code>
</test-data>

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<test-data>
<test-code>
<description><![CDATA[
Success
]]></description>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class MyActivity extends Activity {
@Override
protected void onPause() {
foo();
super.onPause();
}
}
]]></code>
</test-code>
<test-code>
<description><![CDATA[
Failure
]]></description>
<expected-problems>1</expected-problems>
<code><![CDATA[
public class MyActivity extends Activity {
@Override
protected void onPause() {
foo();
}
}
]]></code>
</test-code>
</test-data>

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<test-data>
<test-code>
<description><![CDATA[
Success
]]></description>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class MyActivity extends Activity {
protected void foo() {
if (Config.LOGD) {
Log.d("Tag", "msg 1");
}
bar();
if (Config.LOGD) Log.d("Tag", "msg 2");
bar();
if (Config.LOGD && OTHER_DEBUG_FLAG) {
Log.d("Tag", "msg 3");
}
}
}
]]></code>
</test-code>
<test-code>
<description><![CDATA[
Failure
]]></description>
<expected-problems>1</expected-problems>
<code><![CDATA[
public class MyActivity extends Activity {
protected void foo() {
Log.d("Tag", "msg");
bar();
}
}
]]></code>
</test-code>
</test-data>

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<test-data>
<test-code>
<description><![CDATA[
Success
]]></description>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class MyActivity extends Activity {
protected void foo() {
if (Config.LOGV) {
Log.v("Tag", "msg 1");
}
bar();
if (Config.LOGV) Log.v("Tag", "msg 2");
bar();
if (Config.LOGV && OTHER_DEBUG_FLAG) {
Log.v("Tag", "msg");
}
}
}
]]></code>
</test-code>
<test-code>
<description><![CDATA[
Failure
]]></description>
<expected-problems>1</expected-problems>
<code><![CDATA[
public class MyActivity extends Activity {
protected void foo() {
Log.v("Tag", "msg");
bar();
}
}
]]></code>
</test-code>
</test-data>

166
pmd/rulesets/android.xml Normal file
View File

@ -0,0 +1,166 @@
<?xml version="1.0"?>
<ruleset name="Android Rules"
xmlns="http://pmd.sf.net/ruleset/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"
xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd">
<description>
These rules deal with the Android SDK, mostly related to best practices.
To get better results, make sure that the auxclasspath is defined for type resolution to work.
</description>
<rule name="CallSuperFirst"
since="4.2.5"
message="super must be called at the start of the method"
class="net.sourceforge.pmd.rules.XPathRule"
externalInfoUrl="http://pmd.sourceforge.net/rules/android.html#CallSuperFirst">
<description>Super must be called at the start of the method</description>
<priority>3</priority>
<properties>
<property name="xpath">
<value><![CDATA[
//MethodDeclaration[MethodDeclarator[
@Image='onCreate' or
@Image='onConfigurationChanged' or
@Image='onPostCreate' or
@Image='onPostResume' or
@Image='onRestart' or
@Image='onRestoreInstanceState' or
@Image='onResume' or
@Image='onStart'
]]
/Block/BlockStatement[1]
[not(Statement/StatementExpression/PrimaryExpression/PrimaryPrefix[@Image= ancestor::MethodDeclaration/MethodDeclarator/@Image])]
[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[
typeof(@Image, 'android.app.Activity', 'Activity') or
typeof(@Image, 'android.app.Application', 'Application') or
typeof(@Image, 'android.app.Service', 'Service')
]]]
]]>
</value>
</property>
</properties>
<example><![CDATA[
public class DummyActivity extends Activity {
public void onCreate(Bundle bundle) {
// missing call to super.onCreate(bundle)
foo();
}
}
]]>
</example>
</rule>
<rule name="CallSuperLast"
since="4.2.5"
message="super must be called at the end of the method"
class="net.sourceforge.pmd.rules.XPathRule"
externalInfoUrl="http://pmd.sourceforge.net/rules/android.html#CallSuperLast">
<description>Super must be called at the end of the method</description>
<priority>3</priority>
<properties>
<property name="xpath">
<value>
<![CDATA[
//MethodDeclaration[MethodDeclarator[
@Image='onDestroy' or
@Image='onPause' or
@Image='onSaveInstanceState' or
@Image='onStop' or
@Image='onTerminate'
]]
/Block/BlockStatement[last()]
[not(Statement/StatementExpression/PrimaryExpression/PrimaryPrefix[@Image= ancestor::MethodDeclaration/MethodDeclarator/@Image])]
[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[
typeof(@Image, 'android.app.Activity', 'Activity') or
typeof(@Image, 'android.app.Application', 'Application') or
typeof(@Image, 'android.app.Service', 'Service')
]]]
]]>
</value>
</property>
</properties>
<example>
<![CDATA[
public class DummyActivity extends Activity {
public void onPause() {
foo();
// missing call to super.onPause()
}
}
]]>
</example>
</rule>
<rule name="ProtectLogD" since="4.2.5"
message="Log.d must be protected by checking Config.LOGD"
class="net.sourceforge.pmd.rules.XPathRule"
externalInfoUrl="http://pmd.sourceforge.net/rules/android.html#ProtectLogD">
<description>Log.d must be protected by checking Config.LOGD</description>
<priority>3</priority>
<properties>
<property name="xpath">
<value>
<![CDATA[
//PrimaryPrefix/Name[@Image='Log.d']
[not(ancestor::IfStatement/Expression[
PrimaryExpression/PrimaryPrefix/Name[@Image='Config.LOGD']
or
ConditionalAndExpression/PrimaryExpression/PrimaryPrefix/Name[@Image='Config.LOGD']
])]
]]>
</value>
</property>
</properties>
<example>
<![CDATA[
public class DummyActivity extends Activity {
public void foo() {
Log.d("TAG", "msg1"); // Bad
bar();
if (Config.LOGD) Log.d("TAG", "msg1"); // Good
}
}
]]>
</example>
</rule>
<rule name="ProtectLogV" since="4.2.5"
message="Log.v must be protected by checking Config.LOGV"
class="net.sourceforge.pmd.rules.XPathRule"
externalInfoUrl="http://pmd.sourceforge.net/rules/android.html#ProtectLogV">
<description>Log.v must be protected by checking Config.LOGV</description>
<priority>3</priority>
<properties>
<property name="xpath">
<value>
<![CDATA[
//PrimaryPrefix/Name[@Image='Log.v']
[not(ancestor::IfStatement/Expression[
PrimaryExpression/PrimaryPrefix/Name[@Image='Config.LOGV']
or
ConditionalAndExpression/PrimaryExpression/PrimaryPrefix/Name[@Image='Config.LOGV']
])]
]]>
</value>
</property>
</properties>
<example>
<![CDATA[
public class DummyActivity extends Activity {
public void foo() {
Log.v("TAG", "msg1"); // Bad
bar();
if (Config.LOGV) Log.v("TAG", "msg1"); // Good
}
]]>
</example>
</rule>
</ruleset>

View File

@ -7,6 +7,7 @@
xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd">
<description>Every Java Rule in PMD</description>
<rule ref="rulesets/android.xml"/>
<rule ref="rulesets/basic.xml"/>
<rule ref="rulesets/braces.xml"/>
<rule ref="rulesets/clone.xml"/>

View File

@ -1,2 +1,2 @@
rulesets.filenames=rulesets/basic.xml,rulesets/braces.xml,rulesets/clone.xml,rulesets/codesize.xml,rulesets/controversial.xml,rulesets/coupling.xml,rulesets/design.xml,rulesets/finalizers.xml,rulesets/imports.xml,rulesets/j2ee.xml,rulesets/javabeans.xml,rulesets/junit.xml,rulesets/logging-jakarta-commons.xml,rulesets/logging-java.xml,rulesets/migrating.xml,rulesets/naming.xml,rulesets/optimizations.xml,rulesets/strictexception.xml,rulesets/strings.xml,rulesets/sunsecure.xml,rulesets/unusedcode.xml
rulesets.testnames=rulesets/basic.xml,rulesets/braces.xml,rulesets/clone.xml,rulesets/codesize.xml,rulesets/controversial.xml,rulesets/coupling.xml,rulesets/design.xml,rulesets/finalizers.xml,rulesets/imports.xml,rulesets/j2ee.xml,rulesets/javabeans.xml,rulesets/junit.xml,rulesets/logging-jakarta-commons.xml,rulesets/logging-java.xml,rulesets/migrating.xml,rulesets/naming.xml,rulesets/optimizations.xml,rulesets/strictexception.xml,rulesets/strings.xml,rulesets/sunsecure.xml,rulesets/unusedcode.xml
rulesets.filenames=rulesets/android.xml,rulesets/basic.xml,rulesets/braces.xml,rulesets/clone.xml,rulesets/codesize.xml,rulesets/controversial.xml,rulesets/coupling.xml,rulesets/design.xml,rulesets/finalizers.xml,rulesets/imports.xml,rulesets/j2ee.xml,rulesets/javabeans.xml,rulesets/junit.xml,rulesets/logging-jakarta-commons.xml,rulesets/logging-java.xml,rulesets/migrating.xml,rulesets/naming.xml,rulesets/optimizations.xml,rulesets/strictexception.xml,rulesets/strings.xml,rulesets/sunsecure.xml,rulesets/unusedcode.xml
rulesets.testnames=rulesets/android.xml,rulesets/basic.xml,rulesets/braces.xml,rulesets/clone.xml,rulesets/codesize.xml,rulesets/controversial.xml,rulesets/coupling.xml,rulesets/design.xml,rulesets/finalizers.xml,rulesets/imports.xml,rulesets/j2ee.xml,rulesets/javabeans.xml,rulesets/junit.xml,rulesets/logging-jakarta-commons.xml,rulesets/logging-java.xml,rulesets/migrating.xml,rulesets/naming.xml,rulesets/optimizations.xml,rulesets/strictexception.xml,rulesets/strings.xml,rulesets/sunsecure.xml,rulesets/unusedcode.xml

View File

@ -41,6 +41,7 @@ public class SimpleRuleSetNameMapper {
}
private void populateNameMap() {
nameMap.put("android", "rulesets/android.xml");
nameMap.put("basic", "rulesets/basic.xml");
nameMap.put("jsp", "rulesets/basic-jsp.xml");
nameMap.put("jsf", "rulesets/basic-jsf.xml");

View File

@ -50,6 +50,7 @@
</menu>
<menu name="Rule Sets">
<item name="Index" href="/rules/index.html"/>
<item name="Android" href="/rules/android.html" />
<item name="Basic" href="/rules/basic.html" />
<item name="Braces" href="/rules/braces.html" />
<item name="Code Size" href="/rules/codesize.html" />

View File

@ -48,6 +48,7 @@
</menu>
<menu name="Rule Sets">
<item name="Index" href="/rules/index.html"/>
<item name="Android" href="/rules/android.html" />
<item name="Basic" href="/rules/basic.html" />
<item name="Braces" href="/rules/braces.html" />
<item name="Code Size" href="/rules/codesize.html" />