From 4c88396bf2f8e0faa65f19b42a3b11fcd1e2d974 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Tue, 28 Nov 2017 19:16:05 +0100 Subject: [PATCH] IG: report enum singletons in "Singleton" inspection --- .../siyeh/InspectionGadgetsBundle.properties | 1 + .../ig/classlayout/SingletonInspection.java | 9 +++++---- .../com/siyeh/ig/psiutils/SingletonUtil.java | 20 +++++++++++++------ .../classlayout/singleton/Singleton.java | 17 ++++++++++++++++ 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties index 1cf8d5465ee3..d288e2ac69b4 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties @@ -916,6 +916,7 @@ constant.declared.in.interface.problem.descriptor=Constant #ref dec static.inheritance.problem.descriptor=Interface #ref is implemented only for its 'static' constants #loc utility.class.problem.descriptor=Class #ref has only 'static' members, indicating procedural construction #loc singleton.problem.descriptor=Class #ref is a singleton #loc +enum.singleton.problem.descriptor=Enum #ref is a singleton #loc final.private.method.problem.descriptor='private' method declared #ref #loc noop.method.in.abstract.class.problem.descriptor=No-op Method #ref() should be made abstract #loc final.static.method.problem.descriptor='static' method declared #ref #loc diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/SingletonInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/SingletonInspection.java index 82fcc2797123..35e7953539da 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/SingletonInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/SingletonInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2010 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2017 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. @@ -33,7 +33,9 @@ public class SingletonInspection extends BaseInspection { @Override @NotNull protected String buildErrorString(Object... infos) { - return InspectionGadgetsBundle.message("singleton.problem.descriptor"); + return (Boolean)infos[0] ? + InspectionGadgetsBundle.message("enum.singleton.problem.descriptor") : + InspectionGadgetsBundle.message("singleton.problem.descriptor"); } @Override @@ -50,11 +52,10 @@ public class SingletonInspection extends BaseInspection { @Override public void visitClass(@NotNull PsiClass aClass) { - // no call to super, so that it doesn't drill down to inner classes if (!SingletonUtil.isSingleton(aClass)) { return; } - registerClassError(aClass); + registerClassError(aClass, aClass.isEnum()); } } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/SingletonUtil.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/SingletonUtil.java index e67dae9d86fe..7e08e357f25e 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/SingletonUtil.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/SingletonUtil.java @@ -33,18 +33,26 @@ public class SingletonUtil { private SingletonUtil() {} public static boolean isSingleton(@Nullable PsiClass aClass) { - if (aClass == null || aClass.isInterface() || aClass.isEnum() || aClass.isAnnotationType()) { + if (aClass == null || + aClass.isInterface() || + aClass.isAnnotationType() || + aClass instanceof PsiTypeParameter || + aClass instanceof PsiAnonymousClass) { return false; } - if (aClass instanceof PsiTypeParameter || aClass instanceof PsiAnonymousClass) { - return false; + if (aClass.isEnum()) { + if (!ControlFlowUtils.hasChildrenOfTypeCount(aClass, 1, PsiEnumConstant.class)) { + return false; + } + // has at least on accessible instance method + return Arrays.stream(aClass.getMethods()) + .anyMatch(m -> !m.isConstructor() && !m.hasModifierProperty(PsiModifier.PRIVATE) && !m.hasModifierProperty(PsiModifier.STATIC)); } - final PsiMethod[] constructors = getIfOnlyInvisibleConstructors(aClass); - if (constructors.length == 0) { + if (getIfOnlyInvisibleConstructors(aClass).length == 0) { return false; } final PsiField selfInstance = getIfOneStaticSelfInstance(aClass); - return selfInstance != null && newOnlyAssignsToStaticSelfInstance(constructors[0], selfInstance); + return selfInstance != null && newOnlyAssignsToStaticSelfInstance(getIfOnlyInvisibleConstructors(aClass)[0], selfInstance); } private static PsiField getIfOneStaticSelfInstance(PsiClass aClass) { diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/classlayout/singleton/Singleton.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/classlayout/singleton/Singleton.java index b3da751133e9..91e90b64adbe 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/classlayout/singleton/Singleton.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/classlayout/singleton/Singleton.java @@ -49,4 +49,21 @@ class Singleton2 { private static class SingletonHolder { private static final Singleton2 INSTANCE = new Singleton2(); } +} +enum No1 { + ; + void f() {} +} +enum No2 { + ONE, TWO; + + void f() {} +} +enum No3 { + INSTANCE +} +enum Yes { + INSTANCE; + + void f() {} } \ No newline at end of file