From a513885898dcd79cf6f0cb9c95c6a63af19bb2a2 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Tue, 1 Apr 2014 15:08:31 +0200 Subject: [PATCH] consider static and non-static methods when language level is 8.0 or higher --- .../ClassMayBeInterfaceInspection.java | 35 +++++++++--- .../ClassMayBeInterface.html | 8 +-- .../ConvertMe.after.java | 15 ++++++ .../class_may_be_interface/ConvertMe.java | 15 ++++++ .../ClassMayBeInterfaceInspectionTest.java | 53 +++++++++++++++++++ .../ClassMayBeInterfaceFixTest.java | 37 +++++++++++++ 6 files changed, 151 insertions(+), 12 deletions(-) create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igfixes/classlayout/class_may_be_interface/ConvertMe.after.java create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igfixes/classlayout/class_may_be_interface/ConvertMe.java create mode 100644 plugins/InspectionGadgets/testsrc/com/siyeh/ig/classlayout/ClassMayBeInterfaceInspectionTest.java create mode 100644 plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/classlayout/ClassMayBeInterfaceFixTest.java diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/ClassMayBeInterfaceInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/ClassMayBeInterfaceInspection.java index 1788bfafdfb7..cbea503c54d5 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/ClassMayBeInterfaceInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/ClassMayBeInterfaceInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2013 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2014 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,6 +22,7 @@ import com.intellij.psi.*; import com.intellij.psi.search.SearchScope; import com.intellij.psi.search.searches.ClassInheritorsSearch; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.PsiUtil; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; @@ -88,6 +89,21 @@ public class ClassMayBeInterfaceInspection extends BaseInspection { } private static void changeClassToInterface(PsiClass aClass) { + for (PsiMethod method : aClass.getMethods()) { + PsiUtil.setModifierProperty(method, PsiModifier.PUBLIC, false); + if (method.hasModifierProperty(PsiModifier.STATIC) || method.hasModifierProperty(PsiModifier.ABSTRACT)) { + continue; + } + PsiUtil.setModifierProperty(method, PsiModifier.DEFAULT, true); + } + for (PsiField field : aClass.getFields()) { + PsiUtil.setModifierProperty(field, PsiModifier.PUBLIC, false); + PsiUtil.setModifierProperty(field, PsiModifier.STATIC, false); + PsiUtil.setModifierProperty(field, PsiModifier.FINAL, false); + } + for (PsiClass innerClass : aClass.getInnerClasses()) { + PsiUtil.setModifierProperty(innerClass, PsiModifier.PUBLIC, false); + } final PsiIdentifier nameIdentifier = aClass.getNameIdentifier(); if (nameIdentifier == null) { return; @@ -99,11 +115,8 @@ public class ClassMayBeInterfaceInspection extends BaseInspection { if (classKeyword == null) { return; } - final PsiModifierList modifierList = aClass.getModifierList(); - if (modifierList != null) { - modifierList.setModifierProperty(PsiModifier.ABSTRACT, false); - modifierList.setModifierProperty(PsiModifier.FINAL, false); - } + PsiUtil.setModifierProperty(aClass, PsiModifier.ABSTRACT, false); + PsiUtil.setModifierProperty(aClass, PsiModifier.FINAL, false); classKeyword.replace(interfaceKeyword); } @@ -124,7 +137,7 @@ public class ClassMayBeInterfaceInspection extends BaseInspection { } private static void moveSubClassExtendsToImplements(List inheritors) { - PsiClass oldClass = inheritors.get(0); + final PsiClass oldClass = inheritors.get(0); final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(oldClass.getProject()).getElementFactory(); final PsiJavaCodeReferenceElement classReference = elementFactory.createClassReferenceElement(oldClass); for (int i = 1; i < inheritors.size(); i++) { @@ -170,6 +183,9 @@ public class ClassMayBeInterfaceInspection extends BaseInspection { if (aClass instanceof PsiTypeParameter || aClass instanceof PsiAnonymousClass) { return; } + if (!aClass.hasModifierProperty(PsiModifier.ABSTRACT)) { + return; + } if (!mayBeInterface(aClass)) { return; } @@ -206,7 +222,10 @@ public class ClassMayBeInterfaceInspection extends BaseInspection { private static boolean allMethodsPublicAbstract(PsiClass aClass) { final PsiMethod[] methods = aClass.getMethods(); for (final PsiMethod method : methods) { - if (!(method.hasModifierProperty(PsiModifier.ABSTRACT) && method.hasModifierProperty(PsiModifier.PUBLIC))) { + if (!PsiUtil.isLanguageLevel8OrHigher(aClass) && !method.hasModifierProperty(PsiModifier.ABSTRACT)) { + return false; + } + else if (!method.hasModifierProperty(PsiModifier.PUBLIC) || method.hasModifierProperty(PsiModifier.FINAL)) { return false; } } diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/ClassMayBeInterface.html b/plugins/InspectionGadgets/src/inspectionDescriptions/ClassMayBeInterface.html index f322e1947773..c4ccc3271202 100644 --- a/plugins/InspectionGadgets/src/inspectionDescriptions/ClassMayBeInterface.html +++ b/plugins/InspectionGadgets/src/inspectionDescriptions/ClassMayBeInterface.html @@ -1,10 +1,10 @@ -Reports any concrete or abstract classes -which may be simplified to be interfaces. This occurs if the class has no superclass (other +Reports abstract classes which can be converted to interfaces. +A class may be converted to an interface if it has no superclass (other than Object), has no fields declared that are not static, final, and public, and has no -methods declared that are not public and abstract, and no inner classes -that cannot themselves be interfaces. +methods declared that are not public and abstract and no inner classes that are not public. +When using a language level of 8.0 or higher classes containing static and non-static methods will also be reported.

diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/classlayout/class_may_be_interface/ConvertMe.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/classlayout/class_may_be_interface/ConvertMe.after.java new file mode 100644 index 000000000000..18e3e47d681d --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/classlayout/class_may_be_interface/ConvertMe.after.java @@ -0,0 +1,15 @@ +package com.siyeh.igfixes.classlayout.class_may_be_interface; + +interface ConvertMe { + + String S = ""; + + default void m() {} + + static void n() { + new ConvertMe() {}; + class X implements ConvertMe {} + } + + class A {} +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/classlayout/class_may_be_interface/ConvertMe.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/classlayout/class_may_be_interface/ConvertMe.java new file mode 100644 index 000000000000..efecbc0fbea1 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/classlayout/class_may_be_interface/ConvertMe.java @@ -0,0 +1,15 @@ +package com.siyeh.igfixes.classlayout.class_may_be_interface; + +abstract class ConvertMe { + + public static final String S = ""; + + public void m() {} + + public static void n() { + new ConvertMe() {}; + class X extends ConvertMe {} + } + + public class A {} +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/classlayout/ClassMayBeInterfaceInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/classlayout/ClassMayBeInterfaceInspectionTest.java new file mode 100644 index 000000000000..28fc863b6fd8 --- /dev/null +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/classlayout/ClassMayBeInterfaceInspectionTest.java @@ -0,0 +1,53 @@ +/* + * Copyright 2000-2014 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.classlayout; + +import com.intellij.codeInspection.InspectionProfileEntry; +import com.siyeh.ig.LightInspectionTestCase; + +/** + * @author Bas Leijdekkers + */ +public class ClassMayBeInterfaceInspectionTest extends LightInspectionTestCase { + + public void testOne() { + doTest("abstract class /*'ConvertMe' may be interface*/ConvertMe/**/ {\n" + + " public static final String S = \"\";\n" + + " public void m() {}\n" + + " public static void n() {\n" + + " new ConvertMe() {};\n" + + " class X extends ConvertMe {}\n" + + " }\n" + + " public class A {}\n" + + "}"); + } + + public void testOnTwo() { + doTest("class ConvertMe {\n" + + " public static final String S = \"\";\n" + + " public void m() {}\n" + + " public static void n() {\n" + + " new ConvertMe() {};\n" + + " class X extends ConvertMe {}\n" + + " }\n" + + " public class A {}\n" + + "}"); + } + @Override + protected InspectionProfileEntry getInspection() { + return new ClassMayBeInterfaceInspection(); + } +} diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/classlayout/ClassMayBeInterfaceFixTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/classlayout/ClassMayBeInterfaceFixTest.java new file mode 100644 index 000000000000..a5997a343acb --- /dev/null +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/classlayout/ClassMayBeInterfaceFixTest.java @@ -0,0 +1,37 @@ +/* + * Copyright 2000-2014 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.fixes.classlayout; + +import com.siyeh.InspectionGadgetsBundle; +import com.siyeh.ig.IGQuickFixesTestCase; +import com.siyeh.ig.classlayout.ClassMayBeInterfaceInspection; + +/** + * @author Bas Leijdekkers + */ +public class ClassMayBeInterfaceFixTest extends IGQuickFixesTestCase { + + @Override + protected void setUp() throws Exception { + super.setUp(); + myFixture.enableInspections(new ClassMayBeInterfaceInspection()); + myRelativePath = "classlayout/class_may_be_interface"; + myDefaultHint = InspectionGadgetsBundle.message("class.may.be.interface.convert.quickfix"); + } + + public void testConvertMe() { doTest(); } + +} \ No newline at end of file