Skip to content

Commit

Permalink
Issue #4092: added extends, implements and annotations processing
Browse files Browse the repository at this point in the history
  • Loading branch information
kazachka authored and rnveach committed Sep 16, 2018
1 parent 45d2cab commit ecaa420
Show file tree
Hide file tree
Showing 9 changed files with 191 additions and 57 deletions.
3 changes: 2 additions & 1 deletion config/checkstyle_checks.xml
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,8 @@
UnsupportedEncodingException, BuildException, ConversionException,
FileNotFoundException, TestException, Log, Sets, Multimap,
TokenStreamRecognitionException, RecognitionException,
TokenStreamException, IOException"/>
TokenStreamException, IOException, Override, Deprecated, SafeVarargs,
SuppressWarnings, FunctionalInterface"/>
</module>
<module name="CyclomaticComplexity">
<property name="switchBlockAsSingleDecisionPoint" value="true"/>
Expand Down
1 change: 1 addition & 0 deletions config/suppressions.xml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
<suppress checks="ClassFanOutComplexity" files="[\\/]Main\.java"/>
<suppress checks="ClassFanOutComplexity" files="CheckstyleAntTask\.java"/>
<suppress checks="ClassFanOutComplexity" files="CheckerTest\.java"/>
<suppress checks="ClassFanOutComplexity" files="Checker\.java"/>
<!-- a lot of GUI elements is OK -->
<suppress checks="ClassDataAbstractionCoupling" files="(TreeTable|MainFrame)\.java"/>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ public abstract class AbstractClassCouplingCheck extends AbstractCheck {
"List", "ArrayList", "Deque", "Queue", "LinkedList",
"Set", "HashSet", "SortedSet", "TreeSet",
"Map", "HashMap", "SortedMap", "TreeMap",
"Override", "Deprecated", "SafeVarargs", "SuppressWarnings", "FunctionalInterface",
}).collect(Collectors.toSet()));

/** Package names to ignore. */
Expand Down Expand Up @@ -177,6 +178,8 @@ public void visitToken(DetailAST ast) {
case TokenTypes.ENUM_DEF:
visitClassDef(ast);
break;
case TokenTypes.EXTENDS_CLAUSE:
case TokenTypes.IMPLEMENTS_CLAUSE:
case TokenTypes.TYPE:
fileContext.visitType(ast);
break;
Expand All @@ -186,6 +189,9 @@ public void visitToken(DetailAST ast) {
case TokenTypes.LITERAL_THROWS:
fileContext.visitLiteralThrows(ast);
break;
case TokenTypes.ANNOTATION:
fileContext.visitAnnotationType(ast);
break;
default:
throw new IllegalArgumentException("Unknown type: " + ast);
}
Expand Down Expand Up @@ -327,6 +333,16 @@ public void visitLiteralThrows(DetailAST ast) {
classContext.visitLiteralThrows(ast);
}

/**
* Visit ANNOTATION literal and get its type to referenced classes of context.
* @param annotationAST Annotation ast.
*/
private void visitAnnotationType(DetailAST annotationAST) {
final DetailAST children = annotationAST.getFirstChild();
final DetailAST type = children.getNextSibling();
classContext.addReferencedClassName(type.getText());
}

}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ public int[] getRequiredTokens() {
TokenTypes.PACKAGE_DEF,
TokenTypes.IMPORT,
TokenTypes.CLASS_DEF,
TokenTypes.EXTENDS_CLAUSE,
TokenTypes.IMPLEMENTS_CLAUSE,
TokenTypes.ANNOTATION,
TokenTypes.INTERFACE_DEF,
TokenTypes.ENUM_DEF,
TokenTypes.TYPE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,9 @@ public void test15() throws Exception {

checkConfig.addAttribute("max", "0");

final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
final String[] expected = {
"9:1: " + getCheckMessage(MSG_KEY, 1, 0),
};

verify(checkConfig, getPath("InputClassFanOutComplexity15Extensions.java"), expected);
}
Expand All @@ -165,6 +167,9 @@ public void testGetAcceptableTokens() {
TokenTypes.PACKAGE_DEF,
TokenTypes.IMPORT,
TokenTypes.CLASS_DEF,
TokenTypes.EXTENDS_CLAUSE,
TokenTypes.IMPLEMENTS_CLAUSE,
TokenTypes.ANNOTATION,
TokenTypes.INTERFACE_DEF,
TokenTypes.ENUM_DEF,
TokenTypes.TYPE,
Expand Down Expand Up @@ -230,4 +235,46 @@ public void testPackageName() throws Exception {
getPath("InputClassFanOutComplexityPackageName.java"), expected);
}

@Test
public void testExtends() throws Exception {
final DefaultConfiguration checkConfig =
createModuleConfig(ClassFanOutComplexityCheck.class);
checkConfig.addAttribute("max", "0");
final String[] expected = {
"3:1: " + getCheckMessage(MSG_KEY, 1, 0),
};
verify(checkConfig,
getPath("InputClassFanOutComplexityExtends.java"), expected);
}

@Test
public void testImplements() throws Exception {
final DefaultConfiguration checkConfig =
createModuleConfig(ClassFanOutComplexityCheck.class);
checkConfig.addAttribute("max", "0");
final String[] expected = {
"3:1: " + getCheckMessage(MSG_KEY, 1, 0),
};
verify(checkConfig,
getPath("InputClassFanOutComplexityImplements.java"), expected);
}

@Test
public void testAnnotation() throws Exception {
final DefaultConfiguration checkConfig =
createModuleConfig(ClassFanOutComplexityCheck.class);
checkConfig.addAttribute("max", "0");
final String[] expected = {
"9:1: " + getCheckMessage(MSG_KEY, 2, 0),
"25:5: " + getCheckMessage(MSG_KEY, 2, 0),
"34:5: " + getCheckMessage(MSG_KEY, 3, 0),
"44:5: " + getCheckMessage(MSG_KEY, 2, 0),
"59:1: " + getCheckMessage(MSG_KEY, 1, 0),
"79:1: " + getCheckMessage(MSG_KEY, 1, 0),
"82:1: " + getCheckMessage(MSG_KEY, 1, 0),
};
verify(checkConfig,
getPath("InputClassFanOutComplexityAnnotations.java"), expected);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package com.puppycrawl.tools.checkstyle.checks.metrics.classfanoutcomplexity;

import java.lang.annotation.ElementType;
import java.lang.annotation.Target;

import com.puppycrawl.tools.checkstyle.api.TokenTypes;

/* This input file is intended to be used on strict configuration: max=0 */
public class InputClassFanOutComplexityAnnotations { // violation

private int tokenType = TokenTypes.EXPR;

public void foo1(@TypeAnnotation char a) {}

public void foo2(final char @TypeAnnotation [] a) {}

@MethodAnnotation
public void foo3() {}

@Override
public String toString() {
return super.toString();
}

@MyAnnotation // violation
public class InnerClass {

@MyAnnotation
@MethodAnnotation
public void innerClassMethod() {}

}

public class InnerClass2 { // violation

@MethodAnnotation
@MyAnnotation
public String innerClass2Method(@TypeAnnotation String parameter) {
return parameter.trim();
}

}

public class InnerClass3 { // violation

@TypeAnnotation
private final String warningsType = "boxing";

@MyAnnotation
@SuppressWarnings(value = warningsType)
public String innerClass3Method() {
return new Integer(5).toString();
}

}

}

class OuterClass { // violation

private static final String name = "1";

private static final String value = "4";

@TwoParametersAnnotation(value = "4", tokenType = 1)
public static final String EMPTY_STRING = "";

@TwoParametersAnnotation(value = value, tokenType = TokenTypes.ANNOTATION)
public static final String TAB = "\t";

}

@Target(ElementType.TYPE_USE)
@interface TypeAnnotation {}

@Target(ElementType.METHOD)
@interface MethodAnnotation {}

@MyAnnotation // violation
class MyClass {}

@MyAnnotation // violation
interface MyInterface {}

@interface MyAnnotation {}

@interface TwoParametersAnnotation {

String value();

int tokenType();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.puppycrawl.tools.checkstyle.checks.metrics.classfanoutcomplexity;

public class InputClassFanOutComplexityExtends extends ParentClass {
}

class ParentClass {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.puppycrawl.tools.checkstyle.checks.metrics.classfanoutcomplexity;

public class InputClassFanOutComplexityImplements implements Interface {}

interface Interface {}
72 changes: 17 additions & 55 deletions src/xdocs/config_metrics.xml
Original file line number Diff line number Diff line change
Expand Up @@ -237,13 +237,14 @@
<td>excludedClasses</td>
<td>User-configured class names to ignore</td>
<td><a href="property_types.html#stringSet">String Set</a></td>
<td>IllegalStateException, Set, StringBuilder, HashMap, ArrayList,
String, float, SortedSet, long, RuntimeException, NullPointerException,
TreeSet, List, Boolean, Void, Queue, Short, IllegalArgumentException,
UnsupportedOperationException, HashSet, void, Character, IndexOutOfBoundsException,
byte, double, SecurityException, TreeMap, Double, Deque, int, Exception, LinkedList,
Integer, Float, StringBuffer, boolean, Byte, SortedMap, char, Long, short,
Throwable, Object, Class, ArrayIndexOutOfBoundsException, Map</td>
<td>HashMap, ArrayList, String, float, TreeSet, List, Boolean, Void, Override, Short,
IllegalArgumentException, UnsupportedOperationException, HashSet, void, Character,
IndexOutOfBoundsException, byte, double, Double, LinkedList, Float, Byte,
SortedMap, Long, Throwable, Object, Class, Map, IllegalStateException, Set,
StringBuilder, SuppressWarnings, SortedSet, long, RuntimeException, Deprecated,
NullPointerException, Queue, SecurityException, FunctionalInterface, TreeMap,
Deque, int, Exception, Integer, SafeVarargs, StringBuffer, boolean, char, short,
ArrayIndexOutOfBoundsException</td>
<td>5.7</td>
</tr>
<tr>
Expand Down Expand Up @@ -486,47 +487,7 @@ public class Foo {
This check processes files in the following way:
<ol>
<li>
Iterates over the list of tokens (defined below) and counts all mentioned classes.
<ul>
<li>
<a href="apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#PACKAGE_DEF">
PACKAGE_DEF</a>
</li>
<li>
<a href="apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#IMPORT">
IMPORT</a>
</li>
<li>
<a href="apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#CLASS_DEF">
CLASS_DEF</a>
</li>
<li>
<a href="apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#INTERFACE_DEF">
INTERFACE_DEF</a>
</li>
<li>
<a href="apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#ENUM_DEF">
ENUM_DEF</a>
</li>
<li>
<a href="apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#TYPE">
TYPE</a>
</li>
<li>
<a href="apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#LITERAL_NEW">
LITERAL_NEW</a>
</li>
<li>
<a href="apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#LITERAL_THROWS">
LITERAL_THROWS
</a>
</li>
<li>
<a href="apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#ANNOTATION_DEF">
ANNOTATION_DEF
</a>
</li>
</ul>
Iterates over all tokens that might contain type reference.
</li>
<li>
If a class was imported with direct import (i.e.
Expand Down Expand Up @@ -563,13 +524,14 @@ public class Foo {
<td>excludedClasses</td>
<td>User-configured class names to ignore</td>
<td><a href="property_types.html#stringSet">String Set</a></td>
<td>IllegalStateException, Set, StringBuilder, HashMap, ArrayList,
String, float, SortedSet, long, RuntimeException, NullPointerException,
TreeSet, List, Boolean, Void, Queue, Short, IllegalArgumentException,
UnsupportedOperationException, HashSet, void, Character, IndexOutOfBoundsException,
byte, double, SecurityException, TreeMap, Double, Deque, int, Exception, LinkedList,
Integer, Float, StringBuffer, boolean, Byte, SortedMap, char, Long, short,
Throwable, Object, Class, ArrayIndexOutOfBoundsException, Map</td>
<td>HashMap, ArrayList, String, float, TreeSet, List, Boolean, Void, Override, Short,
IllegalArgumentException, UnsupportedOperationException, HashSet, void, Character,
IndexOutOfBoundsException, byte, double, Double, LinkedList, Float, Byte,
SortedMap, Long, Throwable, Object, Class, Map, IllegalStateException, Set,
StringBuilder, SuppressWarnings, SortedSet, long, RuntimeException, Deprecated,
NullPointerException, Queue, SecurityException, FunctionalInterface, TreeMap,
Deque, int, Exception, Integer, SafeVarargs, StringBuffer, boolean, char, short,
ArrayIndexOutOfBoundsException</td>
<td>5.7</td>
</tr>
<tr>
Expand Down

0 comments on commit ecaa420

Please sign in to comment.