2 * Copyright 2003-2008 Dave Griffith, Bas Leijdekkers
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 import com
.intellij
.codeInsight
.daemon
.GroupNames
;
19 import com
.intellij
.codeInspection
.BaseJavaLocalInspectionTool
;
20 import com
.intellij
.codeInspection
.ProblemsHolder
;
21 import com
.intellij
.openapi
.diagnostic
.Logger
;
22 import com
.intellij
.psi
.PsiElement
;
23 import com
.intellij
.psi
.PsiElementVisitor
;
24 import com
.intellij
.ui
.DocumentAdapter
;
25 import com
.siyeh
.ig
.ui
.FormattedTextFieldMacFix
;
26 import org
.jetbrains
.annotations
.Nls
;
27 import org
.jetbrains
.annotations
.NonNls
;
28 import org
.jetbrains
.annotations
.NotNull
;
29 import org
.jetbrains
.annotations
.Nullable
;
32 import javax
.swing
.event
.DocumentEvent
;
33 import javax
.swing
.text
.Document
;
34 import java
.lang
.reflect
.Field
;
35 import java
.lang
.reflect
.Method
;
36 import java
.text
.NumberFormat
;
37 import java
.text
.ParseException
;
38 import java
.util
.HashMap
;
39 import java
.util
.List
;
42 public abstract class BaseInspection
extends BaseJavaLocalInspectionTool
{
44 private static final Logger LOG
= Logger
.getInstance("#com.siyeh.ig.BaseInspection");
46 @NonNls private static final String INSPECTION
= "Inspection";
47 @NonNls private static final Map
<String
, String
> packageGroupDisplayNameMap
= new HashMap
<String
, String
>();
49 packageGroupDisplayNameMap
.put("abstraction", GroupNames
.ABSTRACTION_GROUP_NAME
);
50 packageGroupDisplayNameMap
.put("assignment", GroupNames
.ASSIGNMENT_GROUP_NAME
);
51 packageGroupDisplayNameMap
.put("bitwise", GroupNames
.BITWISE_GROUP_NAME
);
52 packageGroupDisplayNameMap
.put("bugs", GroupNames
.BUGS_GROUP_NAME
);
53 packageGroupDisplayNameMap
.put("classlayout", GroupNames
.CLASSLAYOUT_GROUP_NAME
);
54 packageGroupDisplayNameMap
.put("classmetrics", GroupNames
.CLASSMETRICS_GROUP_NAME
);
55 packageGroupDisplayNameMap
.put("cloneable", GroupNames
.CLONEABLE_GROUP_NAME
);
56 packageGroupDisplayNameMap
.put("controlflow", GroupNames
.CONTROL_FLOW_GROUP_NAME
);
57 packageGroupDisplayNameMap
.put("dataflow", GroupNames
.DATA_FLOW_ISSUES
);
58 packageGroupDisplayNameMap
.put("dependency", GroupNames
.DEPENDENCY_GROUP_NAME
);
59 packageGroupDisplayNameMap
.put("encapsulation", GroupNames
.ENCAPSULATION_GROUP_NAME
);
60 packageGroupDisplayNameMap
.put("errorhandling", GroupNames
.ERRORHANDLING_GROUP_NAME
);
61 packageGroupDisplayNameMap
.put("finalization", GroupNames
.FINALIZATION_GROUP_NAME
);
62 packageGroupDisplayNameMap
.put("imports", GroupNames
.IMPORTS_GROUP_NAME
);
63 packageGroupDisplayNameMap
.put("inheritance", GroupNames
.INHERITANCE_GROUP_NAME
);
64 packageGroupDisplayNameMap
.put("initialization", GroupNames
.INITIALIZATION_GROUP_NAME
);
65 packageGroupDisplayNameMap
.put("internationalization", GroupNames
.INTERNATIONALIZATION_GROUP_NAME
);
66 packageGroupDisplayNameMap
.put("j2me", GroupNames
.J2ME_GROUP_NAME
);
67 packageGroupDisplayNameMap
.put("javabeans", GroupNames
.JAVABEANS_GROUP_NAME
);
68 packageGroupDisplayNameMap
.put("jdk", GroupNames
.JDK_GROUP_NAME
);
69 packageGroupDisplayNameMap
.put("jdk15", GroupNames
.JDK15_SPECIFIC_GROUP_NAME
);
70 packageGroupDisplayNameMap
.put("junit", GroupNames
.JUNIT_GROUP_NAME
);
71 packageGroupDisplayNameMap
.put("logging", GroupNames
.LOGGING_GROUP_NAME
);
72 packageGroupDisplayNameMap
.put("maturity", GroupNames
.MATURITY_GROUP_NAME
);
73 packageGroupDisplayNameMap
.put("memory", GroupNames
.MEMORY_GROUP_NAME
);
74 packageGroupDisplayNameMap
.put("methodmetrics", GroupNames
.METHODMETRICS_GROUP_NAME
);
75 packageGroupDisplayNameMap
.put("modularization", GroupNames
.MODULARIZATION_GROUP_NAME
);
76 packageGroupDisplayNameMap
.put("naming", GroupNames
.NAMING_CONVENTIONS_GROUP_NAME
);
77 packageGroupDisplayNameMap
.put("numeric", GroupNames
.NUMERIC_GROUP_NAME
);
78 packageGroupDisplayNameMap
.put("packaging", GroupNames
.PACKAGING_GROUP_NAME
);
79 packageGroupDisplayNameMap
.put("performance", GroupNames
.PERFORMANCE_GROUP_NAME
);
80 packageGroupDisplayNameMap
.put("portability", GroupNames
.PORTABILITY_GROUP_NAME
);
81 packageGroupDisplayNameMap
.put("resources", GroupNames
.RESOURCE_GROUP_NAME
);
82 packageGroupDisplayNameMap
.put("security", GroupNames
.SECURITY_GROUP_NAME
);
83 packageGroupDisplayNameMap
.put("serialization", GroupNames
.SERIALIZATION_GROUP_NAME
);
84 packageGroupDisplayNameMap
.put("style", GroupNames
.STYLE_GROUP_NAME
);
85 packageGroupDisplayNameMap
.put("threading", GroupNames
.THREADING_GROUP_NAME
);
86 packageGroupDisplayNameMap
.put("visibility", GroupNames
.VISIBILITY_GROUP_NAME
);
89 private String m_shortName
= null;
92 public final String
getShortName() {
93 if (m_shortName
== null) {
94 final Class
<?
extends BaseInspection
> aClass
= getClass();
95 final String name
= aClass
.getName();
96 assert name
.endsWith(INSPECTION
) :
97 "class name must end with 'Inspection' to correctly" +
98 " calculate the short name: " + name
;
99 m_shortName
= name
.substring(name
.lastIndexOf((int)'.') + 1,
100 name
.length() - INSPECTION
.length());
107 public final String
getGroupDisplayName() {
108 final Class
<?
extends BaseInspection
> thisClass
= getClass();
109 final Package thisPackage
= thisClass
.getPackage();
110 assert thisPackage
!= null : "need package to determine group display name";
111 final String name
= thisPackage
.getName();
112 assert name
!= null :
113 "inspection has default package, group display name cannot be determined";
114 final int index
= name
.lastIndexOf('.');
115 final String key
= name
.substring(index
+ 1);
116 final String groupDisplayName
= packageGroupDisplayNameMap
.get(key
);
117 assert groupDisplayName
!= null : "No display name found for " + key
;
118 return groupDisplayName
;
122 protected abstract String
buildErrorString(Object
... infos
);
124 protected boolean buildQuickFixesOnlyForOnTheFlyErrors() {
129 protected InspectionGadgetsFix
buildFix(Object
... infos
) {
134 protected InspectionGadgetsFix
[] buildFixes(Object
... infos
) {
135 return InspectionGadgetsFix
.EMPTY_ARRAY
;
138 public boolean hasQuickFix() {
139 final Class
<?
extends BaseInspection
> aClass
= getClass();
140 final Method
[] methods
= aClass
.getDeclaredMethods();
141 for (final Method method
: methods
) {
142 @NonNls final String methodName
= method
.getName();
143 if ("buildFix".equals(methodName
)) {
150 public abstract BaseInspectionVisitor
buildVisitor();
153 public PsiElementVisitor
buildVisitor(@NotNull ProblemsHolder holder
,
154 boolean isOnTheFly
) {
155 final BaseInspectionVisitor visitor
= buildVisitor();
156 visitor
.setProblemsHolder(holder
);
157 visitor
.setOnTheFly(isOnTheFly
);
158 visitor
.setInspection(this);
163 protected JFormattedTextField
prepareNumberEditor(@NonNls String fieldName
) {
165 final NumberFormat formatter
= NumberFormat
.getIntegerInstance();
166 formatter
.setParseIntegerOnly(true);
167 final JFormattedTextField valueField
= new JFormattedTextField(formatter
);
168 final Field field
= getClass().getField(fieldName
);
169 valueField
.setValue(field
.get(this));
170 valueField
.setColumns(4);
171 FormattedTextFieldMacFix
.apply(valueField
);
172 final Document document
= valueField
.getDocument();
173 document
.addDocumentListener(new DocumentAdapter() {
174 public void textChanged(DocumentEvent evt
) {
176 valueField
.commitEdit();
177 field
.set(BaseInspection
.this, ((Number
) valueField
.getValue()).intValue());
178 } catch (IllegalAccessException e
) {
180 } catch (ParseException e
) {
181 // No luck this time. Will update the field when correct value is entered.
186 } catch (NoSuchFieldException e
) {
188 } catch (IllegalAccessException e
) {
194 protected static void parseString(String string
, List
<String
>... outs
){
195 final String
[] strings
= string
.split(",");
196 for (List
<String
> out
: outs
) {
199 for (int i
= 0; i
< strings
.length
; i
+= outs
.length
) {
200 for (int j
= 0; j
< outs
.length
; j
++) {
201 final List
<String
> out
= outs
[j
];
202 out
.add(strings
[i
+ j
]);
207 protected static String
formatString(List
<String
>... strings
){
208 final StringBuilder buffer
= new StringBuilder();
209 final int size
= strings
[0].size();
211 formatString(strings
, 0, buffer
);
212 for (int i
= 1; i
< size
; i
++) {
214 formatString(strings
, i
, buffer
);
217 return buffer
.toString();
220 private static void formatString(List
<String
>[] strings
, int index
,
222 out
.append(strings
[0].get(index
));
223 for (int i
= 1; i
< strings
.length
; i
++) {
225 out
.append(strings
[i
].get(index
));