blob: 8be9ce07a5ef84b568ba659723b1aba589f85394 [file] [log] [blame]
/*
* 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);
}
}