diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml index fdb98efa8491..fe80d85060a5 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml @@ -578,6 +578,10 @@ key="non.public.clone.display.name" groupBundle="messages.InspectionsBundle" groupKey="group.names.cloning.issues" enabledByDefault="false" level="WARNING" implementationClass="com.siyeh.ig.cloneable.NonPublicCloneInspection"/> + #ref() +use.of.clone.call.method.problem.descriptor=Implementation of #ref() +use.of.clone.reference.problem.descriptor=Use of #ref diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/cloneable/UseOfCloneInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/cloneable/UseOfCloneInspection.java new file mode 100644 index 000000000000..9d9f349dbf84 --- /dev/null +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/cloneable/UseOfCloneInspection.java @@ -0,0 +1,100 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.siyeh.ig.cloneable; + +import com.intellij.psi.*; +import com.siyeh.HardcodedMethodConstants; +import com.siyeh.InspectionGadgetsBundle; +import com.siyeh.ig.BaseInspection; +import com.siyeh.ig.BaseInspectionVisitor; +import com.siyeh.ig.psiutils.CloneUtils; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NotNull; + +/** + * @author Bas Leijdekkers + */ +public class UseOfCloneInspection extends BaseInspection { + + @Nls + @NotNull + @Override + public String getDisplayName() { + return InspectionGadgetsBundle.message("use.of.clone.display.name"); + } + + @NotNull + @Override + protected String buildErrorString(Object... infos) { + final Object errorElement = infos[0]; + if (errorElement instanceof PsiMethodCallExpression) { + return InspectionGadgetsBundle.message("use.of.clone.call.problem.descriptor"); + } + else if (errorElement instanceof PsiMethod) { + return InspectionGadgetsBundle.message("use.of.clone.call.method.problem.descriptor"); + } + else { + return InspectionGadgetsBundle.message("use.of.clone.reference.problem.descriptor"); + } + } + + @Override + public BaseInspectionVisitor buildVisitor() { + return new UseOfCloneVisitor(); + } + + private static class UseOfCloneVisitor extends BaseInspectionVisitor { + + @Override + public void visitMethodCallExpression(PsiMethodCallExpression expression) { + final PsiReferenceExpression methodExpression = expression.getMethodExpression(); + final String referenceName = methodExpression.getReferenceName(); + if (!HardcodedMethodConstants.CLONE.equals(referenceName)) { + return; + } + final PsiExpressionList argumentList = expression.getArgumentList(); + final PsiExpression[] arguments = argumentList.getExpressions(); + if (arguments.length != 0) { + return; + } + final PsiExpression qualifierExpression = methodExpression.getQualifierExpression(); + if (qualifierExpression != null) { + final PsiType type = qualifierExpression.getType(); + if (type instanceof PsiArrayType) { + return; + } + } + registerMethodCallError(expression, expression); + } + + @Override + public void visitReferenceElement(PsiJavaCodeReferenceElement reference) { + final String qualifiedName = reference.getQualifiedName(); + if (!CommonClassNames.JAVA_LANG_CLONEABLE.equals(qualifiedName)) { + return; + } + registerError(reference, reference); + } + + @Override + public void visitMethod(PsiMethod method) { + if (!CloneUtils.isClone(method) || CloneUtils.onlyThrowsException(method)) { + return; + } + registerMethodError(method, method); + } + } +} diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/UseOfClone.html b/plugins/InspectionGadgets/src/inspectionDescriptions/UseOfClone.html new file mode 100644 index 000000000000..2f4c5a2ac6fc --- /dev/null +++ b/plugins/InspectionGadgets/src/inspectionDescriptions/UseOfClone.html @@ -0,0 +1,11 @@ + + +Reports calls to and implementations of the clone() method and uses of java.lang.Cloneable. +Some coding standards prohibit clone() usage, and recommend using a copy constructor or static factory method. +Calls to clone() on arrays are ignored, because that is a common, correct, efficient and compact way to copy an array. + + +

+ New in 14.1 + + \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/cloneable/use_of_clone/UseOfClone.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/cloneable/use_of_clone/UseOfClone.java new file mode 100644 index 000000000000..f6bd815abcd4 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/cloneable/use_of_clone/UseOfClone.java @@ -0,0 +1,18 @@ +package use_of_clone; + +class UseOfClone implements Cloneable { + + void f(int[] is) { + System.out.println(is.clone()); // don't warn when cloning an array + } + + public UseOfClone clone() { + return this; + } + + void g(UseOfClone o) { + o.clone(); + } +} +interface I extends Cloneable { +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/cloneable/UseOfCloneInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/cloneable/UseOfCloneInspectionTest.java new file mode 100644 index 000000000000..8f8df76d0e72 --- /dev/null +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/cloneable/UseOfCloneInspectionTest.java @@ -0,0 +1,36 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.siyeh.ig.cloneable; + +import com.intellij.codeInspection.InspectionProfileEntry; +import com.siyeh.ig.LightInspectionTestCase; +import org.jetbrains.annotations.Nullable; + +/** + * @author Bas Leijdekkers. + */ +public class UseOfCloneInspectionTest extends LightInspectionTestCase { + + public void testUseOfClone() { + doTest(); + } + + @Nullable + @Override + protected InspectionProfileEntry getInspection() { + return new UseOfCloneInspection(); + } +}