Skip to content

Commit e8f1762

Browse files
committed
Merge branch '__rultor'
2 parents a463a92 + dfc2c62 commit e8f1762

File tree

14 files changed

+728
-82
lines changed

14 files changed

+728
-82
lines changed

qulice-checkstyle/src/main/java/com/qulice/checkstyle/JavadocTagsCheck.java

Lines changed: 27 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,7 @@
3636
import java.util.ArrayList;
3737
import java.util.Arrays;
3838
import java.util.Collection;
39-
import java.util.HashMap;
4039
import java.util.List;
41-
import java.util.Map;
4240
import java.util.regex.Pattern;
4341

4442
/**
@@ -69,7 +67,7 @@ public final class JavadocTagsCheck extends AbstractCheck {
6967
/**
7068
* Map of tag and its pattern.
7169
*/
72-
private final Map<String, Pattern> tags = new HashMap<>();
70+
private final List<RequiredJavaDocTag> required = new ArrayList<>(1);
7371

7472
/**
7573
* List of prohibited javadoc tags.
@@ -97,10 +95,13 @@ public int[] getRequiredTokens() {
9795

9896
@Override
9997
public void init() {
100-
this.tags.put(
101-
"since",
102-
Pattern.compile(
98+
this.required.add(
99+
new RequiredJavaDocTag(
100+
"since",
101+
Pattern.compile(
103102
"^\\d+(\\.\\d+){1,2}(\\.[0-9A-Za-z-]+(\\.[0-9A-Za-z-]+)*)?$"
103+
),
104+
this::log
104105
)
105106
);
106107
}
@@ -115,34 +116,26 @@ public void visitToken(final DetailAST ast) {
115116
for (final String tag : this.prohibited) {
116117
this.findProhibited(lines, start, cstart, cend, tag);
117118
}
118-
for (final String tag : this.tags.keySet()) {
119-
this.matchTagFormat(lines, cstart, cend, tag);
119+
for (final RequiredJavaDocTag tag : this.required) {
120+
tag.matchTagFormat(lines, cstart, cend);
120121
}
121122
} else {
122123
this.log(0, "Problem finding class/interface comment");
123124
}
124125
}
125126

126-
/**
127-
* Get the text of the given tag.
128-
* @param line Line with the tag.
129-
* @return The text of the tag.
130-
*/
131-
private static String getTagText(final String line) {
132-
return line.substring(
133-
line.indexOf(' ', line.indexOf('@')) + 1
134-
);
135-
}
136-
137127
/**
138128
* Find a text in lines, by going up.
139129
* @param lines List of lines to check.
140130
* @param start Start searching from this line number.
141131
* @param text Text to find.
142132
* @return Line number with found text, or -1 if it wasn't found.
143133
*/
144-
private static int findTrimmedTextUp(final String[] lines,
145-
final int start, final String text) {
134+
private static int findTrimmedTextUp(
135+
final String[] lines,
136+
final int start,
137+
final String text
138+
) {
146139
int found = -1;
147140
for (int pos = start - 1; pos >= 0; pos -= 1) {
148141
if (lines[pos].trim().equals(text)) {
@@ -182,8 +175,13 @@ private static int findCommentEnd(final String[] lines, final int start) {
182175
* @param tag Name of the tag.
183176
* @checkstyle ParameterNumber (3 lines)
184177
*/
185-
private void findProhibited(final String[] lines, final int start,
186-
final int cstart, final int cend, final String tag) {
178+
private void findProhibited(
179+
final String[] lines,
180+
final int start,
181+
final int cstart,
182+
final int cend,
183+
final String tag
184+
) {
187185
final List<Integer> found =
188186
this.findTagLineNum(lines, cstart, cend, tag);
189187
if (!found.isEmpty()) {
@@ -195,38 +193,6 @@ private void findProhibited(final String[] lines, final int start,
195193
}
196194
}
197195

198-
/**
199-
* Check if the tag text matches the format from pattern.
200-
* @param lines List of all lines.
201-
* @param start Line number where comment starts.
202-
* @param end Line number where comment ends.
203-
* @param tag Name of the tag.
204-
* @checkstyle ParameterNumber (3 lines)
205-
*/
206-
private void matchTagFormat(final String[] lines, final int start,
207-
final int end, final String tag) {
208-
final List<Integer> found = this.findTagLineNum(lines, start, end, tag);
209-
if (found.isEmpty()) {
210-
this.log(
211-
start + 1,
212-
"Missing ''@{0}'' tag in class/interface comment",
213-
tag
214-
);
215-
return;
216-
}
217-
for (final Integer item : found) {
218-
final String text = JavadocTagsCheck.getTagText(lines[item]);
219-
if (!this.tags.get(tag).matcher(text).matches()) {
220-
this.log(
221-
item + 1,
222-
"Tag text ''{0}'' does not match the pattern ''{1}''",
223-
text,
224-
this.tags.get(tag).toString()
225-
);
226-
}
227-
}
228-
}
229-
230196
/**
231197
* Find given tag in comment lines.
232198
* @param lines Lines to search for the tag.
@@ -236,8 +202,12 @@ private void matchTagFormat(final String[] lines, final int start,
236202
* @return Line number with found tag or -1 otherwise.
237203
* @checkstyle ParameterNumber (3 lines)
238204
*/
239-
private List<Integer> findTagLineNum(final String[] lines, final int start,
240-
final int end, final String tag) {
205+
private List<Integer> findTagLineNum(
206+
final String[] lines,
207+
final int start,
208+
final int end,
209+
final String tag
210+
) {
241211
final String prefix = String.format(" * @%s ", tag);
242212
final List<Integer> found = new ArrayList<>(1);
243213
for (int pos = start; pos <= end; pos += 1) {
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
/*
2+
* Copyright (c) 2011-2024 Qulice.com
3+
*
4+
* All rights reserved.
5+
*
6+
* Redistribution and use in source and binary forms, with or without
7+
* modification, are permitted provided that the following conditions
8+
* are met: 1) Redistributions of source code must retain the above
9+
* copyright notice, this list of conditions and the following
10+
* disclaimer. 2) Redistributions in binary form must reproduce the above
11+
* copyright notice, this list of conditions and the following
12+
* disclaimer in the documentation and/or other materials provided
13+
* with the distribution. 3) Neither the name of the Qulice.com nor
14+
* the names of its contributors may be used to endorse or promote
15+
* products derived from this software without specific prior written
16+
* permission.
17+
*
18+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
20+
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21+
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
22+
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23+
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26+
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27+
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
29+
* OF THE POSSIBILITY OF SUCH DAMAGE.
30+
*/
31+
package com.qulice.checkstyle;
32+
33+
import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
34+
import com.puppycrawl.tools.checkstyle.api.DetailAST;
35+
import com.puppycrawl.tools.checkstyle.api.TokenTypes;
36+
import java.util.regex.Matcher;
37+
import java.util.regex.Pattern;
38+
39+
/**
40+
* Multi line comment checker.
41+
* Used by the checkstyle process multiple times as a singleton.
42+
* @since 0.23.1
43+
*/
44+
public final class MultiLineCommentCheck extends AbstractCheck {
45+
/**
46+
* Pattern for check.
47+
* It is not final as it is initialized from the configuration.
48+
*/
49+
private Pattern format = Pattern.compile("^$");
50+
51+
/**
52+
* The message to report for a match.
53+
* It is not final as it is initialized from the configuration.
54+
*/
55+
private String message = "";
56+
57+
/**
58+
* Comment line.
59+
* It is not final because the visitToken method is called many times
60+
* during the class under test and the field is reinitialized with a new object.
61+
*/
62+
@SuppressWarnings("PMD.AvoidStringBufferField")
63+
private StringBuilder text;
64+
65+
@Override
66+
public boolean isCommentNodesRequired() {
67+
return true;
68+
}
69+
70+
@Override
71+
public int[] getDefaultTokens() {
72+
return new int[]{
73+
TokenTypes.BLOCK_COMMENT_BEGIN,
74+
TokenTypes.COMMENT_CONTENT,
75+
TokenTypes.BLOCK_COMMENT_END,
76+
};
77+
}
78+
79+
@Override
80+
public int[] getAcceptableTokens() {
81+
return this.getDefaultTokens();
82+
}
83+
84+
@Override
85+
public int[] getRequiredTokens() {
86+
return this.getDefaultTokens();
87+
}
88+
89+
@Override
90+
public void visitToken(final DetailAST ast) {
91+
if (ast.getType() == TokenTypes.BLOCK_COMMENT_BEGIN) {
92+
this.text = new StringBuilder(ast.getText());
93+
} else if (ast.getType() == TokenTypes.COMMENT_CONTENT) {
94+
this.text.append(ast.getText());
95+
} else {
96+
this.text.append(ast.getText());
97+
final Matcher matcher = this.format.matcher(this.text.toString());
98+
if (matcher.matches()) {
99+
this.log(ast, this.message);
100+
}
101+
}
102+
}
103+
104+
/**
105+
* The method is called from checkstyle to configure this class.
106+
* The parameter is set from the checks.xml file
107+
* <module name="com.qulice.checkstyle.MultiLineCommentCheck"/> and
108+
* <property name="format" value=" this regexp "/> property
109+
*
110+
* @param fmt Validatig regexp.
111+
*/
112+
public void setFormat(final String fmt) {
113+
this.format = Pattern.compile(fmt);
114+
}
115+
116+
/**
117+
* The method is called from checkstyle to configure this class.
118+
* The parameter is set from the checks.xml file
119+
* <module name="com.qulice.checkstyle.MultiLineCommentCheck"/> and
120+
* <property name="message" value="First sentence in a comment should start with ....."/>
121+
* property
122+
*
123+
* @param msg Error message.
124+
*/
125+
public void setMessage(final String msg) {
126+
this.message = msg;
127+
}
128+
}

0 commit comments

Comments
 (0)