1
2
3
4
5 package com.qulice.checkstyle;
6
7 import java.util.HashMap;
8 import java.util.Map;
9 import java.util.regex.Matcher;
10 import java.util.regex.Pattern;
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 final class RequiredJavaDocTag {
40
41
42
43 private final String name;
44
45
46
47
48 private final Pattern tag;
49
50
51
52
53 private final Pattern content;
54
55
56
57
58 private final Reporter reporter;
59
60
61
62
63
64
65
66 RequiredJavaDocTag(
67 final String name,
68 final Pattern patt,
69 final Reporter rep
70 ) {
71 this(
72 name,
73 Pattern.compile(
74 String.format(
75 "(?<name>^ +\\* +@%s)( +)(?<cont>.*)",
76 name
77 )
78 ),
79 patt,
80 rep
81 );
82 }
83
84
85
86
87
88
89
90
91
92 RequiredJavaDocTag(
93 final String cname,
94 final Pattern ptag,
95 final Pattern patt,
96 final Reporter rep
97 ) {
98 this.name = cname;
99 this.tag = ptag;
100 this.content = patt;
101 this.reporter = rep;
102 }
103
104
105
106
107
108
109
110 public void matchTagFormat(
111 final String[] lines,
112 final int start,
113 final int end
114 ) {
115 final Map<Integer, String> found = new HashMap<>(1);
116 for (int pos = start; pos <= end; pos += 1) {
117 final String line = lines[pos];
118 final Matcher matcher = this.tag.matcher(line);
119 if (RequiredJavaDocTag.tagFound(matcher)) {
120 found.put(pos, matcher.group("cont"));
121 break;
122 }
123 }
124 if (found.isEmpty()) {
125 this.reporter.log(
126 start + 1,
127 "Missing ''@{0}'' tag in class/interface comment",
128 this.name
129 );
130 } else {
131 for (final Map.Entry<Integer, String> item : found.entrySet()) {
132 if (!this.content.matcher(item.getValue()).matches()) {
133 this.reporter.log(
134 item.getKey() + 1,
135 "Tag text ''{0}'' does not match the pattern ''{1}''",
136 item.getValue(),
137 this.content.toString()
138 );
139 }
140 }
141 }
142 }
143
144
145
146
147
148
149 private static boolean tagFound(final Matcher matcher) {
150 return matcher.matches()
151 && !RequiredJavaDocTag.empty(matcher.group("name"))
152 && !RequiredJavaDocTag.empty(matcher.group("cont"));
153 }
154
155
156
157
158
159
160 private static boolean empty(final String str) {
161 return str == null || str.chars().allMatch(Character::isWhitespace);
162 }
163
164
165
166
167
168
169 interface Reporter {
170
171
172
173
174
175
176
177
178 void log(int line, String msg, Object... args);
179 }
180 }