Checkstyle에서 제공되는 모듈 내용을 정리한다.
Link
- File Filters
- Annotations
- Block Checks
- Class Design
- Coding
- DefaultComesLast
- EmptyStatement
- EqualsHashCode
- FallThrough
- IllegalTokenText
- MissingSwitchDefault
- MultipleVariableDeclarations
- NoFinalizer
- OneStatementPerLine
- OverloadMethodsDeclarationOrder
- SimplifyBooleanExpression
- SimplifyBooleanReturn
- StringLiteralEquality
- SuperClone
- VariableDeclarationUsageDistance
- Imports
- Javadoc Comments
- Miscellaneous
- Modifier
- Naming Conventions
- Regexp
- Size Violations
- Whitespace
checkstyle 검사를 제외할 파일 패턴 설정.
<module name="BeforeExecutionExclusionFileFilter">
<property name="fileNamePattern" value="module\-info\.java$"/>
</module>
annotation의 위치를 검사.
<module name="AnnotationLocation">
<property name="id" value="AnnotationLocationMostCases"/>
<property name="tokens"
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF"/>
</module>
<module name="AnnotationLocation">
<property name="id" value="AnnotationLocationVariables"/>
<property name="tokens" value="VARIABLE_DEF"/>
<property name="allowSamelineMultipleAnnotations" value="true"/>
</module>
VIOLATION
@Override @Nullable
public String foo() {
return "bar";
}
@SuppressWarnings("deprecation") public String foo() {
return "bar";
}
OK
@Override
@Nullable
public String foo() {
return "bar";
}
@SuppressWarnings("deprecation")
public String foo() {
return "bar";
}
// allow one single parameterless annotation on the same line
@Override public String foo() {
return "bar";
}
@SuppressWarnings("deprecation") @Mock DataLoader loader;
@inheritDoc이 부여된 메소드가 override 됐는지를 검사.
<module name="MissingOverride"/>
VIOLATION
/*
* {@inheritDoc}
*/
public void foo() {
}
OK
/*
* {@inheritDoc}
*/
@Override
public void foo() {
}
nested block이 존재하는지 검사.
<module name="AvoidNestedBlocks"/>
VIOLATION
int foo = 0;
{
foo = 3;
}
OK
int foo = 0;
foo = 3;
empty block이 존재하는지 검사.
<module name="EmptyBlock">
<property name="option" value="TEXT"/>
<property name="tokens"
value="LITERAL_TRY, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, LITERAL_SWITCH"/>
</module>
VIOLATION
if (foo == bar) {
} else {
System.out.println("not equal");
}
OK
if (foo != bar) {
System.out.println("not equal");
}
비어있는 catch block을 검사.
<module name="EmptyCatchBlock">
<property name="exceptionVariableName" value="expected"/>
</module>
VIOLATION
try {
throw new RuntimeException();
} catch (RuntimeException e) {
}
OK
try {
throw new RuntimeException();
} catch (RuntimeException expected) {
}
try {
throw new RuntimeException();
} catch (RuntimeException e) {
e.printStackTrace();
}
LeftCurly('{')의 줄바꿈을 검사.
<module name="LeftCurly">
<property name="tokens"
value="ANNOTATION_DEF, CLASS_DEF, CTOR_DEF, ENUM_CONSTANT_DEF, ENUM_DEF,
INTERFACE_DEF, LAMBDA, LITERAL_CASE, LITERAL_CATCH, LITERAL_DEFAULT,
LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY, LITERAL_FOR, LITERAL_IF,
LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_WHILE, METHOD_DEF,
OBJBLOCK, STATIC_INIT"/>
</module>
VIOLATION
if (foo == bar)
{
System.out.println("equal");
}
else
{
System.out.println("not equal");
}
OK
if (foo == bar) {
System.out.println("equal");
} else {
System.out.println("not equal");
}
brace('{', '}')가 존재하는지 검사.
<module name="NeedBraces">
<property name="tokens"
value="LITERAL_DO, LITERAL_ELSE, LITERAL_FOR, LITERAL_IF, LITERAL_WHILE"/>
</module>
VIOLATION
if (foo == bar)
System.out.println("equal");
else
System.out.println("not equal");
OK
if (foo == bar) {
System.out.println("equal");
} else {
System.out.println("not equal");
}
RightCurly('}')의 줄바꿈을 검사.
<module name="RightCurly">
<property name="id" value="RightCurlySame"/>
<property name="tokens"
value="LITERAL_TRY, LITERAL_CATCH, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE,
LITERAL_DO"/>
</module>
VIOLATION
if (foo == bar) {
System.out.println("equal"); }
else {
System.out.println("not equal"); }
OK
if (foo == bar) {
System.out.println("equal");
} else {
System.out.println("not equal");
}
private 생성자를 가진 클래스의 modifier가 final인지를 검사.
<module name="FinalClass"/>
VIOLATION
class Foo {
private Foo() {
}
}
OK
final class Foo {
private Foo() {
}
}
static 메소드만 가지는 util 클래스의 생성자가 private인지를 검사.
<module name="HideUtilityClassConstructor"/>
VIOLATION
class Util {
public static void add(int a, int b) { }
public static void div(int a, int b) { }
}
OK
class Util {
private Util() {
}
public static void add(int a, int b) { }
public static void div(int a, int b) { }
}
interface가 type으로 쓰이는지를 검사.
<module name="InterfaceIsType"/>
VIOLATION
interface Foo {
int BAR = 100;
}
OK
class Foo {
private Foo() {
}
public static final int BAR = 100;
}
하나의 파일에 두개 이상의 클래스를 정의했는지를 검사.
<module name="OneTopLevelClass"/>
VIOLATION
// Parent.java
class Parent {
}
class Child {
}
OK
// Parent.java
class Parent {
}
// Child.java
class Child {
}
클래스 멤버의 modifier가 private, protected 인지를 검사.
<module name="VisibilityModifier">
<property name="protectedAllowed" value="true"/>
</module>
VIOLATION
int foo;
int bar;
public final int baz;
public int qux;
OK
private int foo;
protected int bar;
private final int int baz
protected int qux
switch에서 default 뒤에 case가 존재하는지 검사.
<module name="DefaultComesLast"/>
VIOLATION
switch (foo) {
case 1:
break;
default:
case 2:
break;
}
OK
switch (foo) {
case 1:
break;
case 2:
default:
break;
}
<module name="EmptyStatement"/>
VIOLATION
if (foo == bar);
System.out.println("baz"); // always print baz
OK
if (foo == bar) {
System.out.println("baz");
}
equals 메소드를 override하면 hashcode 메소드도 override 했는지 검사.
<module name="EqualsHashCode"/>
VIOLATION
class Foo {
@Override
public boolean equals(Object obj) {
return ...
}
}
OK
class Foo {
@Override
public boolean equals(Object obj) {
return ...
}
@Override
public int hashCode() {
return ...
}
}
switch-case에 fall through를 하는 곳에 "falls?[ -]?thr(u|ough)"
패턴의 주석이 존재하는지 검사.
<module name="FallThrough">
<property name="reliefPattern" value="falls?[ -]?thr(u|ough)"/>
</module>
VIOLATION
int i = 0;
switch (i) {
case 0:
i++;
case 1:
i++;
case 2:
case 3: {
i++;
}
default:
break;
}
OK
int i = 0;
switch (i) {
case 0:
i++;
// fall through
case 1:
i++;
// fall through
case 2:
case 3: {
i++;
}
// fall through
default:
break;
}
escape sequence를 8진수, 유니코드로 표현했는지를 검사.
<module name="IllegalTokenText">
<property name="tokens" value="STRING_LITERAL, CHAR_LITERAL"/>
<property name="format"
value="\\u00(09|0(a|A)|0(c|C)|0(d|D)|22|27|5(C|c))|\\(0(10|11|12|14|15|42|47)| 134)"/>
<property name="message"
value="Consider using special escape sequence instead of octal value or Unicode escaped value."/>
</module>
VIOLATION
char tab = '\u0009';
char octalTab = '\011';
OK
char escapedSequenceTab = '\t';
switch에서 default가 존재하는지 검사.
<module name="MissingSwitchDefault"/>
VIOLATION
switch (i) {
case 1:
break;
case 2:
break;
}
OK
switch (i) {
case 1:
break;
case 2:
break;
default:
break;
}
변수를 comma(',')를 사용하여 정의하였는지 검사.
<module name="MultipleVariableDeclarations"/>
VIOLATION
int foo, bar, fooarray[];
OK
int foo;
int bar;
int[] fooarray;
finalize 메소드를 override 했는지 검사.
<module name="NoFinalizer"/>
VIOLATION
class Foo {
@Override
protected void finalize() throws Throwable {
super.finalize();
}
}
OK
class Foo {
}
한 라인에 다수의 statement가 존재하는지 검사.
<module name="OneStatementPerLine"/>
VIOLATION
int var = 1, var2 = 2;
foo++; bar++;
OK
int var = 1
int var2 = 2;
var1++;
var2++;
오버로드 메소드의 순서를 검사.
<module name="OverloadMethodsDeclarationOrder"/>
VIOLATION
public void foo(int i) { }
public void foo(String s) { }
public void bar() { }
public void foo(int i, String s) { }
OK
public void foo(int i) { }
public void foo(String s) { }
public void foo(int i, String s) { }
public void bar() { }
<module name="SimplifyBooleanExpression"/>
VIOLATION
if (foo == false) { }
OK
if (!foo) { }
<module name="SimplifyBooleanReturn"/>
VIOLATION
if (foo()) {
return true;
} else {
return false;
}
OK
return foo();
<module name="StringLiteralEquality"/>
VIOLATION
if (foo == "bar") {
}
OK
if (foo.equals("bar")) {
}
부모의 clone() 호출을 검사.
<module name="SuperClone"/>
VIOLATION
@Override
public Object clone throws CloneNotSupportedException {
return ...
}
OK
@Override
public Object clone throws CloneNotSUpportedException {
super.clone();
return ...
}
변수 정의와 변수 사용 사이의 거리가 3을 초과하지 않았는지를 검사.
<module name="VariableDeclarationUsageDistance">
<property name="allowedDistance" value="3"/>
</module>
VIOLATION
int foo = 0;
int bar = 0;
int baz;
foo = foo + bar; // foo distance is 3 : OK
bar = foo + foo; // bar distance is 3 : OK
int qux;
baz = bar; // baz distance is 4 : VIOLATION
OK
int foo = 0;
int bar = 0;
int baz;
foo = foo + bar; // foo distance is 3 : OK
bar = foo + foo; // bar distance is 3 : OK
baz = bar; // baz distance is 3 : OK
star('*') import가 존재하는지 검사.
<module name="AvoidStarImport"/>
VIOLATION
import foo.bar.*;
OK
import foo.bar.Baz;
import 순서를 검사.
<module name="CustomImportOrder">
<property name="sortImportsInGroupAlphabetically" value="true"/>
<property name="separateLineBetweenGroups" value="true"/>
<property name="customImportOrderRules" value="STATIC###THIRD_PARTY_PACKAGE"/>
<property name="tokens" value="IMPORT, STATIC_IMPORT, PACKAGE_DEF"/>
</module>
VIOLATION
import java.util.Map;
import java.util.List;
import java.util.ArrayList;
OK
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
sun 패키지의 import가 존재하는지 검사.
<module name="IllegalImport"/>
VIOLATION
import sun.management.counter.StringCounter;
java.lang, 중복, 현재 패키지의 import를 검사.
<module name="RedundantImport"/>
VIOLATION
package foo;
import java.lang.String; // java.lang
import java.lang.String; // duplicate
import foo.Bar; // same package
사용되지 않는 import를 검사.
<module name="UnusedImports"/>
VIOLATION
import java.util.ArrayList;
public class Foo {
public static void main() {
System.out.println("foo");
}
}
OK
public class Foo {
public static void main() {
System.out.println("foo");
}
}
tag 순서를 검사.
- @param
- @return
- @throws
- @deprecated
<module name="AtclauseOrder">
<property name="tagOrder" value="@param, @return, @throws, @deprecated"/>
<property name="target"
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/>
</module>
VIOLATION
/**
* @return bar string
* @param foo foo integer
* @param bar bar integer
*/
public String foo(int foo, int bar) {
return "bar";
}
OK
/**
* @param foo foo integer
* @param bar bar integer
* @return bar string
*/
public String foo(int foo, int bar) {
return "bar";
}
public 메소드에서 @param, @return tag 생략이 가능하도록 함.
<module name="JavadocMethod">
<property name="scope" value="public"/>
<property name="allowMissingParamTags" value="true"/>
<property name="allowMissingReturnTag" value="true"/>
<property name="allowedAnnotations" value="Override, Test"/>
<property name="tokens" value="METHOD_DEF, CTOR_DEF, ANNOTATION_FIELD_DEF"/>
</module>
OK
// allow missing @param, @return tag */
/**
* This is foo method.
*/
public String foo(int foo, int bar) {
return "bar";
}
부적절한 javadoc의 위치를 검사.
<module name="InvalidJavadocPosition"/>
VIOLATION
@SuppressWarnings("foo")
/**
* This comment looks like javadoc but it at an invalid location.
* Therefore, the text will not get into Foo.html and the check will produce a violation.
*/
public class Foo {
}
OK
/**
* This comment looks like javadoc but it at an invalid location.
* Therefore, the text will not get into Foo.html and the check will produce a violation.
*/
@SuppressWarnings("foo")
public class Foo {
}
paragraph(<p>
) 태그를 검사.
<module name="JavadocParagraph"/>
VIOLATION
/**
* No tag
*
* <p>Tag immediately before the text.
* <p>No blank line before the tag.
*
* <p>
* New line after tag.
*
* <p> Whitespace after tag.
*/
public class TestClass {
}
OK
/**
* No tag
*
* <p>Tag immediately before the text.
*
* <p>No blank line before the tag.
*
* <p>New line after tag.
*
* <p>Whitespace after tag.
*/
적절하지 않거나 존재하지 않는 HTML 태그 사용 및 첫 문장에 마침표를 사용했는지 검사.
<module name="JavadocStyle"/>
VIOLATION
/**
* This is Foo class
* <foo>This is Foo class</foo>
*/
class Foo {
}
OK
/**
* This is Foo class.
* <h1>This is Foo class</h1>
*/
class Foo {
}
indentation (4 spaces) 검사.
<module name="JavadocTagContinuationIndentation"/>
VIOLATION
/**
* @param foo
* foo integer
* @param bar
* bar integer
* @return bar string
*/
public String foo(int foo, int bar) {
return "bar";
}
OK
/**
* @param foo
* foo integer
* @param bar
* bar integer
* @return bar string
*/
public type(annotation/enum/class/interface)에서 @param 생략이 가능하도록 함
<module name="JavadocType">
<property name="scope" value="public"/>
<property name="allowMissingParamTags" value="true"/>
</module>
OK
// allow missing @param tag */
/**
* This is Foo class
*/
public class Foo<T> {
...
}
2라인을 넘어가는 메소드의 javadoc이 존재하는지 검사.
<module name="MissingJavadocMethod">
<property name="scope" value="public"/>
<property name="minLineCount" value="2"/>
<property name="allowedAnnotations" value="Override, Test"/>
<property name="tokens" value="METHOD_DEF, CTOR_DEF, ANNOTATION_FIELD_DEF"/>
</module>
VIOLATION
public String foo(int foo, int bar) { // minLineCount is > 2
System.out.println("foo");
System.out.println("bar");
return "bar";
}
OK
/**
* This is foo method.
*/
public String foo(int foo, int bar) {
System.out.println("foo");
System.out.println("bar");
return "bar";
}
public String foo(int foo, int bar) { // minLineCount is <= 2
System.out.println("foo");
return "bar";
}
@Override
public String foo(int foo, int bar) { // @Override, @Test is allowed
System.out.println("foo");
System.out.println("bar");
return "bar";
}
@param, @return, @throws, @deprecated의 설명이 존재하는지 검사.
<module name="NonEmptyAtclauseDescription"/>
VIOLATION
/**
* @param foo
* @param bar
* @return bar string
*/
public String foo(int foo, int bar) {
return "bar";
}
OK
/**
* @param foo foo integer
* @param bar bar integer
* @return bar string
*/
public String foo(int foo, int bar) {
return "bar";
}
단일 라인의 inline 태그가 존재하는지 검사.
<module name="SingleLineJavadoc">
<property name="ignoreInlineTags" value="false"/>
</module>
VIOLATION
/** Single line Javadoc that references {@link String}. */
public void foo() { // not allowed inline tag. only allowed multi-line
}
OK
/**
* Single line Javadoc that references {@link String}.
*/
public void foo() {
}
/** Single line Javadoc. */
public void foo() {
}
summary 첫 문장이 마침표로 끝나는지 검사.
<module name="SummaryJavadoc">
<property name="forbiddenSummaryFragments"
value="^@return the *|^This method returns |^A [{]@code [a-zA-Z0-9]+[}]( is a )"/>
</module>
VIOLATION
/**
* This is foo method
*/
public String foo(int foo, int bar) {
return "bar";
}
/**
*
*/
public String baz() {
return "qux";
}
OK
/**
* This is foo method.
*/
public String foo(int foo, int bar) {
return "bar";
}
배열 타입 스타일을 검사.
<module name="ArrayTypeStyle"/>
VIOLATION
String foo[];
OK
String[] foo;
유니코드를 사용했는지 검사.
<module name="AvoidEscapedUnicodeCharacters">
<property name="allowEscapesForControlCharacters" value="true"/>
<property name="allowByTailComment" value="true"/>
<property name="allowNonPrintableEscapes" value="true"/>
</module>
VIOLATION
String foo = "\u00B5"; // micro sign
OK
String foo = "μs"; // micro sign
// allowEscapesForControlCharacters
String bar = "\u200E";
// allow by allowByTailComment
String baz = "\u03BCS"; // the reader has no idea what this is.
// allow by allowNonPrintableEscapes */
String qux = "\u0020";
주석의 indentation을 검사.
<module name="CommentsIndentation">
<property name="tokens" value="SINGLE_LINE_COMMENT, BLOCK_COMMENT_BEGIN"/>
</module>
VIOLATION
/*
foo is true
*/
boolean foo = true;
// bar is true
boolean bar = true;
OK
/*
foo is true
*/
boolean foo = true;
// bar is true
boolean bar = true;
<module name="Indentation">
<property name="basicOffset" value="2"/>
<property name="braceAdjustment" value="0"/>
<property name="caseIndent" value="2"/>
<property name="throwsIndent" value="4"/>
<property name="lineWrappingIndentation" value="4"/>
<property name="arrayInitIndent" value="2"/>
</module>
VIOLATION
/* <property name="basicOffset" value="2"/> */
class Foo {
void bar() {
}
}
/* <property name="braceAdjustment" value="0"/> */
void bar() {
}
/* <property name="caseIndent" value="2"/> */
switch (foo) {
case 0:
break;
case 1:
break;
default:
break;
}
/* <property name="throwsIndent" value="4"/> */
public static void main(String[] args) throws
IOException {
}
/* <property name="lineWrappingIndentation" value="4"/> */
if ((foo == bar)
&& (baz == qux)) {
System.out.println("equal");
}
/* <property name="arrayInitIndent" value="2"/> */
int[] foo = {
5,
6
};
OK
/* <property name="basicOffset" value="2"/> */
class Foo {
void bar() {
}
}
/* <property name="braceAdjustment" value="0"/> */
void bar() {
}
/* <property name="caseIndent" value="2"/> */
switch (foo) {
case 0:
break;
case 1:
break;
default:
break;
}
/* <property name="throwsIndent" value="4"/> */
public static void main(String[] args) throws
IOException {
}
/* <property name="lineWrappingIndentation" value="4"/> */
if ((foo == bar)
&& (baz == qux)) {
System.out.println("equal");
}
/* <property name="arrayInitIndent" value="2"/> */
int[] foo = {
5,
6
};
파일의 맨 끝에 newline('\n')이 존재하는지 검사.
<module name="NewlineAtEndOfFile"/>
VIOLATION
1 class Foo {
2
3 }
OK
1 class Foo {
2
3 }
4
파일 이름과 클래스명이 일치하는지 검사.
<module name="OuterTypeFilename"/>
VIOLATION
// Foo.java
class Bar {
}
OK
// Foo.java
class Foo {
}
long을 'l'이 아닌 'L'로 표현하는지를 검사.
<module name="UpperEll"/>
VIOLATION
long value = 100l // 1001?
OK
long value = 100L
modifier 순서를 검사.
- public
- protected
- private
- abstract
- default
- static
- final
- transient
- volatile
- synchronized
- native
- strictfp
<module name="ModifierOrder"/>
VIOLATION
abstract public void foo();
OK
public abstract void foo();
불필요한 modifier를 검사.
<module name="RedundantModifier"/>
VIOLATION
public interface Foo {
public void bar();
}
OK
public interface Foo {
void bar();
}
약어를 대문자로 표현했는지 검사.
<module name="AbbreviationAsWordInName">
<property name="ignoreFinal" value="false"/>
<property name="allowedAbbreviationLength" value="1"/>
<property name="tokens"
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, ANNOTATION_DEF, ANNOTATION_FIELD_DEF,
PARAMETER_DEF, VARIABLE_DEF, METHOD_DEF"/>
</module>
VIOLATION
int firstFOO;
int secondFOo;
OK
int firstFoo;
int secondFoo;
String firstXML; // abbreviation is allowed
String firstURL; // abbreviation is allowed
catch 파라미터의 이름을 검사. "^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"
패턴과 일치해야 한다.
<module name="CatchParameterName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Catch parameter name ''{0}'' must match pattern ''{1}''."/>
</module>
VIOLATION
try {
} catch (ArithmeticException Foo) {
} catch (ArrayIndexOutOfBoundsException BAR2) {
}
OK
try {
} catch (ArithmeticException foo) {
} catch (ArrayIndexOutOfBoundsException bar2) {
}
클래스 제네릭 타입을 검사. "(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"
패턴과 일치해야한다.
<module name="ClassTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Class type name ''{0}'' must match pattern ''{1}''."/>
</module>
VIOLATION
class MyClass<t> { }
OK
class MyClass<T> { }
static final 변수 이름을 검사. "^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$"
패턴과 일치해야 한다.
<module name="ConstantName"/>
VIOLATION
public static final int foo = 100;
OK
public static final int FOO = 100;
interface 타입 이름을 검사. "(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"
패턴과 일치해야 한다.
<module name="InterfaceTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Interface type name ''{0}'' must match pattern ''{1}''."/>
</module>
VIOLATION
interface Foo<t> { }
OK
interface Foo<T> { }
람다의 파라미터 이름을 검사. "^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"
패턴과 일치해야 한다.
<module name="LambdaParameterName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Lambda parameter name ''{0}'' must match pattern ''{1}''."/>
</module>
VIOLATION
Function<String, String> foo = Bar -> Bar.toLowerCase();
OK
Function<String, String> foo = bar -> bar.toLowerCase();
지역 final 변수 이름을 검사. "^[a-z][a-zA-Z0-9]*$"
패턴과 일치해야한다.
<module name="LocalFinalVariableName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Local final variable name ''{0}'' must match pattern ''{1}''."/>
</property>
</module>
VIOLATION
public void foo() {
final int BAR = 100;
final int Bar = 100;
}
OK
public void foo() {
final int bar = 100;
}
지역 변수 이름을 검사. "^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"
패턴과 일치해야한다.
<module name="LocalVariableName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Local variable name ''{0}'' must match pattern ''{1}''."/>
</module>
VIOLATION
int foo_1;
int Foo1;
int FOO1;
OK
int fooBar1;
클래스 멤버 이름을 검사. "^[a-z][a-z0-9][a-zA-Z0-9]*$"
패턴과 일치해야한다.
<module name="MemberName">
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
<message key="name.invalidPattern"
value="Member name ''{0}'' must match pattern ''{1}''."/>
</module>
VIOLATION
public int FOO1;
protected int FOO2;
final int FOO3;
private int FOO4;
OK
public int foo1;
protected int foo2;
final int foo3 = 3;
private int foo4;
/* static은 무시한다. */
static int FOO5 = 0;
static int foo6 = 0;
메소드 이름을 검사. "^[a-z][a-z0-9][a-zA-Z0-9_]*$"
패턴과 일치해야한다.
<module name="MethodName">
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9_]*$"/>
<message key="name.invalidPattern"
value="Method name ''{0}'' must match pattern ''{1}''."/>
</module>
VIOLATION
void Foo() { }
OK
void foo() { }
메소드 제네릭 타입 이름을 검사. "(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"
패턴과 일치해야한다.
<module name="MethodTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Method type name ''{0}'' must match pattern ''{1}''."/>
</module>
VIOLATION
public <t> void foo() { }
OK
public <T> void foo() { }
패키지 이름을 검사. "^[a-z]+(\.[a-z][a-z0-9]*)*$"
패턴과 일치해야한다.
<module name="PackageName">
<property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$"/>
<message key="name.invalidPattern"
value="Package name ''{0}'' must match pattern ''{1}''."/>
</module>
VIOLATION
package FOO;
package foo.BAR.baz.qux;
package foo.fooBAR.bar;
package foo._bar.baz_;
OK
package foo;
package foo.bar.baz;
package foo.bar1.baz;
파라미터 이름을 검사. "^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"
패턴과 일치해야한다.
<module name="ParameterName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Parameter name ''{0}'' must match pattern ''{1}''."/>
</module>
VIOLATION
void foo(int bar_2) { }
void foo(int Bar3) { }
OK
void foo(int bar1) { }
static 변수 이름을 검사. "^[a-z][a-zA-Z0-9]*$"
패턴과 일치해야한다.
<module name="StaticVariableName">
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
<message key="name.invalidPattern"
value="Static variable name ''{0}'' must match pattern ''{1}''."/>
</module>
VIOLATION
static int Foo = 300;
static int FOO = 300;
OK
static int foo = 300;
타입(class, interface, enum, annotation) 이름을 검사. "^[A-Z][a-zA-Z0-9]*$"
패턴과 일치해야한다.
<module name="TypeName">
<property name="format" value="^[A-Z][a-zA-Z0-9]*$"/>
<property name="tokens" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, ANNOTATION_DEF"/>
<message key="name.invalidPattern"
value="Type name ''{0}'' must match pattern ''{1}''."/>
</module>
VIOLATION
class myClass { }
OK
class MyClass { }
라인 뒤에 공백(' ') 혹은 탭('\t') 문자가 존재하는지 검사.
<module name="Regexp">
<property name="format" value="[ \t]+$"/>
<property name="illegalPattern" value="true"/>
<property name="message" value="Trailing whitespace"/>
</module>
한 파일이 2500 라인을 초과했는지 검사.
<module name="FileLength">
<property name="max" value="2500"/>
</module>
한 라인에 100 캐릭터를 초과했는지 검사.
<module name="LineLength">
<property name="fileExtensions" value="java"/>
<property name="max" value="100"/>
<property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://"/>
</module>
VIOLATION
String foo = "foooooooooooooooooooooooooooooooooooooooooooooooooooooooooo...";
OK
String foo = "fooooooooooooooooo" +
"oooooooooooooooooo" +
"ooooooooooooooo...";
메소드가 10000 라인을 초과했는지 검사.
<module name="MethodLength">
<property name="max" value="10000"/>
</module>
파라미터 개수가 10개를 초과했는지 검사.
<module name="ParameterNumber">
<property name="max" value="10"/>
</module>
VIOLATION
void foo(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j) {
}
for loop의 공백을 검사.
<module name="EmptyForIteratorPad"/>
VIOLATION
int foo = 0;
for ( ; foo < 100; ) {
foo++;
}
OK
int foo = 0;
for (; foo < 100;) {
foo++;
}
packge, import 등의 줄 바꿈을 검사.
<module name="EmptyLineSeparator">
<property name="tokens"
value="PACKAGE_DEF, IMPORT, STATIC_IMPORT, CLASS_DEF, INTERFACE_DEF, ENUM_DEF,
STATIC_INIT, INSTANCE_INIT, METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/>
<property name="allowNoEmptyLineBetweenFields" value="true"/>
</module>
VIOLATION
package foo.bar.baz;
import foo.bar.baz.Qux;
public class Foo {
public static void main(String[] args) {
}
public static void bar() {
}
}
OK
package foo.bar.baz;
import foo.bar.baz.Qux;
public class Foo {
public static void main(String[] args) {
}
public static void bar() {
}
}
탭('\t') 문자가 존재하는지 검사.
<module name="FileTabCharacter">
<property name="eachLine" value="true"/>
</module>
제네릭의 공백 규칙을 검사.
<module name="GenericWhitespace">
<message key="ws.followed"
value="GenericWhitespace ''{0}'' is followed by whitespace."/>
<message key="ws.preceded"
value="GenericWhitespace ''{0}'' is preceded with whitespace."/>
<message key="ws.illegalFollow"
value="GenericWhitespace ''{0}'' should followed by whitespace."/>
<message key="ws.notPreceded"
value="GenericWhitespace ''{0}'' is not preceded with whitespace."/>
</module>
VIOLATION
List <String> foo;
List<String>bar;
List< String> baz;
List<String > qux;
public< X, Y >X quux(X x, Y y) {
return ...;
}
OK
List<String> foo;
public <X, Y> X bar(X x, Y y) {
return ...;
}
메소드와 파라미터 사이의 공백을 검사.
<module name="MethodParamPad">
<property name="tokens"
value="CTOR_DEF, LITERAL_NEW, METHOD_CALL, METHOD_DEF,
SUPER_CTOR_CALL, ENUM_CONSTANT_DEF"/>
</module>
VIOLATION
public void foo (int bar) {
Baz baz = new Baz ();
baz.qux (1);
}
OK
public void foo(int bar) {
Baz baz = new Baz();
baz.qux(1);
}
import의 줄바꿈을 검사.
<module name="NoLineWrap">
<property name="tokens" value="PACKAGE_DEF, IMPORT, STATIC_IMPORT"/>
</module>
VIOLATION
package foo.bar.
baz.qux;
import foo.bar.
baz.Qux;
import static foo.bar.
Baz.QUX;
OK
package foo.bar.baz.qux;
import foo.bar.baz.Qux;
import static foo.bar.Baz.QUX;
토큰 뒤의 공백을 검사.
<module name="NoWhitespaceAfter"/>
VIOLATION
if (! foo) {
++ bar;
}
OK
if (!foo) {
++bar;
}
토큰 앞의 공백을 검사.
<module name="NoWhitespaceBefore"/>
VIOLATION
int foo = 0 ;
foo ++;
this .bar(1, 2, 3);
this.bar(1 , 2 , 3);
OK
int foo = 0;
foo++;
this.bar(1, 2, 3);
연산자의 줄바꿈을 검사.
<module name="OperatorWrap">
<property name="option" value="NL"/>
<property name="tokens"
value="BAND, BOR, BSR, BXOR, DIV, EQUAL, GE, GT, LAND, LE, LITERAL_INSTANCEOF,
LOR, LT, MINUS, MOD, NOT_EQUAL, PLUS, QUESTION, SL, SR, STAR, METHOD_REF"/>
</module>
VIOLATION
String foo = "A" +
"B";
if ((bar == baz) &&
(qux == quux)) {
System.out.println("equal");
}
OK
String foo = "A"
+ "B";
if ((bar == baz)
&& (qux == quux)) {
System.out.println("equal");
}
괄호 사이의 공백을 검사.
<module name="ParenPad">
<property name="tokens"
value="ANNOTATION, ANNOTATION_FIELD_DEF, CTOR_CALL, CTOR_DEF, DOT,
ENUM_CONSTANT_DEF,
EXPR, LITERAL_CATCH, LITERAL_DO, LITERAL_FOR, LITERAL_IF, LITERAL_NEW,
LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_WHILE, METHOD_CALL,
METHOD_DEF, QUESTION, RESOURCE_SPECIFICATION, SUPER_CTOR_CALL, LAMBDA"/>
</module>
VIOLATION
new String( "foo" );
this.bar( "bar" );
OK
new String("foo");
this.bar("bar");
dot('.')이 개행문자 뒤에 존재하는지 검사.
<module name="SeparatorWrap">
<property name="id" value="SeparatorWrapDot"/>
<property name="tokens" value="DOT"/>
<property name="option" value="nl"/>
</module>
VIOLATION
new Foo().
bar(null).
baz();
OK
new Foo()
.bar(null)
.baz();
comma가 개행문자 앞에 존재하는지 검사.
<module name="SeparatorWrap">
<property name="id" value="SeparatorWrapComma"/>
<property name="tokens" value="COMMA"/>
<property name="option" value="EOL"/>
</module>
VIOLATION
System.out.printf(
"%d %d %d"
,1
,2
,3
);
OK
System.out.printf(
"%d %d %d",
1,
2,
3
);
ellipsis('...')가 개행문자 앞에 존재하는지 검사.
<module name="SeparatorWrap">
<property name="id" value="SeparatorWrapEllipsis"/>
<property name="tokens" value="ELLIPSIS"/>
<property name="option" value="EOL"/>
</module>
VIOLATION
public static void printf(
String
arg1,
Object
...arg2) { }
OK
public static void printf(
String
arg1,
Object...
arg2) { }
배열 선언 문자('[', ']')가 개행문자 앞에 존재하는지 검사.
<module name="SeparatorWrap">
<property name="id" value="SeparatorWrapArrayDeclarator"/>
<property name="tokens" value="ARRAY_DECLARATOR"/>
<property name="option" value="EOL"/>
</module>
VIOLATION
int
[]array;
OK
int[]
array;
메소드 참조('::') 문자가 개행문자 뒤에 존재하는지 검사.
<module name="SeparatorWrap">
<property name="id" value="SeparatorWrapMethodRef"/>
<property name="tokens" value="METHOD_REF"/>
<property name="option" value="nl"/>
</module>
VIOLATION
Arrays.sort(stringArray, String::
compareToIgnoreCase);
OK
Arrays.sort(stringArray, String
::compareToIgnoreCase);
타입 변환 괄호 사이의 공백을 검사.
<module name="TypecastParenPad"/>
VIOLATION
foo = ( String ) bar;
OK
foo = (String) bar;
comma(','), semi-colon(';') 뒤의 공백을 검사.
<module name="WhitespaceAfter">
<property name="tokens" value="COMMA, SEMI"/>
</module>
VIOLATION
void foo(int bar,int baz) {
}
OK
void foo(int bar, int baz) {
}
token 사이에 공백이 존재하는지 검사.
<module name="WhitespaceAround">
<property name="allowEmptyConstructors" value="true"/>
<property name="allowEmptyLambdas" value="true"/>
<property name="allowEmptyMethods" value="false"/>
<property name="allowEmptyTypes" value="true"/>
<property name="allowEmptyLoops" value="true"/>
<property name="tokens"
value="ASSIGN, BAND, BAND_ASSIGN, BOR, BOR_ASSIGN, BSR, BSR_ASSIGN,
BXOR, BXOR_ASSIGN, COLON, DIV, DIV_ASSIGN, DO_WHILE, EQUAL,
GE, GT, LAMBDA, LAND,LCURLY, LE, LITERAL_CATCH, LITERAL_DO,
LITERAL_ELSE, LITERAL_FINALLY,LITERAL_FOR, LITERAL_IF,
LITERAL_RETURN, LITERAL_SWITCH, LITERAL_SYNCHRONIZED,
LITERAL_TRY, LITERAL_WHILE, LOR, LT, MINUS, MINUS_ASSIGN,
MOD, MOD_ASSIGN, NOT_EQUAL, PLUS, PLUS_ASSIGN, QUESTION,
RCURLY, SL, SLIST, SL_ASSIGN, SR, SR_ASSIGN, STAR,
STAR_ASSIGN, LITERAL_ASSERT, TYPE_EXTENSION_AND"/>
<message key="ws.notFollowed"
value="WhitespaceAround: ''{0}'' is not followed by whitespace. Empty blocks may only be represented as '{}' when not part of a multi-block statement (4.1.3)"/>
<message key="ws.notPreceded"
value="WhitespaceAround: ''{0}'' is not preceded with whitespace."/>
</module>
VIOLATION
boolean result = foo==bar; // '==' must preceded and followed whitespace
while(true) {} // 'while' must followed by whitespace
if(foo == bar) { } // 'if' is not followed by whitespace
System.out.println(foo+bar); // '+' must preceded and followed whitespace
synchronized(this) {} // 'synchronized' must followed by whitespace
OK
boolean result = foo == bar;
while (true) {}
if (foo == bar) { }
System.out.println(foo + bar);
synchronized (this) {}