PMD 기본 규칙
잡동사니
| 앤트 작업 |
| 규칙 |
|---|
| 기본 규칙 |
http://pmd.sourceforge.net/rules/basic.html
기본 규칙은 대부분의 개발에서 실질적으로 쓰일만한 것을 포함하고 있다.
빈 예외잡기 블럭 (EmptyCatchBlock)
http://pmd.sourceforge.net/rules/basic.html#EmptyCatchBlock
- 도입
- PMD 0.1
이 규칙은 예외를 잡긴 잡으나(catch) 아무것도 하지 않는 블럭을 탐지한다. 이런 블럭은 예외가 보고되야 하든지, 아니면 무시하고 그 뒤 코드가 실행되야 하든지 간에 예외를 무조건 삼켜버리는 코드다.
- XPath 표현식
//CatchStatement [count(Block/BlockStatement) = 0 and ($allowCommentedBlocks != 'true' or Block/@containsComment = 'false')] [FormalParameter/Type/ReferenceType /ClassOrInterfaceType[@Image != 'InterruptedException' and @Image != 'CloneNotSupportedException'] ]
- 예제
public void doSomething() {
try {
FileInputStream fis = new FileInputStream("/tmp/bugger");
} catch (IOException ioe) {
// not good
}
}
- 속성
| 이름 | 기본값 | 설명 |
|---|---|---|
| allowCommentedBlocks | 주석이 있는 빈 블럭은 넘어간다. |
빈 조건문 (EmptyIfStmt)
http://pmd.sourceforge.net/rules/basic.html#EmptyIfStmt
- 도입
- PMD 0.1
이 규칙은 비어 있는 조건문을 탐지한다.
- XPath 표현식
//IfStatement/Statement [EmptyStatement or Block[count(*) = 0]]
- 예제
public class Foo {
void bar(int x) {
if (x == 0) {
// empty!
}
}
}
빈 반복문 (EmptyWhileStmt)
http://pmd.sourceforge.net/rules/basic.html#EmptyWhileStmt
- 도입
- PMD 0.2
이 규칙은 비어 있는 반복문을 탐지한다. 만일 시간제한 반복문을 사용하려면 Thread.sleep() 메서드를 사용하라. if it's a while loop that does a lot in the exit expression, rewrite it to make it clearer.
- XPath 표현식
//WhileStatement/Statement[./Block[count(*) = 0] or ./EmptyStatement]
- 예제
public class Foo {
void bar(int a, int b) {
while (a == b) {
// empty!
}
}
}
빈 시도문 (EmptyTryBlock)
http://pmd.sourceforge.net/rules/basic.html#EmptyTryBlock
- 도입
- PMD 0.4
이 규칙은 빈 시도문(try)을 탐지한다 - 무엇을 하고 싶은 건가?
- XPath 표현식
//TryStatement/Block[1][count(*) = 0]
- 예제
public class Foo {
public void bar() {
try {
} catch (Exception e) {
e.printStackTrace();
}
}
}
빈 최종문 (EmptyFinallyBlock)
http://pmd.sourceforge.net/rules/basic.html#EmptyFinallyBlock
- 도입
- PMD 0.4
이 규칙은 비어있는 최종문(finally)을 탐지한다 - 이 구문은 지워도 된다.
- XPath 표현식
//FinallyStatement[count(Block/BlockStatement) = 0]
- 예제
public class Foo {
public void bar() {
try {
int x=2;
} finally {
// empty!
}
}
}
빈 선택문 (EmptySwitchStatements)
http://pmd.sourceforge.net/rules/basic.html#EmptySwitchStatements
- 도입
- PMD 1.0
이 규칙은 비어있는 선택문(switch)을 탐지한다.
- XPath 표현식
//SwitchStatement[count(*) = 1]
- 예제
public class Foo {
public void bar() {
int x = 2;
switch (x) {
// once there was code here
// but it's been commented out or something
}
}
}
뒤섞인 증가문 (JumbledIncrementer)
http://pmd.sourceforge.net/rules/basic.html#JumbledIncrementer
- 도입
- PMD 1.0
이 규칙은 뒤섞인 증가문을 탐지한다. 이런 코드는 대부분 실수로 작성되며, 의도된 경우라도 혼란을 가져온다.
- XPath 표현식
//ForStatement [ ForUpdate/StatementExpressionList/StatementExpression/PostfixExpression/PrimaryExpression/PrimaryPrefix/Name/@Image = ancestor::ForStatement/ForInit//VariableDeclaratorId/@Image ]
- 예제
public class JumbledIncrementerRule1 {
public void foo() {
for (int i = 0; i < 10; i++) {
for (int k = 0; k < 20; i++) {
System.out.println("Hello");
}
}
}
}
For문을 While문으로 바꾸기 (ForLoopShouldBeWhileLoop)
http://pmd.sourceforge.net/rules/basic.html#ForLoopShouldBeWhileLoop
- 도입
- PMD 1.02
For문 일부는 whlie문으로 바꿀 수 있다. 이게 더 간결하다.
- XPath 표현식
//ForStatement [count(*) > 1] [not(ForInit)] [not(ForUpdate)] [not(Type and Expression and Statement)]
- 예제
public class Foo {
void bar() {
for (;true;) true; // No Init or Update part, may as well be: while (true)
}
}
불필요한 임시 변환 (UnnecessaryConversionTemporary)
- 도입
- PMD 1.02
이 규칙은 불필요한 기본형(primitive)의 문자열(String) 변환을 탐지한다.
이 규칙은 다음 자바 클래스에 정의되어 있다: net.sourceforge.pmd.rules.UnnecessaryConversionTemporary
- 예제
public String convert(int x) {
// this wastes an object
String foo = new Integer(x).toString();
// this is better
return Integer.toString(x);
}
Equals와 HashCode 재정의 (OverrideBothEqualsAndHashcode)
http://pmd.sourceforge.net/rules/basic.html#OverrideBothEqualsAndHashcode
- 도입
- PMD 0.4
이 규칙은 두 메서드(public boolean Object.equals(Object other), public int Object.hashCode())를 모두 재정의하거나 아니면 둘 다 재정의하지 않았는지를 탐지한다. 만일 상위클래스로부터 hashCode() 메서드를 상속받았다 하더라도 명시적으로 하위클래스 자체의 hashCode() 메서드를 구현할 것을 권장한다.
이 규칙은 다음 자바 클래스에 정의되어 있다: net.sourceforge.pmd.rules.OverrideBothEqualsAndHashcode
- 예제
// this is bad
public class Bar {
public boolean equals(Object o) {
// do some comparison
}
}
// and so is this
public class Baz {
public int hashCode() {
// return some hash value
}
}
// this is OK
public class Foo {
public boolean equals(Object other) {
// do some comparison
}
public int hashCode() {
// return some hash value
}
}
이중 검사 잠금 (DoubleCheckedLocking)
http://pmd.sourceforge.net/rules/basic.html#DoubleCheckedLocking
- 도입
- PMD 1.04
자바에서 이중 검사 잠금 패턴에 의해 객체가 부분적으로 생성되는 경우가 있습니다. 일부 JRE는 그 참조(reference)가 의도한 것과는 달리, 객체를 생성하기 이 전에 baz 변수에 참조를 할당하도록 최적화합니다. 자세한 것은 다음 문서를 보십시오: http://www.javaworld.com/javaworld/jw-02-2001/jw-0209-double.html
이중 검사 잠금 문서나 IBM developerWorks 기사를 참고하시기 바랍니다.
이 규칙은 다음 자바 클래스에 정의되어 있다: net.sourceforge.pmd.rules.DoubleCheckedLocking
- 예제
public class Foo {
Object baz;
Object bar() {
if(baz == null) { //baz may be non-null yet not fully created
synchronized(this){
if(baz == null){
baz = new Object();
}
}
}
return baz;
}
}
Finally 블럭에서 결과 반환 (ReturnFromFinallyBlock)
http://pmd.sourceforge.net/rules/basic.html#ReturnFromFinallyBlock
- 도입
- PMD 1.05
Finally 블럭에서 결과 반환은 피하십시오 - 이럴 경우 던져진 예외가 버려지게 됩니다.
- XPath 표현식
//FinallyStatement//ReturnStatement
- 예제
public class Bar {
public String foo() {
try {
throw new Exception( "My Exception" );
} catch (Exception e) {
throw e;
} finally {
return "A. O. K."; // Very bad.
}
}
}
빈 동기화 블럭 (EmptySynchronizedBlock)
http://pmd.sourceforge.net/rules/basic.html#EmptySynchronizedBlock
- 도입
- PMD 1.3
빈 동기화 블럭 피하십시오 - 이건 쓸모가 없습니다.
- XPath 표현식
//SynchronizedStatement/Block[1][count(*) = 0]
- 예제
public class Foo {
public void bar() {
synchronized (this) {
// empty!
}
}
}
불필요한 반환 (UnnecessaryReturn)
- 도입
- PMD 1.3
불필요한 반환문을 피하십시오.
이 규칙은 다음 자바 클래스에 정의되어 있다: net.sourceforge.pmd.rules.basic.UnnecessaryReturn
- 예제
public class Foo {
public void bar() {
int x = 42;
return;
}
}
빈 정적 초기화 블럭 (EmptyStaticInitializer)
http://pmd.sourceforge.net/rules/basic.html#EmptyStaticInitializer
- 도입
- PMD 1.5
An empty static initializer was found.
빈 정적 초기화 블럭을 찾습니다.
- XPath 표현식
//Initializer[@Static='true']/Block[count(*)=0]
- 예제
public class Foo {
static {
// empty
}
}
조건없는 If 구문 (UnconditionalIfStatement)
http://pmd.sourceforge.net/rules/basic.html#UnconditionalIfStatement
- 도입
- PMD 1.5
Do not use "if" statements that are always true or always false.
항상 참이거나 거짓인 "if" 구문을 쓰지 마십시오.
- XPath 표현식
//IfStatement/Expression [count(PrimaryExpression)=1] /PrimaryExpression/PrimaryPrefix/Literal/BooleanLiteral
- 예제
public class Foo {
public void close() {
if (true) {
// ...
}
}
}
반복문 밖의 빈 구문 (EmptyStatementNotInLoop)
http://pmd.sourceforge.net/rules/basic.html#EmptyStatementNotInLoop
- 도입
- PMD 1.5
for 반복문이나 while 반복문의 유일한 본문으로 사용되지 않은 (세미콜론 그 자체로도 알려진) 빈 구문은 아마도 버그일 것입니다. 혹은 삭제해야만 하는 연속된 세미콜론 쌍일 수도 있습니다.
- XPath 표현식
//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)
]
- 예제
public class MyClass {
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");;
}
}
논리값 객체 생성 (BooleanInstantiation)
http://pmd.sourceforge.net/rules/basic.html#BooleanInstantiation
- 도입
- PMD 1.2
논리값(Boolean) 객체의 생성을 피하십시오; 대신 Boolean.TRUE, Boolean.FALSE를 사용하거나 Boolean.valueOf() 메서드를 사용하십시오.
이 규칙은 다음 자바 클래스에 정의되어 있습니다: net.sourceforge.pmd.rules.basic.BooleanInstantiation
- 예제
public class Foo {
Boolean bar = new Boolean("true"); // just do a Boolean bar = Boolean.TRUE;
Boolean buz = Boolean.valueOf(false); // just do a Boolean buz = Boolean.FALSE;
}
불필요한 Final 수정자 (UnnecessaryFinalModifier)
http://pmd.sourceforge.net/rules/basic.html#UnnecessaryFinalModifier
- 도입
- PMD 3.0
클래스가 final 수정자를 가지면 모든 메서드는 자동으로 final이 됩니다.
- XPath 표현식
//ClassOrInterfaceDeclaration[@Final='true' and @Interface='false'] /ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/MethodDeclaration[@Final='true']
- 예제
public final class Foo {
// This final modifier is not necessary, since the class is final
// and thus, all methods are final
private final void foo() {
}
}
합칠 수 있는 If 문 (CollapsibleIfStatements)
http://pmd.sourceforge.net/rules/basic.html#CollapsibleIfStatements
- 도입
- PMD 1.02
때론 두 if문은 각 조건을 논리적 최소 평가(short-circuit evaluation)로 나눔으로써 합칠 수 있습니다.
- XPath 표현식
//IfStatement[@Else='false']/Statement /IfStatement[@Else='false'] | //IfStatement[@Else='false']/Statement /Block[count(BlockStatement)=1]/BlockStatement /Statement/IfStatement[@Else='false']
- 예제
public class Foo {
void bar() {
if (x) {
if (y) {
// do stuff
}
}
}
}
쓸모없는 메서드 재정의 (UselessOverridingMethod)
http://pmd.sourceforge.net/rules/basic.html#UselessOverridingMethod
- 도입
- PMD 3.3
재정의한 메서드가 단지 부모클래스의 동일한 메서드를 호출할 뿐입니다.
이 규칙은 다음 자바 클래스에 정의되어 있습니다: net.sourceforge.pmd.rules.UselessOverridingMethod
- 예제
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
}
- 속성
| 이름 | 기본값 | 설명 |
|---|---|---|
| ignoreAnnotations | false | 애노테이션을 무시한다. |
ToArray에서 클래스 변환 예외 (ClassCastExceptionWithToArray)
http://pmd.sourceforge.net/rules/basic.html#ClassCastExceptionWithToArray
- 도입
- PMD 3.4
컬렉션(Collection)에서 특정 클래스의 배열을 뽑아내기 위해선, toArray() 메서드에 원하는 클래스의 배열을 매개 변수에 전달해야 한다. 그렇지 않으면 ClassCaseException이 발생한다.
- XPath 표현식
//CastExpression[Type/ReferenceType/ClassOrInterfaceType[@Image != "Object"]]//PrimaryExpression [ PrimaryPrefix/Name[ends-with(@Image, '.toArray')] and PrimarySuffix/Arguments[count(*) = 0] and count(PrimarySuffix) = 1 ]
- 예제
import java.util.ArrayList;
import java.util.Collection;
public class Test {
public static void main(String[] args) {
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 wouldn't trigger the rule
Integer[] b=(Integer [])c.toArray(new Integer[c.size()]);
}
}
AvoidDecimalLiteralsInBigDecimalConstructor
http://pmd.sourceforge.net/rules/basic.html#AvoidDecimalLiteralsInBigDecimalConstructor
- 도입
- PMD 3.4
누군가 "new BigDecimal(.1)"이 .1과 정확히 같을 거라고 예상할 지도 모르겠지만, 사실 이 값은 .1000000000000000055511151231257827021181583404541015625과 같습니다. 왜냐하면 .1은 double형은 (혹은 크기가 제한된 그 어떤 이진 분수라면 그 어떤 것도) .1을 정확히 표현할 수 없기 때문입니다. 따라서 생성자에 전달된 긴 값은 그 형태가 보여주는 것과는 달리 정확히 .1이 아닙니다. 반면에 (String) 생성자는 정확하게 예측할 수 있습니다. 'new BigDecimal(".1")'는 여러분이 예측하는 것처럼 정확히 .1과 같습니다. 그러므로 이런 경우에 (String) 생성자를 사용하는 것을 권장합니다.
- XPath 표현식
//AllocationExpression[ClassOrInterfaceType[@Image="BigDecimal"] and ./Arguments/ArgumentList /Expression/PrimaryExpression/PrimaryPrefix/Literal[(not (ends-with (@Image,'"'))) and contains(@Image,".")]]
- 예제
import java.math.BigDecimal;
public class Test {
public static void main(String[] args) {
// this would trigger the rule
BigDecimal bd=new BigDecimal(1.123);
// this wouldn't trigger the rule
BigDecimal bd=new BigDecimal("1.123");
// this wouldn't trigger the rule
BigDecimal bd=new BigDecimal(12);
}
}
불변객체에 대한 불필요한 연산 (UselessOperationOnImmutable)
http://pmd.sourceforge.net/rules/basic.html#UselessOperationOnImmutable
- 도입
- PMD 3.5
불변객체(String, BigDecimal or BigInteger)에 대한 연산은 그 객체 자체를 변경시키지 않습니다. 그 연산 결과는 새 객체이며, 따라서 그 값을 버리는 것은 오류입니다.
이 규칙은 다음 자바 클래스에 정의되어 있습니다: net.sourceforge.pmd.rules.UselessOperationOnImmutable
- 예제
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
}
}
잘못 위치한 널 검사 (MisplacedNullCheck)
http://pmd.sourceforge.net/rules/basic.html#MisplacedNullCheck
- 도입
- PMD 3.5
여기서는 잘못 위치한 널 검사를 찾습니다. 어떤 값이 널이라면, 여러분은 NullPointerException를 만날 것입니다. 그 검사는 무용지물이거나 (그 값은 절대 "널"이 될 수 없는 경우), 아니면 잘못된 것입니다.
- XPath 표현식
//Expression
/*[self::ConditionalOrExpression or self::ConditionalAndExpression]
/descendant::PrimaryExpression/PrimaryPrefix
/Name[starts-with(@Image,
concat(ancestor::PrimaryExpression/following-sibling::EqualityExpression
[./PrimaryExpression/PrimaryPrefix/Literal/NullLiteral]
/PrimaryExpression/PrimaryPrefix
/Name[count(../../PrimarySuffix)=0]/@Image,"."))
]
- 예제
public class Foo {
void bar() {
if (a.equals(baz) && a != null) {}
}
}
- 예제
public class Foo {
void bar() {
if (a.equals(baz) || a == null) {}
}
}
Equals 내에서 사용되지 않는 널 검사 (UnusedNullCheckInEquals)
http://pmd.sourceforge.net/rules/basic.html#UnusedNullCheckInEquals
- 도입
- PMD 3.5
객체 참조자의 널 여부를 검사한 다음에는 다른 객체의 equals()의 인자로 넘기기보단 널 여부를 검사한 객체의 equals() 메서드를 호출하는 게 낫습니다.
- XPath 표현식
//PrimarySuffix[@Image='equals' and not(../PrimaryPrefix/Literal)] /following-sibling::PrimarySuffix/Arguments/ArgumentList/Expression /PrimaryExpression[count(PrimarySuffix)=0]/PrimaryPrefix /Name[@Image = ./../../../../../../../../../../Expression/ConditionalAndExpression /EqualityExpression[@Image="!=" and count(./preceding-sibling::*)=0 and ./PrimaryExpression/PrimaryPrefix/Literal/NullLiteral] /PrimaryExpression/PrimaryPrefix/Name/@Image]
- 예제
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
}
}
}
}
ThreadGroup 지양 (AvoidThreadGroup)
http://pmd.sourceforge.net/rules/basic.html#AvoidThreadGroup
- 도입
- PMD 3.6
java.lang.ThreadGroup을 피하십시오. 이 클래스는 쓰레드 환경에서 사용하도록 의도되었음에도 불구하고 쓰레드에 안전하지 않은 메서드를 포함하고 있습니다.
- XPath 표현식
//AllocationExpression/ClassOrInterfaceType[typeof(@Image, 'java.lang.ThreadGroup')]| //PrimarySuffix[contains(@Image, 'getThreadGroup')]
- 예제
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();
}
}
깨진 널 검사 (BrokenNullCheck)
http://pmd.sourceforge.net/rules/basic.html#BrokenNullCheck
- 도입
- PMD 3.8
NullPointerException을 던지수 도 있는 널 검사는 잘못된 경우입니다. 이는 ||이 && 대신에 잘못 쓰이거나, 그 반대의 경우에 일어납니다.
이 규칙은 다음 자바 클래스에 정의되어 있습니다: net.sourceforge.pmd.rules.BrokenNullCheck
- 예제
class Foo {
String bar(String string) {
// should be &&
if (string!=null || !string.equals(""))
return string;
// should be ||
if (string==null && string.equals(""))
return string;
}
}
BigInteger의 인스턴스 생성 (BigIntegerInstantiation)
http://pmd.sourceforge.net/rules/basic.html#BigIntegerInstantiation
- 도입
- PMD 3.9
이미 존재하는 BigInteger의 인스턴스(BigInteger.ZERO, BigInteger.ONE), Java 1.5 이상에서는 BigInteger.TEN과 BigDecimal의 인스턴스(BigDecimal.ZERO, BigDecimal.ONE, BigDecimal.TEN)를 새로 만들지 마십시오.
이 규칙은 다음 자바 클래스에 정의되어 있습니다: net.sourceforge.pmd.rules.BigIntegerInstantiation
- 예제
public class Test {
public static void main(String[] args) {
BigInteger bi=new BigInteger(1);
BigInteger bi2=new BigInteger("0");
BigInteger bi3=new BigInteger(0.0);
BigInteger bi4;
bi4=new BigInteger(0);
}
}
8진수 사용 지양 (AvoidUsingOctalValues)
http://pmd.sourceforge.net/rules/basic.html#AvoidUsingOctalValues
- 도입
- PMD 3.9
정수 리터럴은 0으로 시작하면 안 됩니다. 0은 리터럴의 나머지 부분이 8진수로 해석될 것임을 의미합니다.
이 규칙은 다음 자바 클래스에 정의되어 있습니다: net.sourceforge.pmd.rules.AvoidUsingOctalValues
- 예제
public class Foo {
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
}
AvoidUsingHardCodedIP
http://pmd.sourceforge.net/rules/basic.html#AvoidUsingHardCodedIP
- 도입
- PMD 4.1
하드 코딩된 IP를 포함한 애플리케이션은 때때로 배포가 불가능할 수 있습니다. IP 주소를 외부로 빼내는 것은 아무런 문제가 없습니다.
이 규칙은 다음 자바 클래스에 정의되어 있습니다: net.sourceforge.pmd.rules.AvoidUsingHardCodedIP
- 예제
public class Foo {
String ip = "127.0.0.1"; // This is a really bad idea !
}
- 속성
| 이름 | 기본값 | 설명 |
|---|---|---|
| pattern | ^"[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"$ | 정규표현식 |
ResultSet 검사 (CheckResultSet)
http://pmd.sourceforge.net/rules/basic.html#CheckResultSet
- 도입
- PMD 4.1
ResultSet의 위치 이동 메서드(next, previous, first, last)의 반환 값을 항상 검사하십시오. 개발자는 반환값을 확실히 검사해야만 합니다!
- XPath 표현식
//Type/ReferenceType/ClassOrInterfaceType[
(@Image = 'ResultSet')
and
(../../../descendant::Name[ends-with(@Image,'executeQuery')])
and
(
(not (contains(
(./ancestor::Block/descendant::WhileStatement/descendant::Name/attribute::Image),
concat(../../../VariableDeclarator/VariableDeclaratorId/attribute::Image,'.next')
) ) )
and ( not ( contains(
(./ancestor::Block/descendant::IfStatement/descendant::Name/attribute::Image),
concat(../../../VariableDeclarator/VariableDeclaratorId/attribute::Image,'.next')
) ) )
and (not (contains(
(./ancestor::Block/descendant::WhileStatement/descendant::Name/attribute::Image),
concat(../../../VariableDeclarator/VariableDeclaratorId/attribute::Image,'.previous')
) ) )
and ( not ( contains(
(./ancestor::Block/descendant::IfStatement/descendant::Name/attribute::Image),
concat(../../../VariableDeclarator/VariableDeclaratorId/attribute::Image,'.previous')
) ) )
and ( not ( contains(
(./ancestor::Block/descendant::IfStatement/descendant::Name/attribute::Image),
concat(../../../VariableDeclarator/VariableDeclaratorId/attribute::Image,'.last')
) ) )
and ( not ( contains(
(./ancestor::Block/descendant::IfStatement/descendant::Name/attribute::Image),
concat(../../../VariableDeclarator/VariableDeclaratorId/attribute::Image,'.first')
) ) )
)
]
- 예제
// This is NOT appropriate !
Statement stat = conn.createStatement();
ResultSet rst = stat.executeQuery("SELECT name FROM person");
rst.next(); // what if it returns a 'false' ?
String firstName = rst.getString(1);
// This is appropriate...
Statement stat = conn.createStatement();
ResultSet rst = stat.executeQuery("SELECT name FROM person");
if (rst.next())
{
String firstName = rst.getString(1);
}
else
{
// here you deal with the error ( at least log it)
}
여러 단항연산자 지양 (AvoidMultipleUnaryOperators)
http://pmd.sourceforge.net/rules/basic.html#AvoidMultipleUnaryOperators
- 도입
- PMD 4.2
여러 단항연산자를 사용하면 버그를 만들기 쉽고 헷갈립니다. 이런 사용법이 버그가 아닌지 확인하고 표현식을 단순화할 것을 고려해 보십시오.
- XPath 표현식
//UnaryExpression[ ./UnaryExpression or ./UnaryExpressionNotPlusMinus or ./PrimaryExpression/PrimaryPrefix/Expression/UnaryExpression or ./PrimaryExpression/PrimaryPrefix/Expression/UnaryExpressionNotPlusMinus ] | //UnaryExpressionNotPlusMinus[ ./UnaryExpression or ./UnaryExpressionNotPlusMinus or ./PrimaryExpression/PrimaryPrefix/Expression/UnaryExpression or ./PrimaryExpression/PrimaryPrefix/Expression/UnaryExpressionNotPlusMinus ]
- 예제
// 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;
빈 초기화 (EmptyInitializer)
http://pmd.sourceforge.net/rules/basic.html#EmptyInitializer
- 도입
- PMD 5.0
빈 초기화가 발견된 경우입니다.
- XPath 표현식
//Initializer/Block[count(*)=0]
- 예제
public class Foo {
static {} // Why ?
{} // Again, why ?
}
Thread.run()의 호출금지 (DontCallThreadRun)
http://pmd.sourceforge.net/rules/basic.html#DontCallThreadRun
- 도입
- PMD 4.3
Thread.run() 메서드의 직접 실행은 호출한 컨트롤이 있는 쓰레드에서 이뤄집니다. 이보다는 의도한 동작을 위해서 Thread.start()를 호출하십시오.
- XPath 표현식
//StatementExpression/PrimaryExpression
[
PrimaryPrefix
[
./Name[ends-with(@Image, '.run') or @Image = 'run']
and substring-before(Name/@Image, '.') =//VariableDeclarator/VariableDeclaratorId/@Image
[../../../Type/ReferenceType[ClassOrInterfaceType/@Image = 'Thread']]
or (
./AllocationExpression/ClassOrInterfaceType[@Image = 'Thread']
and ../PrimarySuffix[@Image = 'run'])
]
]
- 예제
Thread t = new Thread(); t.run(); // use t.start() instead new Thread().run(); // same violation

