IDEADEV-40452
[fedora-idea.git] / plugins / InspectionGadgets / src / com / siyeh / ig / BaseInspection.java
blobb99b089db1f955f4c9811e72cacaf4f024aa3a0f
1 /*
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.
16 package com.siyeh.ig;
18 import com.intellij.codeInsight.daemon.GroupNames;
19 import com.intellij.codeInspection.BaseJavaLocalInspectionTool;
20 import com.intellij.codeInspection.LocalInspectionToolSession;
21 import com.intellij.codeInspection.ProblemsHolder;
22 import com.intellij.openapi.application.Application;
23 import com.intellij.openapi.application.ApplicationManager;
24 import com.intellij.openapi.diagnostic.Logger;
25 import com.intellij.psi.PsiElementVisitor;
26 import com.intellij.ui.DocumentAdapter;
27 import com.siyeh.ig.ui.FormattedTextFieldMacFix;
28 import org.jetbrains.annotations.Nls;
29 import org.jetbrains.annotations.NonNls;
30 import org.jetbrains.annotations.NotNull;
31 import org.jetbrains.annotations.Nullable;
33 import javax.swing.*;
34 import javax.swing.event.DocumentEvent;
35 import javax.swing.text.Document;
36 import java.lang.reflect.Field;
37 import java.lang.reflect.Method;
38 import java.text.NumberFormat;
39 import java.text.ParseException;
40 import java.util.HashMap;
41 import java.util.List;
42 import java.util.Map;
44 public abstract class BaseInspection extends BaseJavaLocalInspectionTool {
46 private static final Logger LOG = Logger.getInstance("#com.siyeh.ig.BaseInspection");
48 private InspectionRunListener listener = null;
49 @NonNls private static final String INSPECTION_GADGETS_COMPONENT_NAME =
50 "InspectionGadgets";
51 @NonNls private static final String INSPECTION = "Inspection";
52 @NonNls private static final Map<String, String> packageGroupDisplayNameMap = new HashMap<String, String>();
53 static {
54 packageGroupDisplayNameMap.put("abstraction", GroupNames.ABSTRACTION_GROUP_NAME);
55 packageGroupDisplayNameMap.put("assignment", GroupNames.ASSIGNMENT_GROUP_NAME);
56 packageGroupDisplayNameMap.put("bitwise", GroupNames.BITWISE_GROUP_NAME);
57 packageGroupDisplayNameMap.put("bugs", GroupNames.BUGS_GROUP_NAME);
58 packageGroupDisplayNameMap.put("classlayout", GroupNames.CLASSLAYOUT_GROUP_NAME);
59 packageGroupDisplayNameMap.put("classmetrics", GroupNames.CLASSMETRICS_GROUP_NAME);
60 packageGroupDisplayNameMap.put("cloneable", GroupNames.CLONEABLE_GROUP_NAME);
61 packageGroupDisplayNameMap.put("controlflow", GroupNames.CONTROL_FLOW_GROUP_NAME);
62 packageGroupDisplayNameMap.put("dataflow", GroupNames.DATA_FLOW_ISSUES);
63 packageGroupDisplayNameMap.put("dependency", GroupNames.DEPENDENCY_GROUP_NAME);
64 packageGroupDisplayNameMap.put("encapsulation", GroupNames.ENCAPSULATION_GROUP_NAME);
65 packageGroupDisplayNameMap.put("errorhandling", GroupNames.ERRORHANDLING_GROUP_NAME);
66 packageGroupDisplayNameMap.put("finalization", GroupNames.FINALIZATION_GROUP_NAME);
67 packageGroupDisplayNameMap.put("imports", GroupNames.IMPORTS_GROUP_NAME);
68 packageGroupDisplayNameMap.put("inheritance", GroupNames.INHERITANCE_GROUP_NAME);
69 packageGroupDisplayNameMap.put("initialization", GroupNames.INITIALIZATION_GROUP_NAME);
70 packageGroupDisplayNameMap.put("internationalization", GroupNames.INTERNATIONALIZATION_GROUP_NAME);
71 packageGroupDisplayNameMap.put("j2me", GroupNames.J2ME_GROUP_NAME);
72 packageGroupDisplayNameMap.put("javabeans", GroupNames.JAVABEANS_GROUP_NAME);
73 packageGroupDisplayNameMap.put("jdk", GroupNames.JDK_GROUP_NAME);
74 packageGroupDisplayNameMap.put("jdk15", GroupNames.JDK15_SPECIFIC_GROUP_NAME);
75 packageGroupDisplayNameMap.put("junit", GroupNames.JUNIT_GROUP_NAME);
76 packageGroupDisplayNameMap.put("logging", GroupNames.LOGGING_GROUP_NAME);
77 packageGroupDisplayNameMap.put("maturity", GroupNames.MATURITY_GROUP_NAME);
78 packageGroupDisplayNameMap.put("memory", GroupNames.MEMORY_GROUP_NAME);
79 packageGroupDisplayNameMap.put("methodmetrics", GroupNames.METHODMETRICS_GROUP_NAME);
80 packageGroupDisplayNameMap.put("modularization", GroupNames.MODULARIZATION_GROUP_NAME);
81 packageGroupDisplayNameMap.put("naming", GroupNames.NAMING_CONVENTIONS_GROUP_NAME);
82 packageGroupDisplayNameMap.put("numeric", GroupNames.NUMERIC_GROUP_NAME);
83 packageGroupDisplayNameMap.put("packaging", GroupNames.PACKAGING_GROUP_NAME);
84 packageGroupDisplayNameMap.put("performance", GroupNames.PERFORMANCE_GROUP_NAME);
85 packageGroupDisplayNameMap.put("portability", GroupNames.PORTABILITY_GROUP_NAME);
86 packageGroupDisplayNameMap.put("resources", GroupNames.RESOURCE_GROUP_NAME);
87 packageGroupDisplayNameMap.put("security", GroupNames.SECURITY_GROUP_NAME);
88 packageGroupDisplayNameMap.put("serialization", GroupNames.SERIALIZATION_GROUP_NAME);
89 packageGroupDisplayNameMap.put("style", GroupNames.STYLE_GROUP_NAME);
90 packageGroupDisplayNameMap.put("threading", GroupNames.THREADING_GROUP_NAME);
91 packageGroupDisplayNameMap.put("visibility", GroupNames.VISIBILITY_GROUP_NAME);
94 private String m_shortName = null;
95 private long timeStamp = -1;
97 @NotNull
98 public final String getShortName() {
99 if (m_shortName == null) {
100 final Class<? extends BaseInspection> aClass = getClass();
101 final String name = aClass.getName();
102 assert name.endsWith(INSPECTION) :
103 "class name must end with 'Inspection' to correctly" +
104 " calculate the short name: " + name;
105 m_shortName = name.substring(name.lastIndexOf((int)'.') + 1,
106 name.length() - INSPECTION.length());
108 return m_shortName;
112 @Nls @NotNull
113 public final String getGroupDisplayName() {
114 final Class<? extends BaseInspection> thisClass = getClass();
115 final Package thisPackage = thisClass.getPackage();
116 assert thisPackage != null : "need package to determine group display name";
117 final String name = thisPackage.getName();
118 assert name != null :
119 "inspection has default package, group display name cannot be determined";
120 final int index = name.lastIndexOf('.');
121 final String key = name.substring(index + 1);
122 final String groupDisplayName = packageGroupDisplayNameMap.get(key);
123 assert groupDisplayName != null : "No display name found for " + key;
124 return groupDisplayName;
127 @NotNull
128 protected abstract String buildErrorString(Object... infos);
130 protected boolean buildQuickFixesOnlyForOnTheFlyErrors() {
131 return false;
134 @Nullable
135 protected InspectionGadgetsFix buildFix(Object... infos) {
136 return null;
139 @NotNull
140 protected InspectionGadgetsFix[] buildFixes(Object... infos) {
141 return InspectionGadgetsFix.EMPTY_ARRAY;
144 public boolean hasQuickFix() {
145 final Class<? extends BaseInspection> aClass = getClass();
146 final Method[] methods = aClass.getDeclaredMethods();
147 for (final Method method : methods) {
148 @NonNls final String methodName = method.getName();
149 if ("buildFix".equals(methodName)) {
150 return true;
153 return false;
156 public abstract BaseInspectionVisitor buildVisitor();
158 @NotNull
159 public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder,
160 boolean isOnTheFly) {
161 final BaseInspectionVisitor visitor = buildVisitor();
162 visitor.setProblemsHolder(holder);
163 visitor.setOnTheFly(isOnTheFly);
164 visitor.setInspection(this);
165 return visitor;
169 protected JFormattedTextField prepareNumberEditor(@NonNls String fieldName) {
170 try {
171 final NumberFormat formatter = NumberFormat.getIntegerInstance();
172 formatter.setParseIntegerOnly(true);
173 final JFormattedTextField valueField = new JFormattedTextField(formatter);
174 final Field field = getClass().getField(fieldName);
175 valueField.setValue(field.get(this));
176 valueField.setColumns(4);
177 FormattedTextFieldMacFix.apply(valueField);
178 final Document document = valueField.getDocument();
179 document.addDocumentListener(new DocumentAdapter() {
180 public void textChanged(DocumentEvent evt) {
181 try {
182 valueField.commitEdit();
183 field.set(BaseInspection.this, ((Number) valueField.getValue()).intValue());
184 } catch (IllegalAccessException e) {
185 LOG.error(e);
186 } catch (ParseException e) {
187 // No luck this time. Will update the field when correct value is entered.
191 return valueField;
192 } catch (NoSuchFieldException e) {
193 LOG.error(e);
194 } catch (IllegalAccessException e) {
195 LOG.error(e);
197 return null;
200 protected static void parseString(String string, List<String>... outs){
201 final String[] strings = string.split(",");
202 for (List<String> out : outs) {
203 out.clear();
205 for (int i = 0; i < strings.length; i += outs.length) {
206 for (int j = 0; j < outs.length; j++) {
207 final List<String> out = outs[j];
208 if (i + j >= strings.length) {
209 out.add("");
210 } else {
211 out.add(strings[i + j]);
217 protected static String formatString(List<String>... strings){
218 final StringBuilder buffer = new StringBuilder();
219 final int size = strings[0].size();
220 if (size > 0) {
221 formatString(strings, 0, buffer);
222 for (int i = 1; i < size; i++) {
223 buffer.append(',');
224 formatString(strings, i, buffer);
227 return buffer.toString();
230 private static void formatString(List<String>[] strings, int index,
231 StringBuilder out) {
232 out.append(strings[0].get(index));
233 for (int i = 1; i < strings.length; i++) {
234 out.append(',');
235 out.append(strings[i].get(index));
239 private void initializeTelemetryIfNecessary() {
240 if (InspectionGadgetsPlugin.TELEMETRY_ENABLED && listener == null) {
241 final Application application = ApplicationManager.getApplication();
242 final InspectionGadgetsPlugin plugin = (InspectionGadgetsPlugin)
243 application.getComponent(INSPECTION_GADGETS_COMPONENT_NAME);
244 listener = plugin.getTelemetry();
248 @Override
249 public void inspectionStarted(LocalInspectionToolSession session) {
250 super.inspectionStarted(session);
251 if (InspectionGadgetsPlugin.TELEMETRY_ENABLED) {
252 if (timeStamp > 0) {
253 System.out.println("start reported without corresponding finish");
255 initializeTelemetryIfNecessary();
256 timeStamp = System.currentTimeMillis();
260 @Override
261 public void inspectionFinished(LocalInspectionToolSession session) {
262 super.inspectionFinished(session);
263 if (InspectionGadgetsPlugin.TELEMETRY_ENABLED) {
264 if (timeStamp < 0) {
265 System.out.println("finish reported without corresponding start");
266 return;
268 final long end = System.currentTimeMillis();
269 final String displayName = getDisplayName();
270 listener.reportRun(displayName, end - timeStamp);
271 timeStamp = -1;