1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package com.puppycrawl.tools.checkstyle.checks.metrics;
20
21 import java.math.BigInteger;
22
23 import com.puppycrawl.tools.checkstyle.api.DetailAST;
24 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
25
26
27
28
29
30
31
32
33
34
35
36
37
38 public final class NPathComplexityCheck extends AbstractComplexityCheck
39 {
40
41
42
43
44
45 public static final String MSG_KEY = "npathComplexity";
46
47
48 private static final int DEFAULT_MAX = 200;
49
50
51 public NPathComplexityCheck()
52 {
53 super(DEFAULT_MAX);
54 }
55
56 @Override
57 public int[] getDefaultTokens()
58 {
59 return new int[] {
60 TokenTypes.CTOR_DEF,
61 TokenTypes.METHOD_DEF,
62 TokenTypes.STATIC_INIT,
63 TokenTypes.INSTANCE_INIT,
64 TokenTypes.LITERAL_WHILE,
65 TokenTypes.LITERAL_DO,
66 TokenTypes.LITERAL_FOR,
67 TokenTypes.LITERAL_IF,
68 TokenTypes.LITERAL_ELSE,
69 TokenTypes.LITERAL_SWITCH,
70 TokenTypes.LITERAL_CASE,
71 TokenTypes.LITERAL_TRY,
72 TokenTypes.LITERAL_CATCH,
73 TokenTypes.QUESTION,
74 };
75 }
76
77 @Override
78 public int[] getAcceptableTokens()
79 {
80 return new int[] {
81 TokenTypes.CTOR_DEF,
82 TokenTypes.METHOD_DEF,
83 TokenTypes.STATIC_INIT,
84 TokenTypes.INSTANCE_INIT,
85 TokenTypes.LITERAL_WHILE,
86 TokenTypes.LITERAL_DO,
87 TokenTypes.LITERAL_FOR,
88 TokenTypes.LITERAL_IF,
89 TokenTypes.LITERAL_ELSE,
90 TokenTypes.LITERAL_SWITCH,
91 TokenTypes.LITERAL_CASE,
92 TokenTypes.LITERAL_TRY,
93 TokenTypes.LITERAL_CATCH,
94 TokenTypes.QUESTION,
95 };
96 }
97
98 @Override
99 public void visitToken(DetailAST ast)
100 {
101 switch (ast.getType()) {
102 case TokenTypes.LITERAL_WHILE:
103 case TokenTypes.LITERAL_DO:
104 case TokenTypes.LITERAL_FOR:
105 case TokenTypes.LITERAL_IF:
106 case TokenTypes.QUESTION:
107 case TokenTypes.LITERAL_TRY:
108 case TokenTypes.LITERAL_SWITCH:
109 visitMultiplyingConditional();
110 break;
111 case TokenTypes.LITERAL_ELSE:
112 case TokenTypes.LITERAL_CATCH:
113 case TokenTypes.LITERAL_CASE:
114 visitAddingConditional();
115 break;
116 default:
117 super.visitToken(ast);
118 }
119 }
120
121 @Override
122 public void leaveToken(DetailAST ast)
123 {
124 switch (ast.getType()) {
125 case TokenTypes.LITERAL_WHILE:
126 case TokenTypes.LITERAL_DO:
127 case TokenTypes.LITERAL_FOR:
128 case TokenTypes.LITERAL_IF:
129 case TokenTypes.QUESTION:
130 case TokenTypes.LITERAL_TRY:
131 case TokenTypes.LITERAL_SWITCH:
132 leaveMultiplyingConditional();
133 break;
134 case TokenTypes.LITERAL_ELSE:
135 case TokenTypes.LITERAL_CATCH:
136 case TokenTypes.LITERAL_CASE:
137 leaveAddingConditional();
138 break;
139 default:
140 super.leaveToken(ast);
141 }
142 }
143
144 @Override
145 protected String getMessageID()
146 {
147 return MSG_KEY;
148 }
149
150
151 private void visitAddingConditional()
152 {
153 pushValue();
154 }
155
156
157 private void leaveAddingConditional()
158 {
159 setCurrentValue(
160 getCurrentValue().subtract(BigInteger.ONE).add(popValue()));
161 }
162
163
164 private void visitMultiplyingConditional()
165 {
166 pushValue();
167 }
168
169
170 private void leaveMultiplyingConditional()
171 {
172 setCurrentValue(
173 getCurrentValue().add(BigInteger.ONE).multiply(popValue()));
174 }
175 }