1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package com.puppycrawl.tools.checkstyle.checks;
21
22 import java.io.File;
23 import java.util.regex.Pattern;
24
25 import com.puppycrawl.tools.checkstyle.FileStatefulCheck;
26 import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
27 import com.puppycrawl.tools.checkstyle.api.DetailAST;
28 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
29 import com.puppycrawl.tools.checkstyle.utils.TokenUtil;
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50 @FileStatefulCheck
51 public class OuterTypeFilenameCheck extends AbstractCheck {
52
53
54
55
56
57 public static final String MSG_KEY = "type.file.mismatch";
58
59
60 private static final Pattern FILE_EXTENSION_PATTERN = Pattern.compile("\\.[^.]*$");
61
62
63 private boolean seenFirstToken;
64
65
66 private String fileName;
67
68
69 private boolean hasPublic;
70
71
72 private DetailAST wrongType;
73
74 @Override
75 public int[] getDefaultTokens() {
76 return getRequiredTokens();
77 }
78
79 @Override
80 public int[] getAcceptableTokens() {
81 return getRequiredTokens();
82 }
83
84 @Override
85 public int[] getRequiredTokens() {
86 return new int[] {
87 TokenTypes.CLASS_DEF,
88 TokenTypes.INTERFACE_DEF,
89 TokenTypes.ENUM_DEF,
90 TokenTypes.ANNOTATION_DEF,
91 TokenTypes.RECORD_DEF,
92 };
93 }
94
95 @Override
96 public void beginTree(DetailAST rootAST) {
97 fileName = getSourceFileName();
98 seenFirstToken = false;
99 hasPublic = false;
100 wrongType = null;
101 }
102
103 @Override
104 public void visitToken(DetailAST ast) {
105 if (seenFirstToken) {
106 final DetailAST modifiers = ast.findFirstToken(TokenTypes.MODIFIERS);
107 if (modifiers.findFirstToken(TokenTypes.LITERAL_PUBLIC) != null
108 && TokenUtil.isRootNode(ast.getParent())) {
109 hasPublic = true;
110 }
111 }
112 else {
113 final String outerTypeName = ast.findFirstToken(TokenTypes.IDENT).getText();
114
115 if (!fileName.equals(outerTypeName)) {
116 wrongType = ast;
117 }
118 }
119 seenFirstToken = true;
120 }
121
122 @Override
123 public void finishTree(DetailAST rootAST) {
124 if (!hasPublic && wrongType != null) {
125 log(wrongType, MSG_KEY);
126 }
127 }
128
129
130
131
132
133
134 private String getSourceFileName() {
135 String name = getFilePath();
136 name = name.substring(name.lastIndexOf(File.separatorChar) + 1);
137 return FILE_EXTENSION_PATTERN.matcher(name).replaceAll("");
138 }
139
140 }