1 | //////////////////////////////////////////////////////////////////////////////// | |
2 | // checkstyle: Checks Java source code for adherence to a set of rules. | |
3 | // Copyright (C) 2001-2018 the original author or authors. | |
4 | // | |
5 | // This library is free software; you can redistribute it and/or | |
6 | // modify it under the terms of the GNU Lesser General Public | |
7 | // License as published by the Free Software Foundation; either | |
8 | // version 2.1 of the License, or (at your option) any later version. | |
9 | // | |
10 | // This library is distributed in the hope that it will be useful, | |
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | // Lesser General Public License for more details. | |
14 | // | |
15 | // You should have received a copy of the GNU Lesser General Public | |
16 | // License along with this library; if not, write to the Free Software | |
17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 | //////////////////////////////////////////////////////////////////////////////// | |
19 | ||
20 | package com.puppycrawl.tools.checkstyle.checks.coding; | |
21 | ||
22 | import java.util.Arrays; | |
23 | ||
24 | import com.puppycrawl.tools.checkstyle.StatelessCheck; | |
25 | import com.puppycrawl.tools.checkstyle.api.AbstractCheck; | |
26 | import com.puppycrawl.tools.checkstyle.api.DetailAST; | |
27 | import com.puppycrawl.tools.checkstyle.api.TokenTypes; | |
28 | import com.puppycrawl.tools.checkstyle.utils.CheckUtils; | |
29 | import com.puppycrawl.tools.checkstyle.utils.CommonUtils; | |
30 | import com.puppycrawl.tools.checkstyle.utils.ScopeUtils; | |
31 | import com.puppycrawl.tools.checkstyle.utils.TokenUtils; | |
32 | ||
33 | /** | |
34 | * <p> | |
35 | * Checks that there are no <a href="https://en.wikipedia.org/wiki/Magic_number_%28programming%29"> | |
36 | * "magic numbers"</a> where a magic | |
37 | * number is a numeric literal that is not defined as a constant. | |
38 | * By default, -1, 0, 1, and 2 are not considered to be magic numbers. | |
39 | * </p> | |
40 | * | |
41 | * <p>Constant definition is any variable/field that has 'final' modifier. | |
42 | * It is fine to have one constant defining multiple numeric literals within one expression: | |
43 | * <pre> | |
44 | * {@code static final int SECONDS_PER_DAY = 24 * 60 * 60; | |
45 | * static final double SPECIAL_RATIO = 4.0 / 3.0; | |
46 | * static final double SPECIAL_SUM = 1 + Math.E; | |
47 | * static final double SPECIAL_DIFFERENCE = 4 - Math.PI; | |
48 | * static final Border STANDARD_BORDER = BorderFactory.createEmptyBorder(3, 3, 3, 3); | |
49 | * static final Integer ANSWER_TO_THE_ULTIMATE_QUESTION_OF_LIFE = new Integer(42);} | |
50 | * </pre> | |
51 | * | |
52 | * <p>Check have following options: | |
53 | * ignoreHashCodeMethod - ignore magic numbers in hashCode methods; | |
54 | * ignoreAnnotation - ignore magic numbers in annotation declarations; | |
55 | * ignoreFieldDeclaration - ignore magic numbers in field declarations. | |
56 | * <p> | |
57 | * To configure the check with default configuration: | |
58 | * </p> | |
59 | * <pre> | |
60 | * <module name="MagicNumber"/> | |
61 | * </pre> | |
62 | * <p> | |
63 | * results is following violations: | |
64 | * </p> | |
65 | * <pre> | |
66 | * {@code | |
67 | * {@literal @}MyAnnotation(6) // violation | |
68 | * class MyClass { | |
69 | * private field = 7; // violation | |
70 | * | |
71 | * void foo() { | |
72 | * int i = i + 1; // no violation | |
73 | * int j = j + 8; // violation | |
74 | * } | |
75 | * } | |
76 | * } | |
77 | * </pre> | |
78 | * <p> | |
79 | * To configure the check so that it checks floating-point numbers | |
80 | * that are not 0, 0.5, or 1: | |
81 | * </p> | |
82 | * <pre> | |
83 | * <module name="MagicNumber"> | |
84 | * <property name="tokens" value="NUM_DOUBLE, NUM_FLOAT"/> | |
85 | * <property name="ignoreNumbers" value="0, 0.5, 1"/> | |
86 | * <property name="ignoreFieldDeclaration" value="true"/> | |
87 | * <property name="ignoreAnnotation" value="true"/> | |
88 | * </module> | |
89 | * </pre> | |
90 | * <p> | |
91 | * results is following violations: | |
92 | * </p> | |
93 | * <pre> | |
94 | * {@code | |
95 | * {@literal @}MyAnnotation(6) // no violation | |
96 | * class MyClass { | |
97 | * private field = 7; // no violation | |
98 | * | |
99 | * void foo() { | |
100 | * int i = i + 1; // no violation | |
101 | * int j = j + (int)0.5; // no violation | |
102 | * } | |
103 | * } | |
104 | * } | |
105 | * </pre> | |
106 | * <p> | |
107 | * Config example of constantWaiverParentToken option: | |
108 | * </p> | |
109 | * <pre> | |
110 | * <module name="MagicNumber"> | |
111 | * <property name="constantWaiverParentToken" value="ASSIGN,ARRAY_INIT,EXPR, | |
112 | * UNARY_PLUS, UNARY_MINUS, TYPECAST, ELIST, DIV, PLUS "/> | |
113 | * </module> | |
114 | * </pre> | |
115 | * <p> | |
116 | * result is following violation: | |
117 | * </p> | |
118 | * <pre> | |
119 | * {@code | |
120 | * class TestMethodCall { | |
121 | * public void method2() { | |
122 | * final TestMethodCall dummyObject = new TestMethodCall(62); //violation | |
123 | * final int a = 3; // ok as waiver is ASSIGN | |
124 | * final int [] b = {4, 5} // ok as waiver is ARRAY_INIT | |
125 | * final int c = -3; // ok as waiver is UNARY_MINUS | |
126 | * final int d = +4; // ok as waiver is UNARY_PLUS | |
127 | * final int e = method(1, 2) // ELIST is there but violation due to METHOD_CALL | |
128 | * final int x = 3 * 4; // violation | |
129 | * final int y = 3 / 4; // ok as waiver is DIV | |
130 | * final int z = 3 + 4; // ok as waiver is PLUS | |
131 | * final int w = 3 - 4; // violation | |
132 | * final int x = (int)(3.4); //ok as waiver is TYPECAST | |
133 | * } | |
134 | * } | |
135 | * } | |
136 | * </pre> | |
137 | * @author Rick Giles | |
138 | * @author Lars Kühne | |
139 | * @author Daniel Solano Gómez | |
140 | */ | |
141 | @StatelessCheck | |
142 | public class MagicNumberCheck extends AbstractCheck { | |
143 | ||
144 | /** | |
145 | * A key is pointing to the warning message text in "messages.properties" | |
146 | * file. | |
147 | */ | |
148 | public static final String MSG_KEY = "magic.number"; | |
149 | ||
150 | /** | |
151 | * The token types that are allowed in the AST path from the | |
152 | * number literal to the enclosing constant definition. | |
153 | */ | |
154 | private int[] constantWaiverParentToken = { | |
155 | TokenTypes.ASSIGN, | |
156 | TokenTypes.ARRAY_INIT, | |
157 | TokenTypes.EXPR, | |
158 | TokenTypes.UNARY_PLUS, | |
159 | TokenTypes.UNARY_MINUS, | |
160 | TokenTypes.TYPECAST, | |
161 | TokenTypes.ELIST, | |
162 | TokenTypes.LITERAL_NEW, | |
163 | TokenTypes.METHOD_CALL, | |
164 | TokenTypes.STAR, | |
165 | TokenTypes.DIV, | |
166 | TokenTypes.PLUS, | |
167 | TokenTypes.MINUS, | |
168 | }; | |
169 | ||
170 | /** The numbers to ignore in the check, sorted. */ | |
171 | private double[] ignoreNumbers = {-1, 0, 1, 2}; | |
172 | ||
173 | /** Whether to ignore magic numbers in a hash code method. */ | |
174 | private boolean ignoreHashCodeMethod; | |
175 | ||
176 | /** Whether to ignore magic numbers in annotation. */ | |
177 | private boolean ignoreAnnotation; | |
178 | ||
179 | /** Whether to ignore magic numbers in field declaration. */ | |
180 | private boolean ignoreFieldDeclaration; | |
181 | ||
182 | /** | |
183 | * Constructor for MagicNumber Check. | |
184 | * Sort the allowedTokensBetweenMagicNumberAndConstDef array for binary search. | |
185 | */ | |
186 | public MagicNumberCheck() { | |
187 |
1
1. |
Arrays.sort(constantWaiverParentToken); |
188 | } | |
189 | ||
190 | @Override | |
191 | public int[] getDefaultTokens() { | |
192 |
1
1. getDefaultTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/coding/MagicNumberCheck::getDefaultTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED |
return getAcceptableTokens(); |
193 | } | |
194 | ||
195 | @Override | |
196 | public int[] getAcceptableTokens() { | |
197 |
1
1. getAcceptableTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/coding/MagicNumberCheck::getAcceptableTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED |
return new int[] { |
198 | TokenTypes.NUM_DOUBLE, | |
199 | TokenTypes.NUM_FLOAT, | |
200 | TokenTypes.NUM_INT, | |
201 | TokenTypes.NUM_LONG, | |
202 | }; | |
203 | } | |
204 | ||
205 | @Override | |
206 | public int[] getRequiredTokens() { | |
207 |
1
1. getRequiredTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/coding/MagicNumberCheck::getRequiredTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED |
return CommonUtils.EMPTY_INT_ARRAY; |
208 | } | |
209 | ||
210 | @Override | |
211 | public void visitToken(DetailAST ast) { | |
212 |
2
1. visitToken : negated conditional → KILLED 2. visitToken : negated conditional → KILLED |
if ((!ignoreAnnotation || !isChildOf(ast, TokenTypes.ANNOTATION)) |
213 |
2
1. visitToken : negated conditional → KILLED 2. visitToken : negated conditional → KILLED |
&& !isInIgnoreList(ast) |
214 |
1
1. visitToken : negated conditional → KILLED |
&& (!ignoreHashCodeMethod || !isInHashCodeMethod(ast))) { |
215 | final DetailAST constantDefAST = findContainingConstantDef(ast); | |
216 | ||
217 |
1
1. visitToken : negated conditional → KILLED |
if (constantDefAST == null) { |
218 |
2
1. visitToken : negated conditional → KILLED 2. visitToken : negated conditional → KILLED |
if (!ignoreFieldDeclaration || !isFieldDeclaration(ast)) { |
219 |
1
1. visitToken : removed call to com/puppycrawl/tools/checkstyle/checks/coding/MagicNumberCheck::reportMagicNumber → KILLED |
reportMagicNumber(ast); |
220 | } | |
221 | } | |
222 | else { | |
223 | final boolean found = isMagicNumberExists(ast, constantDefAST); | |
224 |
1
1. visitToken : negated conditional → KILLED |
if (found) { |
225 |
1
1. visitToken : removed call to com/puppycrawl/tools/checkstyle/checks/coding/MagicNumberCheck::reportMagicNumber → KILLED |
reportMagicNumber(ast); |
226 | } | |
227 | } | |
228 | } | |
229 | } | |
230 | ||
231 | /** | |
232 | * Is magic number some where at ast tree. | |
233 | * @param ast ast token | |
234 | * @param constantDefAST constant ast | |
235 | * @return true if magic number is present | |
236 | */ | |
237 | private boolean isMagicNumberExists(DetailAST ast, DetailAST constantDefAST) { | |
238 | boolean found = false; | |
239 | DetailAST astNode = ast.getParent(); | |
240 |
1
1. isMagicNumberExists : negated conditional → KILLED |
while (astNode != constantDefAST) { |
241 | final int type = astNode.getType(); | |
242 |
2
1. isMagicNumberExists : changed conditional boundary → KILLED 2. isMagicNumberExists : negated conditional → KILLED |
if (Arrays.binarySearch(constantWaiverParentToken, type) < 0) { |
243 | found = true; | |
244 | break; | |
245 | } | |
246 | astNode = astNode.getParent(); | |
247 | } | |
248 |
1
1. isMagicNumberExists : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return found; |
249 | } | |
250 | ||
251 | /** | |
252 | * Finds the constant definition that contains aAST. | |
253 | * @param ast the AST | |
254 | * @return the constant def or null if ast is not contained in a constant definition. | |
255 | */ | |
256 | private static DetailAST findContainingConstantDef(DetailAST ast) { | |
257 | DetailAST varDefAST = ast; | |
258 |
1
1. findContainingConstantDef : negated conditional → KILLED |
while (varDefAST != null |
259 |
1
1. findContainingConstantDef : negated conditional → KILLED |
&& varDefAST.getType() != TokenTypes.VARIABLE_DEF |
260 |
1
1. findContainingConstantDef : negated conditional → KILLED |
&& varDefAST.getType() != TokenTypes.ENUM_CONSTANT_DEF) { |
261 | varDefAST = varDefAST.getParent(); | |
262 | } | |
263 | DetailAST constantDef = null; | |
264 | ||
265 | // no containing variable definition? | |
266 |
1
1. findContainingConstantDef : negated conditional → KILLED |
if (varDefAST != null) { |
267 | // implicit constant? | |
268 |
1
1. findContainingConstantDef : negated conditional → KILLED |
if (ScopeUtils.isInInterfaceOrAnnotationBlock(varDefAST) |
269 |
1
1. findContainingConstantDef : negated conditional → KILLED |
|| varDefAST.getType() == TokenTypes.ENUM_CONSTANT_DEF) { |
270 | constantDef = varDefAST; | |
271 | } | |
272 | else { | |
273 | // explicit constant | |
274 | final DetailAST modifiersAST = varDefAST.findFirstToken(TokenTypes.MODIFIERS); | |
275 | ||
276 |
1
1. findContainingConstantDef : negated conditional → KILLED |
if (modifiersAST.findFirstToken(TokenTypes.FINAL) != null) { |
277 | constantDef = varDefAST; | |
278 | } | |
279 | } | |
280 | } | |
281 |
1
1. findContainingConstantDef : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/coding/MagicNumberCheck::findContainingConstantDef to ( if (x != null) null else throw new RuntimeException ) → KILLED |
return constantDef; |
282 | } | |
283 | ||
284 | /** | |
285 | * Reports aAST as a magic number, includes unary operators as needed. | |
286 | * @param ast the AST node that contains the number to report | |
287 | */ | |
288 | private void reportMagicNumber(DetailAST ast) { | |
289 | String text = ast.getText(); | |
290 | final DetailAST parent = ast.getParent(); | |
291 | DetailAST reportAST = ast; | |
292 |
1
1. reportMagicNumber : negated conditional → KILLED |
if (parent.getType() == TokenTypes.UNARY_MINUS) { |
293 | reportAST = parent; | |
294 | text = "-" + text; | |
295 | } | |
296 |
1
1. reportMagicNumber : negated conditional → KILLED |
else if (parent.getType() == TokenTypes.UNARY_PLUS) { |
297 | reportAST = parent; | |
298 | text = "+" + text; | |
299 | } | |
300 |
1
1. reportMagicNumber : removed call to com/puppycrawl/tools/checkstyle/checks/coding/MagicNumberCheck::log → KILLED |
log(reportAST.getLineNo(), |
301 | reportAST.getColumnNo(), | |
302 | MSG_KEY, | |
303 | text); | |
304 | } | |
305 | ||
306 | /** | |
307 | * Determines whether or not the given AST is in a valid hash code method. | |
308 | * A valid hash code method is considered to be a method of the signature | |
309 | * {@code public int hashCode()}. | |
310 | * | |
311 | * @param ast the AST from which to search for an enclosing hash code | |
312 | * method definition | |
313 | * | |
314 | * @return {@code true} if {@code ast} is in the scope of a valid hash code method. | |
315 | */ | |
316 | private static boolean isInHashCodeMethod(DetailAST ast) { | |
317 | boolean inHashCodeMethod = false; | |
318 | ||
319 | // if not in a code block, can't be in hashCode() | |
320 |
1
1. isInHashCodeMethod : negated conditional → KILLED |
if (ScopeUtils.isInCodeBlock(ast)) { |
321 | // find the method definition AST | |
322 | DetailAST methodDefAST = ast.getParent(); | |
323 |
1
1. isInHashCodeMethod : negated conditional → KILLED |
while (methodDefAST != null |
324 |
1
1. isInHashCodeMethod : negated conditional → KILLED |
&& methodDefAST.getType() != TokenTypes.METHOD_DEF) { |
325 | methodDefAST = methodDefAST.getParent(); | |
326 | } | |
327 | ||
328 |
1
1. isInHashCodeMethod : negated conditional → KILLED |
if (methodDefAST != null) { |
329 | // Check for 'hashCode' name. | |
330 | final DetailAST identAST = methodDefAST.findFirstToken(TokenTypes.IDENT); | |
331 | ||
332 |
1
1. isInHashCodeMethod : negated conditional → KILLED |
if ("hashCode".equals(identAST.getText())) { |
333 | // Check for no arguments. | |
334 | final DetailAST paramAST = methodDefAST.findFirstToken(TokenTypes.PARAMETERS); | |
335 | // we are in a 'public int hashCode()' method! The compiler will ensure | |
336 | // the method returns an 'int' and is public. | |
337 |
1
1. isInHashCodeMethod : negated conditional → KILLED |
inHashCodeMethod = paramAST.getChildCount() == 0; |
338 | } | |
339 | } | |
340 | } | |
341 |
1
1. isInHashCodeMethod : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return inHashCodeMethod; |
342 | } | |
343 | ||
344 | /** | |
345 | * Decides whether the number of an AST is in the ignore list of this | |
346 | * check. | |
347 | * @param ast the AST to check | |
348 | * @return true if the number of ast is in the ignore list of this check. | |
349 | */ | |
350 | private boolean isInIgnoreList(DetailAST ast) { | |
351 | double value = CheckUtils.parseDouble(ast.getText(), ast.getType()); | |
352 | final DetailAST parent = ast.getParent(); | |
353 |
1
1. isInIgnoreList : negated conditional → KILLED |
if (parent.getType() == TokenTypes.UNARY_MINUS) { |
354 |
1
1. isInIgnoreList : Replaced double multiplication with division → KILLED |
value = -1 * value; |
355 | } | |
356 |
3
1. isInIgnoreList : changed conditional boundary → KILLED 2. isInIgnoreList : negated conditional → KILLED 3. isInIgnoreList : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return Arrays.binarySearch(ignoreNumbers, value) >= 0; |
357 | } | |
358 | ||
359 | /** | |
360 | * Determines whether or not the given AST is field declaration. | |
361 | * | |
362 | * @param ast AST from which to search for an enclosing field declaration | |
363 | * | |
364 | * @return {@code true} if {@code ast} is in the scope of field declaration | |
365 | */ | |
366 | private static boolean isFieldDeclaration(DetailAST ast) { | |
367 | DetailAST varDefAST = ast; | |
368 |
1
1. isFieldDeclaration : negated conditional → KILLED |
while (varDefAST != null |
369 |
1
1. isFieldDeclaration : negated conditional → KILLED |
&& varDefAST.getType() != TokenTypes.VARIABLE_DEF) { |
370 | varDefAST = varDefAST.getParent(); | |
371 | } | |
372 | ||
373 | // contains variable declaration | |
374 | // and it is directly inside class declaration | |
375 |
2
1. isFieldDeclaration : negated conditional → KILLED 2. isFieldDeclaration : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return varDefAST != null |
376 |
1
1. isFieldDeclaration : negated conditional → KILLED |
&& varDefAST.getParent().getParent().getType() == TokenTypes.CLASS_DEF; |
377 | } | |
378 | ||
379 | /** | |
380 | * Sets the tokens which are allowed between Magic Number and defined Object. | |
381 | * @param tokens The string representation of the tokens interested in | |
382 | */ | |
383 | public void setConstantWaiverParentToken(String... tokens) { | |
384 | constantWaiverParentToken = new int[tokens.length]; | |
385 |
2
1. setConstantWaiverParentToken : changed conditional boundary → KILLED 2. setConstantWaiverParentToken : negated conditional → KILLED |
for (int i = 0; i < tokens.length; i++) { |
386 | constantWaiverParentToken[i] = TokenUtils.getTokenId(tokens[i]); | |
387 | } | |
388 |
1
1. setConstantWaiverParentToken : removed call to java/util/Arrays::sort → KILLED |
Arrays.sort(constantWaiverParentToken); |
389 | } | |
390 | ||
391 | /** | |
392 | * Sets the numbers to ignore in the check. | |
393 | * BeanUtils converts numeric token list to double array automatically. | |
394 | * @param list list of numbers to ignore. | |
395 | */ | |
396 | public void setIgnoreNumbers(double... list) { | |
397 |
1
1. setIgnoreNumbers : negated conditional → KILLED |
if (list.length == 0) { |
398 | ignoreNumbers = CommonUtils.EMPTY_DOUBLE_ARRAY; | |
399 | } | |
400 | else { | |
401 | ignoreNumbers = new double[list.length]; | |
402 |
1
1. setIgnoreNumbers : removed call to java/lang/System::arraycopy → KILLED |
System.arraycopy(list, 0, ignoreNumbers, 0, list.length); |
403 |
1
1. setIgnoreNumbers : removed call to java/util/Arrays::sort → KILLED |
Arrays.sort(ignoreNumbers); |
404 | } | |
405 | } | |
406 | ||
407 | /** | |
408 | * Set whether to ignore hashCode methods. | |
409 | * @param ignoreHashCodeMethod decide whether to ignore | |
410 | * hash code methods | |
411 | */ | |
412 | public void setIgnoreHashCodeMethod(boolean ignoreHashCodeMethod) { | |
413 | this.ignoreHashCodeMethod = ignoreHashCodeMethod; | |
414 | } | |
415 | ||
416 | /** | |
417 | * Set whether to ignore Annotations. | |
418 | * @param ignoreAnnotation decide whether to ignore annotations | |
419 | */ | |
420 | public void setIgnoreAnnotation(boolean ignoreAnnotation) { | |
421 | this.ignoreAnnotation = ignoreAnnotation; | |
422 | } | |
423 | ||
424 | /** | |
425 | * Set whether to ignore magic numbers in field declaration. | |
426 | * @param ignoreFieldDeclaration decide whether to ignore magic numbers | |
427 | * in field declaration | |
428 | */ | |
429 | public void setIgnoreFieldDeclaration(boolean ignoreFieldDeclaration) { | |
430 | this.ignoreFieldDeclaration = ignoreFieldDeclaration; | |
431 | } | |
432 | ||
433 | /** | |
434 | * Determines if the given AST node has a parent node with given token type code. | |
435 | * | |
436 | * @param ast the AST from which to search for annotations | |
437 | * @param type the type code of parent token | |
438 | * | |
439 | * @return {@code true} if the AST node has a parent with given token type. | |
440 | */ | |
441 | private static boolean isChildOf(DetailAST ast, int type) { | |
442 | boolean result = false; | |
443 | DetailAST node = ast; | |
444 | do { | |
445 |
1
1. isChildOf : negated conditional → KILLED |
if (node.getType() == type) { |
446 | result = true; | |
447 | break; | |
448 | } | |
449 | node = node.getParent(); | |
450 |
1
1. isChildOf : negated conditional → KILLED |
} while (node != null); |
451 | ||
452 |
1
1. isChildOf : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return result; |
453 | } | |
454 | ||
455 | } | |
Mutations | ||
187 |
1.1 |
|
192 |
1.1 |
|
197 |
1.1 |
|
207 |
1.1 |
|
212 |
1.1 2.2 |
|
213 |
1.1 2.2 |
|
214 |
1.1 |
|
217 |
1.1 |
|
218 |
1.1 2.2 |
|
219 |
1.1 |
|
224 |
1.1 |
|
225 |
1.1 |
|
240 |
1.1 |
|
242 |
1.1 2.2 |
|
248 |
1.1 |
|
258 |
1.1 |
|
259 |
1.1 |
|
260 |
1.1 |
|
266 |
1.1 |
|
268 |
1.1 |
|
269 |
1.1 |
|
276 |
1.1 |
|
281 |
1.1 |
|
292 |
1.1 |
|
296 |
1.1 |
|
300 |
1.1 |
|
320 |
1.1 |
|
323 |
1.1 |
|
324 |
1.1 |
|
328 |
1.1 |
|
332 |
1.1 |
|
337 |
1.1 |
|
341 |
1.1 |
|
353 |
1.1 |
|
354 |
1.1 |
|
356 |
1.1 2.2 3.3 |
|
368 |
1.1 |
|
369 |
1.1 |
|
375 |
1.1 2.2 |
|
376 |
1.1 |
|
385 |
1.1 2.2 |
|
388 |
1.1 |
|
397 |
1.1 |
|
402 |
1.1 |
|
403 |
1.1 |
|
445 |
1.1 |
|
450 |
1.1 |
|
452 |
1.1 |