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
39
40 public final class MethodDeclarationLengthCheck extends AbstractCheck {
41
42
43
44
45 private int max;
46
47
48
49
50 public MethodDeclarationLengthCheck() {
51 this.max = 80;
52 }
53
54
55
56
57
58
59 public void setMax(final int value) {
60 this.max = value;
61 }
62
63 @Override
64 public int[] getDefaultTokens() {
65 return this.getRequiredTokens();
66 }
67
68 @Override
69 public int[] getAcceptableTokens() {
70 return this.getRequiredTokens();
71 }
72
73 @Override
74 public int[] getRequiredTokens() {
75 return new int[] {TokenTypes.METHOD_DEF, TokenTypes.CTOR_DEF};
76 }
77
78 @Override
79 public void visitToken(final DetailAST ast) {
80 final DetailAST start = MethodDeclarationLengthCheck.head(ast);
81 final DetailAST end = MethodDeclarationLengthCheck.tail(ast);
82 if (start != null && end != null
83 && start.getLineNo() < end.getLineNo()) {
84 this.verify(start, end);
85 }
86 }
87
88 private void verify(final DetailAST start, final DetailAST end) {
89 final String[] lines = this.getLines();
90 final int first = start.getLineNo();
91 final int last = end.getLineNo();
92 final int col = start.getColumnNo();
93 final StringBuilder joined = new StringBuilder(
94 lines[first - 1].substring(col).trim()
95 );
96 for (int idx = first; idx < last; idx += 1) {
97 final String trimmed = lines[idx].trim();
98 if (!trimmed.isEmpty()) {
99 joined.append(' ').append(trimmed);
100 }
101 }
102 if (col + joined.length() <= this.max) {
103 this.log(
104 first,
105 "Method declaration can be placed on a single line"
106 );
107 }
108 }
109
110 private static DetailAST head(final DetailAST def) {
111 final DetailAST modifiers = def.findFirstToken(TokenTypes.MODIFIERS);
112 DetailAST child = modifiers.getFirstChild();
113 while (child != null && child.getType() == TokenTypes.ANNOTATION) {
114 child = child.getNextSibling();
115 }
116 final DetailAST result;
117 if (child == null) {
118 DetailAST fallback = def.findFirstToken(TokenTypes.TYPE);
119 if (fallback == null) {
120 fallback = def.findFirstToken(TokenTypes.IDENT);
121 }
122 result = fallback;
123 } else {
124 result = child;
125 }
126 return result;
127 }
128
129 private static DetailAST tail(final DetailAST def) {
130 DetailAST end = def.findFirstToken(TokenTypes.SLIST);
131 if (end == null) {
132 end = def.findFirstToken(TokenTypes.SEMI);
133 }
134 return end;
135 }
136 }