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.javadoc;
21
22 import java.util.regex.Pattern;
23
24 import com.puppycrawl.tools.checkstyle.StatelessCheck;
25 import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
26 import com.puppycrawl.tools.checkstyle.api.DetailAST;
27 import com.puppycrawl.tools.checkstyle.api.FileContents;
28 import com.puppycrawl.tools.checkstyle.api.Scope;
29 import com.puppycrawl.tools.checkstyle.api.TextBlock;
30 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
31 import com.puppycrawl.tools.checkstyle.utils.ScopeUtil;
32
33
34
35
36
37 @StatelessCheck
38 public class JavadocVariableCheck
39 extends AbstractCheck {
40
41
42
43
44
45 public static final String MSG_JAVADOC_MISSING = "javadoc.missing";
46
47
48 private Scope scope = Scope.PRIVATE;
49
50
51 private Scope excludeScope;
52
53
54 private Pattern ignoreNamePattern;
55
56
57
58
59
60 public void setScope(Scope scope) {
61 this.scope = scope;
62 }
63
64
65
66
67
68 public void setExcludeScope(Scope excludeScope) {
69 this.excludeScope = excludeScope;
70 }
71
72
73
74
75
76 public void setIgnoreNamePattern(Pattern pattern) {
77 ignoreNamePattern = pattern;
78 }
79
80 @Override
81 public int[] getDefaultTokens() {
82 return getAcceptableTokens();
83 }
84
85 @Override
86 public int[] getAcceptableTokens() {
87 return new int[] {
88 TokenTypes.VARIABLE_DEF,
89 TokenTypes.ENUM_CONSTANT_DEF,
90 };
91 }
92
93
94
95
96
97 @Override
98 public int[] getRequiredTokens() {
99 return new int[] {
100 TokenTypes.VARIABLE_DEF,
101 };
102 }
103
104 @Override
105 public void visitToken(DetailAST ast) {
106 if (shouldCheck(ast)) {
107 final FileContents contents = getFileContents();
108 final TextBlock textBlock =
109 contents.getJavadocBefore(ast.getLineNo());
110
111 if (textBlock == null) {
112 log(ast, MSG_JAVADOC_MISSING);
113 }
114 }
115 }
116
117
118
119
120
121
122 private boolean isIgnored(DetailAST ast) {
123 final String name = ast.findFirstToken(TokenTypes.IDENT).getText();
124 return ignoreNamePattern != null && ignoreNamePattern.matcher(name).matches()
125 || "serialVersionUID".equals(name);
126 }
127
128
129
130
131
132
133 private boolean shouldCheck(final DetailAST ast) {
134 boolean result = false;
135 if (!ScopeUtil.isInCodeBlock(ast) && !isIgnored(ast)) {
136 Scope customScope = Scope.PUBLIC;
137 if (ast.getType() != TokenTypes.ENUM_CONSTANT_DEF
138 && !ScopeUtil.isInInterfaceOrAnnotationBlock(ast)) {
139 final DetailAST mods = ast.findFirstToken(TokenTypes.MODIFIERS);
140 customScope = ScopeUtil.getScopeFromMods(mods);
141 }
142
143 final Scope surroundingScope = ScopeUtil.getSurroundingScope(ast);
144 result = customScope.isIn(scope) && surroundingScope.isIn(scope)
145 && (excludeScope == null
146 || !customScope.isIn(excludeScope)
147 || !surroundingScope.isIn(excludeScope));
148 }
149 return result;
150 }
151
152 }