1
2
3
4
5 package com.qulice.checkstyle;
6
7 import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
8 import com.puppycrawl.tools.checkstyle.api.DetailAST;
9 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
10 import java.util.regex.Pattern;
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 public final class ProhibitStaticNestedClassesCheck extends AbstractCheck {
28
29
30
31
32 private static final Pattern TESTS =
33 Pattern.compile(".*(Test|IT|ITCase)\\.java$");
34
35
36
37
38 private Pattern exclude;
39
40
41
42
43 public ProhibitStaticNestedClassesCheck() {
44 this.exclude = ProhibitStaticNestedClassesCheck.TESTS;
45 }
46
47
48
49
50
51
52 public void setExcludeFileNamePattern(final String regex) {
53 this.exclude = Pattern.compile(regex);
54 }
55
56 @Override
57 public int[] getDefaultTokens() {
58 return new int[] {TokenTypes.CLASS_DEF};
59 }
60
61 @Override
62 public int[] getAcceptableTokens() {
63 return this.getDefaultTokens();
64 }
65
66 @Override
67 public int[] getRequiredTokens() {
68 return this.getDefaultTokens();
69 }
70
71 @Override
72 public void visitToken(final DetailAST ast) {
73 if (!this.exclude.matcher(this.getFilePath()).find()
74 && ProhibitStaticNestedClassesCheck.isStaticNestedClass(ast)) {
75 final DetailAST name = ast.findFirstToken(TokenTypes.IDENT);
76 this.log(
77 name.getLineNo(),
78 String.format(
79 "Static class \"%s\" must be moved into its own file",
80 name.getText()
81 )
82 );
83 }
84 }
85
86 private static boolean isStaticNestedClass(final DetailAST ast) {
87 final DetailAST parent = ast.getParent();
88 return parent != null && parent.getType() == TokenTypes.OBJBLOCK
89 && ast.findFirstToken(TokenTypes.MODIFIERS)
90 .findFirstToken(TokenTypes.LITERAL_STATIC) != null;
91 }
92 }