From e498a286467082bd5cb0d7ac4eec3b1bfd20ea21 Mon Sep 17 00:00:00 2001 From: Olga Klisho Date: Mon, 17 Dec 2018 14:55:18 +0100 Subject: [PATCH] Array can be replaced with enum values inspection added (IDEA-195323) --- .../siyeh/InspectionGadgetsBundle.properties | 4 + .../src/META-INF/InspectionGadgets.xml | 4 + ...CanBeReplacedWithEnumValuesInspection.java | 134 ++++++++++++++++++ .../ArrayCanBeReplacedWithEnumValues.html | 6 + .../ClassWithEnum.after.java | 12 ++ .../ClassWithEnum.java | 12 ++ .../EnumRevOrder.java | 12 ++ .../EnumWithField.after.java | 18 +++ .../EnumWithField.java | 18 +++ .../ErrorInMultiDArray.java | 11 ++ .../FooInit.after.java | 10 ++ .../array_replaced_enum_values/FooInit.java | 10 ++ .../InnerEnum.after.java | 15 ++ .../array_replaced_enum_values/InnerEnum.java | 15 ++ .../MultiDArrayNoError.java | 14 ++ .../NotEnumInit.java | 12 ++ .../NotEnumMulti.java | 12 ++ .../OuterEnumUse.after.java | 8 ++ .../OuterEnumUse.java | 8 ++ ...rayCanBeReplacedWithEnumValuesFixTest.java | 63 ++++++++ 20 files changed, 398 insertions(+) create mode 100644 plugins/InspectionGadgets/src/com/siyeh/ig/style/ArrayCanBeReplacedWithEnumValuesInspection.java create mode 100644 plugins/InspectionGadgets/src/inspectionDescriptions/ArrayCanBeReplacedWithEnumValues.html create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/ClassWithEnum.after.java create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/ClassWithEnum.java create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/EnumRevOrder.java create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/EnumWithField.after.java create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/EnumWithField.java create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/ErrorInMultiDArray.java create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/FooInit.after.java create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/FooInit.java create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/InnerEnum.after.java create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/InnerEnum.java create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/MultiDArrayNoError.java create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/NotEnumInit.java create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/NotEnumMulti.java create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/OuterEnumUse.after.java create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/OuterEnumUse.java create mode 100644 plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/style/ArrayCanBeReplacedWithEnumValuesFixTest.java diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties index fdd7850e9ab8..de5a87d14ed3 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties @@ -2158,6 +2158,10 @@ junit5.converter.fix.name=Migrate to JUnit 5 call.to.suspicious.string.method.display.name=Call to suspicious String method call.to.suspicious.string.method.problem.descriptor=String.#ref() called in internationalized context #loc +array.can.be.replaced.with.enum.values = Array can be replaced with enum values +array.can.be.replaced.with.enum.values.quickfix = Replace array with {0}.values() +array.can.be.replaced.with.enum.values.family.quickfix = Replace array with EnumType.values() + string.concatenation.replace.fix=Replace with StringBuilder string.concatenation.replace.fix.name=Convert variable ''{0}'' from String to {1} string.concatenation.introduce.fix=Introduce StringBuilder diff --git a/plugins/InspectionGadgets/src/META-INF/InspectionGadgets.xml b/plugins/InspectionGadgets/src/META-INF/InspectionGadgets.xml index 333ebd19d79d..c1777e32b1df 100644 --- a/plugins/InspectionGadgets/src/META-INF/InspectionGadgets.xml +++ b/plugins/InspectionGadgets/src/META-INF/InspectionGadgets.xml @@ -2536,6 +2536,10 @@ key="inspection.simplifiable.if.statement.display.name" groupBundle="messages.InspectionsBundle" groupKey="group.names.code.style.issues" enabledByDefault="true" level="INFORMATION" implementationClass="com.siyeh.ig.style.SimplifiableIfStatementInspection"/> + enumValues = Stream.of(initClass.getFields()) + .filter(ev -> ev instanceof PsiEnumConstant) + .map(ev -> ev.getName()) + .collect(Collectors.toList()); + + final PsiExpression[] initializers = expression.getInitializers(); + if (enumValues.size() != initializers.length) { + return; + } + + for (int i = 0; i < initializers.length; i++) { + if (!(initializers[i] instanceof PsiReferenceExpression && + enumValues.get(i).equals(((PsiReferenceExpression)initializers[i]).getReferenceName()) && + initExprType.equals(initializers[i].getType()))) { + return; + } + } + + final PsiElement parent = expression.getParent(); + final String enumName = initClass.getQualifiedName(); + + if (parent instanceof PsiNewExpression) { + registerError(parent, enumName); + } + else { + registerError(expression, enumName); + } + } + } +} + diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/ArrayCanBeReplacedWithEnumValues.html b/plugins/InspectionGadgets/src/inspectionDescriptions/ArrayCanBeReplacedWithEnumValues.html new file mode 100644 index 000000000000..a78495bc6358 --- /dev/null +++ b/plugins/InspectionGadgets/src/inspectionDescriptions/ArrayCanBeReplacedWithEnumValues.html @@ -0,0 +1,6 @@ + + + +Reports arrays of enum constants which may be replaced with EnumType.values(). + + \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/ClassWithEnum.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/ClassWithEnum.after.java new file mode 100644 index 000000000000..98bdc8dfd411 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/ClassWithEnum.after.java @@ -0,0 +1,12 @@ +class ClassWithEnum { + + public static void foo() { + testMethod(TestEnum.values()); + } + + private static void testMethod(TestEnum[] values) { } + + public enum TestEnum { + ONE, TWO, THREE + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/ClassWithEnum.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/ClassWithEnum.java new file mode 100644 index 000000000000..259478be9deb --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/ClassWithEnum.java @@ -0,0 +1,12 @@ +class ClassWithEnum { + + public static void foo() { + testMethod(new TestEnum[]{TestEnum.ONE, TestEnum.TWO, TestEnum.THREE}); + } + + private static void testMethod(TestEnum[] values) { } + + public enum TestEnum { + ONE, TWO, THREE + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/EnumRevOrder.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/EnumRevOrder.java new file mode 100644 index 000000000000..41991ad9b2aa --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/EnumRevOrder.java @@ -0,0 +1,12 @@ +class EnumRevOrder { + + public static void foo() { + testMethod(new TestEnum[]{TestEnum.THREE, TestEnum.TWO, TestEnum.ONE}); + } + + private static void testMethod(TestEnum[] values) { } + + public enum TestEnum { + ONE, TWO, THREE; + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/EnumWithField.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/EnumWithField.after.java new file mode 100644 index 000000000000..6eb8938c0228 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/EnumWithField.after.java @@ -0,0 +1,18 @@ +class EnumWithField { + + public static void foo() { + testMethod(TestEnum.values()); + } + + private static void testMethod(TestEnum[] values) { } + + public enum TestEnum { + ONE(1), TWO(2), THREE(3); + + private final int levelCode; + + TestEnum(int levelCode) { + this.levelCode = levelCode; + } + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/EnumWithField.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/EnumWithField.java new file mode 100644 index 000000000000..63d0a3ba8447 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/EnumWithField.java @@ -0,0 +1,18 @@ +class EnumWithField { + + public static void foo() { + testMethod(new TestEnum[]{TestEnum.ONE, TestEnum.TWO, TestEnum.THREE}); + } + + private static void testMethod(TestEnum[] values) { } + + public enum TestEnum { + ONE(1), TWO(2), THREE(3); + + private final int levelCode; + + TestEnum(int levelCode) { + this.levelCode = levelCode; + } + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/ErrorInMultiDArray.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/ErrorInMultiDArray.java new file mode 100644 index 000000000000..60134a62f89f --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/ErrorInMultiDArray.java @@ -0,0 +1,11 @@ +class ErrorInMultiDArray { + + public static void foo() { + testMethod(new TestEnum[]{{TestEnum.ONE, TestEnum.TWO, TestEnum.THREE}}); + } + + private static void testMethod(TestEnum[] values) { } + + public enum TestEnum { + ONE, TWO, THREE; +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/FooInit.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/FooInit.after.java new file mode 100644 index 000000000000..e2052097fc96 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/FooInit.after.java @@ -0,0 +1,10 @@ +class Foo { + enum En {A;} + static En foo() { + return En.A; + } + + { + En[] array = En.values(); + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/FooInit.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/FooInit.java new file mode 100644 index 000000000000..c3173d926c75 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/FooInit.java @@ -0,0 +1,10 @@ +class Foo { + enum En {A;} + static En foo() { + return En.A; + } + + { + En[] array = new En[] {foo()}; + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/InnerEnum.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/InnerEnum.after.java new file mode 100644 index 000000000000..373fd194ab85 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/InnerEnum.after.java @@ -0,0 +1,15 @@ +class InnerEnum { + + public static void foo() { + testMethod(TestEnum.Inner.values()); + } + + private static void testMethod(TestEnum.Inner[] values) { + } + + public enum TestEnum { + ONE, TWO, THREE; + + enum Inner {FIVE, SIX, SEVEN} + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/InnerEnum.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/InnerEnum.java new file mode 100644 index 000000000000..4700dea51209 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/InnerEnum.java @@ -0,0 +1,15 @@ +class InnerEnum { + + public static void foo() { + testMethod(new TestEnum.Inner[]{TestEnum.Inner.FIVE, TestEnum.Inner.SIX, TestEnum.Inner.SEVEN}); + } + + private static void testMethod(TestEnum.Inner[] values) { + } + + public enum TestEnum { + ONE, TWO, THREE; + + enum Inner {FIVE, SIX, SEVEN} + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/MultiDArrayNoError.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/MultiDArrayNoError.java new file mode 100644 index 000000000000..8a84a62ba347 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/MultiDArrayNoError.java @@ -0,0 +1,14 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +class MultiDArrayNoError { + + public static void foo() { + testMethod(new TestEnum[][]{{TestEnum.ONE, TestEnum.THREE, TestEnum.TWO}}); + } + + private static void testMethod(TestEnum[][] values) { + } + + public enum TestEnum { + ONE, TWO, THREE; + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/NotEnumInit.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/NotEnumInit.java new file mode 100644 index 000000000000..f50cf0dc541b --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/NotEnumInit.java @@ -0,0 +1,12 @@ +class NotEnumInit { + + public static void foo() { + testMethod(new TestEnum[]{"", TestEnum.ONE}); + } + + private static void testMethod(TestEnum[] values) { } + + public enum TestEnum { + ONE, TWO, THREE + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/NotEnumMulti.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/NotEnumMulti.java new file mode 100644 index 000000000000..2162fcf44396 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/NotEnumMulti.java @@ -0,0 +1,12 @@ +class NotEnumMulti { + + public static void foo() { + testMethod(new TestEnum[][]{{TestEnum.ONE}}); + } + + private static void testMethod(TestEnum[] values) { } + + public enum TestEnum { + ONE, TWO, THREE + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/OuterEnumUse.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/OuterEnumUse.after.java new file mode 100644 index 000000000000..b70053d596fe --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/OuterEnumUse.after.java @@ -0,0 +1,8 @@ +class OuterEnumUse { + + public static void foo() { + testMethod(OuterEnum.TestEnum.values()); + } + private static void testMethod(OuterEnum.TestEnum[] values) { + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/OuterEnumUse.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/OuterEnumUse.java new file mode 100644 index 000000000000..1cc9c9a0d045 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/array_replaced_enum_values/OuterEnumUse.java @@ -0,0 +1,8 @@ +class OuterEnumUse { + + public static void foo() { + testMethod(new OuterEnum.TestEnum[]{OuterEnum.TestEnum.A, OuterEnum.TestEnum.B, OuterEnum.TestEnum.C}); + } + private static void testMethod(OuterEnum.TestEnum[] values) { + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/style/ArrayCanBeReplacedWithEnumValuesFixTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/style/ArrayCanBeReplacedWithEnumValuesFixTest.java new file mode 100644 index 000000000000..3825d7ea6112 --- /dev/null +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/style/ArrayCanBeReplacedWithEnumValuesFixTest.java @@ -0,0 +1,63 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.siyeh.ig.fixes.style; + +import com.siyeh.InspectionGadgetsBundle; +import com.siyeh.ig.IGQuickFixesTestCase; +import com.siyeh.ig.style.ArrayCanBeReplacedWithEnumValuesInspection; + + +public class ArrayCanBeReplacedWithEnumValuesFixTest extends IGQuickFixesTestCase { + + public void testClassWithEnum() { doTest("TestEnum"); } + + public void testEnumWithField() {doTest("TestEnum");} + + public void testNotEnumInit() { assertQuickfixNotAvailable(); } + + public void testNotEnumMulti() { assertQuickfixNotAvailable(); } + + public void testEnumRevOrder() { assertQuickfixNotAvailable();} + + public void testErrorInMultiDArray() { assertQuickfixNotAvailable();} + + public void testMultiDArrayNoError() {assertQuickfixNotAvailable();} + + public void testInnerEnum() {doTest("Inner");} + + public void testFooInit() {assertQuickfixNotAvailable();} + + public void testOuterEnumUse() {doTest("TestEnum");} + + + + @Override + protected void doTest(String hint) { + super.doTest(InspectionGadgetsBundle.message("array.can.be.replaced.with.enum.values.quickfix", hint)); + } + + @Override + protected void assertQuickfixNotAvailable() { + String message = InspectionGadgetsBundle.message("array.can.be.replaced.with.enum.values.quickfix", "@"); + super.assertQuickfixNotAvailable(message.substring(0, message.indexOf('@'))); + } + + @Override + public void setUp() throws Exception { + super.setUp(); + myFixture.enableInspections(new ArrayCanBeReplacedWithEnumValuesInspection()); + myRelativePath = "style/array_replaced_enum_values"; + } + + + @Override + protected String[] getEnvironmentClasses() { + return new String[] { + "public class OuterEnum {\n" + + " public enum TestEnum {\n" + + " A, B, C\n" + + " }\n" + + "}" + }; + } +} +