19980f61a46059ae03663d945514745277a49c20
[idea/community.git] / plugins / InspectionGadgets / src / com / siyeh / ig / psiutils / SingletonUtil.java
1 /*
2  * Copyright 2003-2005 Dave Griffith
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.siyeh.ig.psiutils;
17
18 import com.intellij.psi.*;
19 import org.jetbrains.annotations.NotNull;
20
21 public class SingletonUtil {
22     private SingletonUtil() {
23         super();
24     }
25
26     public static boolean isSingleton(@NotNull PsiClass aClass) {
27         if (aClass.isInterface() || aClass.isEnum() || aClass.isAnnotationType()) {
28             return false;
29         }
30         if(aClass instanceof PsiTypeParameter ||
31                 aClass instanceof PsiAnonymousClass){
32             return false;
33         }                         
34         if (!hasConstructor(aClass)) {
35             return false;
36         }
37         if (hasVisibleConstructor(aClass)) {
38             return false;
39         }
40         return containsOneStaticSelfInstance(aClass);
41     }
42
43     private static boolean containsOneStaticSelfInstance(PsiClass aClass) {
44         final PsiField[] fields = aClass.getFields();
45         int numSelfInstances = 0;
46         for(final PsiField field : fields){
47             final String className = aClass.getQualifiedName();
48             if(field.hasModifierProperty(PsiModifier.STATIC)){
49                 final PsiType type = field.getType();
50                 final String fieldTypeName = type.getCanonicalText();
51                 if(fieldTypeName.equals(className)){
52                     numSelfInstances++;
53                 }
54             }
55         }
56         return numSelfInstances == 1;
57     }
58
59     private static boolean hasConstructor(PsiClass aClass) {
60         return aClass.getConstructors().length>0;
61     }
62
63     private static boolean hasVisibleConstructor(PsiClass aClass) {
64         final PsiMethod[] methods = aClass.getConstructors();
65         for(final PsiMethod method : methods){
66             if(method.hasModifierProperty(PsiModifier.PUBLIC)){
67                 return true;
68             }
69             if(!method.hasModifierProperty(PsiModifier.PRIVATE) &&
70                     !method.hasModifierProperty(PsiModifier.PROTECTED)){
71                 return true;
72             }
73         }
74         return false;
75     }
76 }