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
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 public final class JavadocTagsDotCheck extends AbstractCheck {
39
40
41
42
43 public JavadocTagsDotCheck() {
44
45 }
46
47 @Override
48 public int[] getDefaultTokens() {
49 return new int[] {
50 TokenTypes.METHOD_DEF,
51 TokenTypes.CTOR_DEF,
52 };
53 }
54
55 @Override
56 public int[] getAcceptableTokens() {
57 return this.getDefaultTokens();
58 }
59
60 @Override
61 public int[] getRequiredTokens() {
62 return this.getDefaultTokens();
63 }
64
65 @Override
66 public void visitToken(final DetailAST ast) {
67 final String[] lines = this.getLines();
68 final int cend = JavadocTagsDotCheck.findTrimmedTextUp(
69 lines, ast.getLineNo() - 1, "*/"
70 );
71 final int cstart = JavadocTagsDotCheck.findTrimmedTextUp(
72 lines, cend, "/**"
73 );
74 if (cstart >= 0 && cend > cstart) {
75 this.inspect(lines, cstart, cend);
76 }
77 }
78
79 private void inspect(final String[] lines, final int cstart, final int cend) {
80 int tag = -1;
81 for (int pos = cstart + 1; pos <= cend; pos += 1) {
82 final String trimmed = lines[pos].trim();
83 final boolean next = trimmed.startsWith("* @")
84 || "*/".equals(trimmed);
85 if (next && tag >= 0) {
86 this.verify(lines, tag, pos - 1);
87 tag = -1;
88 }
89 if (JavadocTagsDotCheck.isParamOrReturn(trimmed)) {
90 tag = pos;
91 }
92 }
93 }
94
95 private void verify(final String[] lines, final int from, final int until) {
96 for (int pos = until; pos >= from; pos -= 1) {
97 final String content = JavadocTagsDotCheck.stripMarker(lines[pos]);
98 if (!content.isEmpty()) {
99 if (content.endsWith(".")) {
100 this.log(
101 pos + 1,
102 "No dot allowed at the end of a '@param' or '@return' Javadoc tag"
103 );
104 }
105 break;
106 }
107 }
108 }
109
110 private static boolean isParamOrReturn(final String trimmed) {
111 final String tag;
112 if (trimmed.startsWith("* @")) {
113 tag = trimmed.substring("* @".length());
114 } else {
115 tag = "";
116 }
117 return tag.startsWith("param ")
118 || tag.startsWith("return ")
119 || "return".equals(tag);
120 }
121
122 private static String stripMarker(final String line) {
123 String result = line.trim();
124 if (result.startsWith("*")) {
125 result = result.substring(1).trim();
126 }
127 return result;
128 }
129
130 private static int findTrimmedTextUp(
131 final String[] lines,
132 final int start,
133 final String text
134 ) {
135 int found = -1;
136 for (int pos = start - 1; pos >= 0; pos -= 1) {
137 if (lines[pos].trim().equals(text)) {
138 found = pos;
139 break;
140 }
141 }
142 return found;
143 }
144 }