001///////////////////////////////////////////////////////////////////////////////////////////////
002// checkstyle: Checks Java source code and other text files for adherence to a set of rules.
003// Copyright (C) 2001-2024 the original author or authors.
004//
005// This library is free software; you can redistribute it and/or
006// modify it under the terms of the GNU Lesser General Public
007// License as published by the Free Software Foundation; either
008// version 2.1 of the License, or (at your option) any later version.
009//
010// This library is distributed in the hope that it will be useful,
011// but WITHOUT ANY WARRANTY; without even the implied warranty of
012// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013// Lesser General Public License for more details.
014//
015// You should have received a copy of the GNU Lesser General Public
016// License along with this library; if not, write to the Free Software
017// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
018///////////////////////////////////////////////////////////////////////////////////////////////
019
020package com.puppycrawl.tools.checkstyle.checks.coding;
021
022import com.puppycrawl.tools.checkstyle.StatelessCheck;
023import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
024import com.puppycrawl.tools.checkstyle.api.DetailAST;
025import com.puppycrawl.tools.checkstyle.api.TokenTypes;
026
027/**
028 * <div>
029 * Checks that the clone method is not overridden from the
030 * Object class.
031 * </div>
032 *
033 * <p>
034 * This check is almost exactly the same as the {@code NoFinalizerCheck}.
035 * </p>
036 *
037 * <p>
038 * See
039 * <a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Object.html#clone()">
040 * Object.clone()</a>
041 * </p>
042 *
043 * <p>
044 * Rationale: The clone method relies on strange, hard to follow rules that
045 * are difficult to get right and do not work in all situations. In some cases,
046 * either a copy constructor or a static factory method can be used instead of
047 * the clone method to return copies of an object. For more information on rules
048 * for the clone method and its issues, see Effective Java:
049 * Programming Language Guide First Edition by Joshua Bloch pages 45-52.
050 * </p>
051 *
052 * <p>
053 * Below are some rules/reasons why the clone method should be avoided.
054 * </p>
055 * <ul>
056 * <li>
057 * Classes supporting the clone method should implement the Cloneable
058 * interface but the Cloneable interface does not include the clone method.
059 * As a result, it doesn't enforce the method override.
060 * </li>
061 * <li>
062 * The Cloneable interface forces the Object's clone method to work
063 * correctly. Without implementing it, the Object's clone method will
064 * throw a CloneNotSupportedException.
065 * </li>
066 * <li>
067 * Non-final classes must return the object returned from a call to
068 * super.clone().
069 * </li>
070 * <li>
071 * Final classes can use a constructor to create a clone which is different
072 * from non-final classes.
073 * </li>
074 * <li>
075 * If a super class implements the clone method incorrectly all subclasses
076 * calling super.clone() are doomed to failure.
077 * </li>
078 * <li>
079 * If a class has references to mutable objects then those object
080 * references must be replaced with copies in the clone method
081 * after calling super.clone().
082 * </li>
083 * <li>
084 * The clone method does not work correctly with final mutable object
085 * references because final references cannot be reassigned.
086 * </li>
087 * <li>
088 * If a super class overrides the clone method then all subclasses must
089 * provide a correct clone implementation.
090 * </li>
091 * </ul>
092 *
093 * <p>Two alternatives to the clone method, in some cases, is a copy constructor
094 * or a static factory method to return copies of an object. Both of these
095 * approaches are simpler and do not conflict with final fields. They do not
096 * force the calling client to handle a CloneNotSupportedException.  They also
097 * are typed therefore no casting is necessary. Finally, they are more
098 * flexible since they can take interface types rather than concrete classes.
099 * </p>
100 *
101 * <p>Sometimes a copy constructor or static factory is not an acceptable
102 * alternative to the clone method.  The example below highlights the
103 * limitation of a copy constructor (or static factory). Assume
104 * Square is a subclass for Shape.
105 * </p>
106 * <pre>
107 * Shape s1 = new Square();
108 * System.out.println(s1 instanceof Square); //true
109 * </pre>
110 *
111 * <p>
112 * ...assume at this point the code knows nothing of s1 being a Square
113 *    that's the beauty of polymorphism but the code wants to copy
114 *    the Square which is declared as a Shape, its super type...
115 * </p>
116 * <pre>
117 * Shape s2 = new Shape(s1); //using the copy constructor
118 * System.out.println(s2 instanceof Square); //false
119 * </pre>
120 *
121 * <p>
122 * The working solution (without knowing about all subclasses and doing many
123 * casts) is to do the following (assuming correct clone implementation).
124 * </p>
125 * <pre>
126 * Shape s2 = s1.clone();
127 * System.out.println(s2 instanceof Square); //true
128 * </pre>
129 *
130 * <p>
131 * Just keep in mind if this type of polymorphic cloning is required
132 * then a properly implemented clone method may be the best choice.
133 * </p>
134 *
135 * <p>Much of this information was taken from Effective Java:
136 * Programming Language Guide First Edition by Joshua Bloch
137 * pages 45-52.  Give Bloch credit for writing an excellent book.
138 * </p>
139 *
140 * <p>
141 * Parent is {@code com.puppycrawl.tools.checkstyle.TreeWalker}
142 * </p>
143 *
144 * <p>
145 * Violation Message Keys:
146 * </p>
147 * <ul>
148 * <li>
149 * {@code avoid.clone.method}
150 * </li>
151 * </ul>
152 *
153 * @since 5.0
154 */
155@StatelessCheck
156public class NoCloneCheck extends AbstractCheck {
157
158    /**
159     * A key is pointing to the warning message text in "messages.properties"
160     * file.
161     */
162    public static final String MSG_KEY = "avoid.clone.method";
163
164    @Override
165    public int[] getDefaultTokens() {
166        return getRequiredTokens();
167    }
168
169    @Override
170    public int[] getAcceptableTokens() {
171        return getRequiredTokens();
172    }
173
174    @Override
175    public int[] getRequiredTokens() {
176        return new int[] {TokenTypes.METHOD_DEF};
177    }
178
179    @Override
180    public void visitToken(DetailAST ast) {
181        final DetailAST mid = ast.findFirstToken(TokenTypes.IDENT);
182        final String name = mid.getText();
183
184        if ("clone".equals(name)) {
185            final DetailAST params = ast.findFirstToken(TokenTypes.PARAMETERS);
186            final boolean hasEmptyParamList =
187                params.findFirstToken(TokenTypes.PARAMETER_DEF) == null;
188
189            if (hasEmptyParamList) {
190                log(ast, MSG_KEY);
191            }
192        }
193    }
194
195}