| /* |
| * Copyright 2003-2014 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. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package com.siyeh.ig; |
| |
| import com.intellij.codeInsight.daemon.HighlightDisplayKey; |
| import com.intellij.codeInspection.BaseJavaBatchLocalInspectionTool; |
| import com.intellij.codeInspection.InspectionProfileEntry; |
| import com.intellij.codeInspection.LocalInspectionToolSession; |
| import com.intellij.codeInspection.ProblemsHolder; |
| import com.intellij.codeInspection.ex.InspectionProfileImpl; |
| import com.intellij.openapi.diagnostic.Logger; |
| import com.intellij.openapi.util.text.StringUtil; |
| import com.intellij.profile.codeInspection.InspectionProjectProfileManager; |
| import com.intellij.psi.PsiElement; |
| import com.intellij.psi.PsiElementVisitor; |
| import com.intellij.ui.DocumentAdapter; |
| import com.intellij.util.ReflectionUtil; |
| import com.intellij.util.ui.UIUtil; |
| import com.siyeh.ig.telemetry.InspectionGadgetsTelemetry; |
| import org.jetbrains.annotations.Nls; |
| import org.jetbrains.annotations.NonNls; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import javax.swing.*; |
| import javax.swing.event.DocumentEvent; |
| import javax.swing.text.Document; |
| import java.text.NumberFormat; |
| import java.text.ParseException; |
| import java.util.List; |
| |
| public abstract class BaseInspection extends BaseJavaBatchLocalInspectionTool { |
| private static final Logger LOG = Logger.getInstance("#com.siyeh.ig.BaseInspection"); |
| |
| private String m_shortName = null; |
| private long timestamp = -1L; |
| |
| @Override |
| @NotNull |
| public String getShortName() { |
| if (m_shortName == null) { |
| final Class<? extends BaseInspection> aClass = getClass(); |
| final String name = aClass.getSimpleName(); |
| m_shortName = InspectionProfileEntry.getShortName(name); |
| if (m_shortName.equals(name)) { |
| throw new AssertionError("class name must end with 'Inspection' to correctly calculate the short name: " + name); |
| } |
| } |
| return m_shortName; |
| } |
| |
| @Nls |
| @NotNull |
| @Override |
| public abstract String getDisplayName(); |
| |
| @Override |
| @Nls |
| @NotNull |
| public final String getGroupDisplayName() { |
| return GroupDisplayNameUtil.getGroupDisplayName(getClass()); |
| } |
| |
| @NotNull |
| protected abstract String buildErrorString(Object... infos); |
| |
| protected boolean buildQuickFixesOnlyForOnTheFlyErrors() { |
| return false; |
| } |
| |
| @Nullable |
| protected InspectionGadgetsFix buildFix(Object... infos) { |
| return null; |
| } |
| |
| @NotNull |
| protected InspectionGadgetsFix[] buildFixes(Object... infos) { |
| return InspectionGadgetsFix.EMPTY_ARRAY; |
| } |
| |
| public abstract BaseInspectionVisitor buildVisitor(); |
| |
| @Override |
| @NotNull |
| public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, |
| boolean isOnTheFly) { |
| final BaseInspectionVisitor visitor = buildVisitor(); |
| visitor.setProblemsHolder(holder); |
| visitor.setOnTheFly(isOnTheFly); |
| visitor.setInspection(this); |
| return visitor; |
| } |
| |
| protected JFormattedTextField prepareNumberEditor(@NonNls final String fieldName) { |
| final NumberFormat formatter = NumberFormat.getIntegerInstance(); |
| formatter.setParseIntegerOnly(true); |
| final JFormattedTextField valueField = new JFormattedTextField(formatter); |
| Object value = ReflectionUtil.getField(getClass(), this, null, fieldName); |
| valueField.setValue(value); |
| valueField.setColumns(2); |
| |
| // hack to work around text field becoming unusably small sometimes when using GridBagLayout |
| valueField.setMinimumSize(valueField.getPreferredSize()); |
| |
| UIUtil.fixFormattedField(valueField); |
| final Document document = valueField.getDocument(); |
| document.addDocumentListener(new DocumentAdapter() { |
| @Override |
| public void textChanged(DocumentEvent evt) { |
| try { |
| valueField.commitEdit(); |
| final Number number = (Number)valueField.getValue(); |
| ReflectionUtil.setField(BaseInspection.this.getClass(), BaseInspection.this, int.class, fieldName, number.intValue()); |
| } |
| catch (ParseException e) { |
| // No luck this time. Will update the field when correct value is entered. |
| } |
| } |
| }); |
| return valueField; |
| } |
| |
| protected static void parseString(String string, List<String>... outs) { |
| final List<String> strings = StringUtil.split(string, ","); |
| for (List<String> out : outs) { |
| out.clear(); |
| } |
| final int iMax = strings.size(); |
| for (int i = 0; i < iMax; i += outs.length) { |
| for (int j = 0; j < outs.length; j++) { |
| final List<String> out = outs[j]; |
| if (i + j >= iMax) { |
| out.add(""); |
| } |
| else { |
| out.add(strings.get(i + j)); |
| } |
| } |
| } |
| } |
| |
| protected static String formatString(List<String>... strings) { |
| final StringBuilder buffer = new StringBuilder(); |
| final int size = strings[0].size(); |
| if (size > 0) { |
| formatString(strings, 0, buffer); |
| for (int i = 1; i < size; i++) { |
| buffer.append(','); |
| formatString(strings, i, buffer); |
| } |
| } |
| return buffer.toString(); |
| } |
| |
| private static void formatString(List<String>[] strings, int index, |
| StringBuilder out) { |
| out.append(strings[0].get(index)); |
| for (int i = 1; i < strings.length; i++) { |
| out.append(','); |
| out.append(strings[i].get(index)); |
| } |
| } |
| |
| @Override |
| public void inspectionStarted(@NotNull LocalInspectionToolSession session, boolean isOnTheFly) { |
| super.inspectionStarted(session, isOnTheFly); |
| if (InspectionGadgetsTelemetry.isEnabled()) { |
| timestamp = System.currentTimeMillis(); |
| } |
| } |
| |
| @Override |
| public void inspectionFinished(@NotNull LocalInspectionToolSession session, |
| @NotNull ProblemsHolder problemsHolder) { |
| super.inspectionFinished(session, problemsHolder); |
| if (InspectionGadgetsTelemetry.isEnabled()) { |
| if (timestamp < 0L) { |
| LOG.warn("finish reported without corresponding start"); |
| return; |
| } |
| final long end = System.currentTimeMillis(); |
| final String displayName = getDisplayName(); |
| InspectionGadgetsTelemetry.getInstance().reportRun(displayName, end - timestamp); |
| timestamp = -1L; |
| } |
| } |
| |
| public static boolean isInspectionEnabled(@NonNls String shortName, PsiElement context) { |
| final InspectionProjectProfileManager profileManager = InspectionProjectProfileManager.getInstance(context.getProject()); |
| final InspectionProfileImpl profile = (InspectionProfileImpl)profileManager.getInspectionProfile(); |
| final HighlightDisplayKey key = HighlightDisplayKey.find(shortName); |
| return profile.isToolEnabled(key, context); |
| } |
| } |