| 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 com.puppycrawl.tools.checkstyle.StatelessCheck; | |
| 23 | import com.puppycrawl.tools.checkstyle.api.AbstractCheck; | |
| 24 | import com.puppycrawl.tools.checkstyle.api.DetailAST; | |
| 25 | import com.puppycrawl.tools.checkstyle.api.TokenTypes; | |
| 26 | ||
| 27 | /** | |
| 28 | * <p> | |
| 29 | * Checks that the clone method is not overridden from the | |
| 30 | * Object class. | |
| 31 | * </p> | |
| 32 | * | |
| 33 | * <p>Rationale: The clone method relies on strange/hard to follow rules that | |
| 34 | * do not work it all situations. Consequently, it is difficult to | |
| 35 | * override correctly. Below are some of the rules/reasons why the clone | |
| 36 | * method should be avoided. | |
| 37 | * | |
| 38 | * <ul> | |
| 39 | * <li> | |
| 40 | * Classes supporting the clone method should implement the Cloneable | |
| 41 | * interface but the Cloneable interface does not include the clone method. | |
| 42 | * As a result, it doesn't enforce the method override. | |
| 43 | * </li> | |
| 44 | * <li> | |
| 45 | * The Cloneable interface forces the Object's clone method to work | |
| 46 | * correctly. Without implementing it, the Object's clone method will | |
| 47 | * throw a CloneNotSupportedException. | |
| 48 | * </li> | |
| 49 | * <li> | |
| 50 | * Non-final classes must return the object returned from a call to | |
| 51 | * super.clone(). | |
| 52 | * </li> | |
| 53 | * <li> | |
| 54 | * Final classes can use a constructor to create a clone which is different | |
| 55 | * from non-final classes. | |
| 56 | * </li> | |
| 57 | * <li> | |
| 58 | * If a super class implements the clone method incorrectly all subclasses | |
| 59 | * calling super.clone() are doomed to failure. | |
| 60 | * </li> | |
| 61 | * <li> | |
| 62 | * If a class has references to mutable objects then those object | |
| 63 | * references must be replaced with copies in the clone method | |
| 64 | * after calling super.clone(). | |
| 65 | * </li> | |
| 66 | * <li> | |
| 67 | * The clone method does not work correctly with final mutable object | |
| 68 | * references because final references cannot be reassigned. | |
| 69 | * </li> | |
| 70 | * <li> | |
| 71 | * If a super class overrides the clone method then all subclasses must | |
| 72 | * provide a correct clone implementation. | |
| 73 | * </li> | |
| 74 | * </ul> | |
| 75 | * | |
| 76 | * <p>Two alternatives to the clone method, in some cases, is a copy constructor | |
| 77 | * or a static factory method to return copies of an object. Both of these | |
| 78 | * approaches are simpler and do not conflict with final fields. They do not | |
| 79 | * force the calling client to handle a CloneNotSupportedException. They also | |
| 80 | * are typed therefore no casting is necessary. Finally, they are more | |
| 81 | * flexible since they can take interface types rather than concrete classes. | |
| 82 | * | |
| 83 | * <p>Sometimes a copy constructor or static factory is not an acceptable | |
| 84 | * alternative to the clone method. The example below highlights the | |
| 85 | * limitation of a copy constructor (or static factory). Assume | |
| 86 | * Square is a subclass for Shape. | |
| 87 | * | |
| 88 | * <pre> | |
| 89 | * Shape s1 = new Square(); | |
| 90 | * System.out.println(s1 instanceof Square); //true | |
| 91 | * </pre> | |
| 92 | * ...assume at this point the code knows nothing of s1 being a Square | |
| 93 | * that's the beauty of polymorphism but the code wants to copy | |
| 94 | * the Square which is declared as a Shape, its super type... | |
| 95 | * | |
| 96 | * <pre> | |
| 97 | * Shape s2 = new Shape(s1); //using the copy constructor | |
| 98 | * System.out.println(s2 instanceof Square); //false | |
| 99 | * </pre> | |
| 100 | * The working solution (without knowing about all subclasses and doing many | |
| 101 | * casts) is to do the following (assuming correct clone implementation). | |
| 102 | * | |
| 103 | * <pre> | |
| 104 | * Shape s2 = s1.clone(); | |
| 105 | * System.out.println(s2 instanceof Square); //true | |
| 106 | * </pre> | |
| 107 | * Just keep in mind if this type of polymorphic cloning is required | |
| 108 | * then a properly implemented clone method may be the best choice. | |
| 109 | * | |
| 110 | * <p>Much of this information was taken from Effective Java: | |
| 111 | * Programming Language Guide First Edition by Joshua Bloch | |
| 112 | * pages 45-52. Give Bloch credit for writing an excellent book. | |
| 113 | * </p> | |
| 114 | * | |
| 115 | * <p>This check is almost exactly the same as the {@link NoFinalizerCheck} | |
| 116 | * | |
| 117 | * @author Travis Schneeberger | |
| 118 | * @see Object#clone() | |
| 119 | */ | |
| 120 | @StatelessCheck | |
| 121 | public class NoCloneCheck extends AbstractCheck { | |
| 122 | ||
| 123 | /** | |
| 124 | * A key is pointing to the warning message text in "messages.properties" | |
| 125 | * file. | |
| 126 | */ | |
| 127 | public static final String MSG_KEY = "avoid.clone.method"; | |
| 128 | ||
| 129 | @Override | |
| 130 | public int[] getDefaultTokens() { | |
| 131 |
1
1. getDefaultTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/coding/NoCloneCheck::getDefaultTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED |
return getRequiredTokens(); |
| 132 | } | |
| 133 | ||
| 134 | @Override | |
| 135 | public int[] getAcceptableTokens() { | |
| 136 |
1
1. getAcceptableTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/coding/NoCloneCheck::getAcceptableTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED |
return getRequiredTokens(); |
| 137 | } | |
| 138 | ||
| 139 | @Override | |
| 140 | public int[] getRequiredTokens() { | |
| 141 |
1
1. getRequiredTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/coding/NoCloneCheck::getRequiredTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED |
return new int[] {TokenTypes.METHOD_DEF}; |
| 142 | } | |
| 143 | ||
| 144 | @Override | |
| 145 | public void visitToken(DetailAST aAST) { | |
| 146 | final DetailAST mid = aAST.findFirstToken(TokenTypes.IDENT); | |
| 147 | final String name = mid.getText(); | |
| 148 | ||
| 149 |
1
1. visitToken : negated conditional → KILLED |
if ("clone".equals(name)) { |
| 150 | final DetailAST params = aAST.findFirstToken(TokenTypes.PARAMETERS); | |
| 151 | final boolean hasEmptyParamList = | |
| 152 |
1
1. visitToken : negated conditional → KILLED |
params.findFirstToken(TokenTypes.PARAMETER_DEF) == null; |
| 153 | ||
| 154 |
1
1. visitToken : negated conditional → KILLED |
if (hasEmptyParamList) { |
| 155 |
1
1. visitToken : removed call to com/puppycrawl/tools/checkstyle/checks/coding/NoCloneCheck::log → KILLED |
log(aAST.getLineNo(), MSG_KEY); |
| 156 | } | |
| 157 | } | |
| 158 | } | |
| 159 | ||
| 160 | } | |
Mutations | ||
| 131 |
1.1 |
|
| 136 |
1.1 |
|
| 141 |
1.1 |
|
| 149 |
1.1 |
|
| 152 |
1.1 |
|
| 154 |
1.1 |
|
| 155 |
1.1 |