language-aware inspections

This commit is contained in:
Dmitry Avdeev
2011-10-04 10:43:49 +04:00
parent 91c43faa99
commit 6a3984e3c7
13 changed files with 76 additions and 46 deletions
@@ -73,7 +73,7 @@ public class EmptyIntentionInspectionQuickFixTest extends LightQuickFixTestCase{
IntentionAction action = emptyActions.get(i);
if (!(action instanceof EmptyIntentionAction)) emptyActions.remove(i);
}
assertEquals(1, emptyActions.size());
assertEquals(emptyActions.toString(), 1, emptyActions.size());
}
public void testLowPriority() throws Exception {
@@ -31,4 +31,7 @@ public class LocalInspectionEP extends InspectionEP {
@Attribute("alternativeId")
public String alternativeId;
@Attribute("runForWholeFile")
public boolean runForWholeFile;
}
@@ -128,8 +128,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass
if (!HighlightLevelUtil.shouldInspect(myFile)) return;
final InspectionManagerEx iManager = (InspectionManagerEx)InspectionManager.getInstance(myProject);
final InspectionProfileWrapper profile = myProfileWrapper;
final List<LocalInspectionTool> tools = DumbService.getInstance(myProject).filterByDumbAwareness(getInspectionTools(profile));
inspect(tools, iManager, true, true, progress);
inspect(getInspectionTools(profile), iManager, true, true, DumbService.isDumb(myProject), progress);
}
finally {
disposeDescriptors();
@@ -145,10 +144,9 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass
for (InspectionProfileEntry toolWrapper : toolWrappers) {
tool2Wrapper.put(((LocalInspectionToolWrapper)toolWrapper).getTool(), (LocalInspectionToolWrapper)toolWrapper);
}
List<LocalInspectionTool> tools = new ArrayList<LocalInspectionTool>(tool2Wrapper.keySet());
ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator();
inspect(tools, iManager, false, false, progress);
inspect(new ArrayList<LocalInspectionToolWrapper>(tool2Wrapper.values()), iManager, false, false, false, progress);
addDescriptorsFromInjectedResults(tool2Wrapper, iManager);
List<InspectionResult> resultList = result.get(myFile);
if (resultList == null) return;
@@ -206,25 +204,43 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass
}
}
private void inspect(@NotNull final List<LocalInspectionTool> tools,
private void inspect(@NotNull final List<LocalInspectionToolWrapper> toolWrappers,
@NotNull final InspectionManagerEx iManager,
final boolean isOnTheFly,
boolean failFastOnAcquireReadAction,
boolean checkDumbAwareness,
@NotNull final ProgressIndicator indicator) {
myFailFastOnAcquireReadAction = failFastOnAcquireReadAction;
if (tools.isEmpty()) return;
if (toolWrappers.isEmpty()) return;
List<PsiElement> inside = new ArrayList<PsiElement>();
List<PsiElement> outside = new ArrayList<PsiElement>();
Divider.divideInsideAndOutside(myFile, myStartOffset, myEndOffset, myPriorityRange, inside, outside,
HighlightLevelUtil.AnalysisLevel.HIGHLIGHT_AND_INSPECT,true);
Set<String> languages = new HashSet<String>();
for (PsiElement element : inside) {
languages.add(element.getLanguage().getID());
}
for (PsiElement element : outside) {
languages.add(element.getLanguage().getID());
}
List<LocalInspectionTool> tools = new ArrayList<LocalInspectionTool>();
for (LocalInspectionToolWrapper wrapper : toolWrappers) {
if (wrapper.getLanguage() == null || languages.contains(wrapper.getLanguage())) {
LocalInspectionTool tool = wrapper.getTool();
if (!checkDumbAwareness || tool instanceof DumbAware) {
tools.add(tool);
}
}
}
setProgressLimit(1L * tools.size() * 2);
final LocalInspectionToolSession session = new LocalInspectionToolSession(myFile, myStartOffset, myEndOffset);
List<Trinity<LocalInspectionTool, ProblemsHolder, PsiElementVisitor>> init = new ArrayList<Trinity<LocalInspectionTool, ProblemsHolder, PsiElementVisitor>>();
visitPriorityElementsAndInit(tools, iManager, isOnTheFly, indicator, inside, session, init);
visitRestElementsAndCleanup(tools,iManager,isOnTheFly, indicator, outside, session, init);
visitRestElementsAndCleanup(tools, iManager, isOnTheFly, indicator, outside, session, init);
indicator.checkCanceled();
@@ -640,7 +656,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass
return new ArrayList<PsiElement>(result);
}
List<LocalInspectionTool> getInspectionTools(InspectionProfileWrapper profile) {
List<LocalInspectionToolWrapper> getInspectionTools(InspectionProfileWrapper profile) {
return profile.getHighlightingLocalInspectionTools(myFile);
}
@@ -16,9 +16,12 @@
package com.intellij.codeInsight.daemon.impl;
import com.intellij.codeHighlighting.*;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeHighlighting.MainHighlightingPassFactory;
import com.intellij.codeHighlighting.Pass;
import com.intellij.codeHighlighting.TextEditorHighlightingPass;
import com.intellij.codeHighlighting.TextEditorHighlightingPassRegistrar;
import com.intellij.codeInspection.ex.InspectionProfileWrapper;
import com.intellij.codeInspection.ex.LocalInspectionToolWrapper;
import com.intellij.openapi.components.AbstractProjectComponent;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
@@ -26,7 +29,6 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
import com.intellij.psi.PsiFile;
import com.intellij.util.PlatformUtils;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -74,10 +76,10 @@ public class LocalInspectionsPassFactory extends AbstractProjectComponent implem
super(file, document, textRange.getStartOffset(), textRange.getEndOffset(), visibleRange, true);
}
List<LocalInspectionTool> getInspectionTools(InspectionProfileWrapper profile) {
List<LocalInspectionTool> tools = super.getInspectionTools(profile);
List<LocalInspectionTool> result = new ArrayList<LocalInspectionTool>(tools.size());
for (LocalInspectionTool tool : tools) {
List<LocalInspectionToolWrapper> getInspectionTools(InspectionProfileWrapper profile) {
List<LocalInspectionToolWrapper> tools = super.getInspectionTools(profile);
List<LocalInspectionToolWrapper> result = new ArrayList<LocalInspectionToolWrapper>(tools.size());
for (LocalInspectionToolWrapper tool : tools) {
if (!tool.runForWholeFile()) result.add(tool);
}
return result;
@@ -23,6 +23,7 @@ import com.intellij.codeHighlighting.TextEditorHighlightingPassRegistrar;
import com.intellij.codeInsight.daemon.DaemonBundle;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.ex.InspectionProfileWrapper;
import com.intellij.codeInspection.ex.LocalInspectionToolWrapper;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.components.AbstractProjectComponent;
import com.intellij.openapi.editor.Editor;
@@ -94,11 +95,12 @@ public class WholeFileLocalInspectionsPassFactory extends AbstractProjectCompone
myFileTools.containsKey(file) && !myFileTools.get(file)) {
return null;
}
return new LocalInspectionsPass(file, editor.getDocument(), 0, file.getTextLength(), LocalInspectionsPass.EMPTY_PRIORITY_RANGE, true) {
List<LocalInspectionTool> getInspectionTools(InspectionProfileWrapper profile) {
List<LocalInspectionTool> tools = super.getInspectionTools(profile);
List<LocalInspectionTool> result = new ArrayList<LocalInspectionTool>();
for (LocalInspectionTool tool : tools) {
List<LocalInspectionToolWrapper> getInspectionTools(InspectionProfileWrapper profile) {
List<LocalInspectionToolWrapper> tools = super.getInspectionTools(profile);
List<LocalInspectionToolWrapper> result = new ArrayList<LocalInspectionToolWrapper>(tools.size());
for (LocalInspectionToolWrapper tool : tools) {
if (tool.runForWholeFile()) result.add(tool);
}
myFileTools.put(file, !result.isEmpty());
@@ -18,7 +18,6 @@ package com.intellij.codeInspection.ex;
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
import com.intellij.codeInspection.InspectionProfile;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
@@ -55,15 +54,13 @@ public class InspectionProfileWrapper {
return (InspectionTool[])myProfile.getInspectionTools(element);
}
public List<LocalInspectionTool> getHighlightingLocalInspectionTools(PsiElement element) {
List<LocalInspectionTool> enabled = new ArrayList<LocalInspectionTool>();
public List<LocalInspectionToolWrapper> getHighlightingLocalInspectionTools(PsiElement element) {
List<LocalInspectionToolWrapper> enabled = new ArrayList<LocalInspectionToolWrapper>();
final InspectionTool[] tools = getInspectionTools(element);
checkInspectionsDuplicates(tools);
for (InspectionTool tool : tools) {
if (tool instanceof LocalInspectionToolWrapper) {
if (myProfile.isToolEnabled(HighlightDisplayKey.find(tool.getShortName()), element)) {
enabled.add(((LocalInspectionToolWrapper)tool).getTool());
}
if (tool instanceof LocalInspectionToolWrapper && myProfile.isToolEnabled(HighlightDisplayKey.find(tool.getShortName()), element)) {
enabled.add((LocalInspectionToolWrapper)tool);
}
}
return enabled;
@@ -60,6 +60,11 @@ public abstract class InspectionToolWrapper<T extends InspectionProfileEntry, E
return myTool != null;
}
@Nullable
public String getLanguage() {
return myEP == null ? null : myEP.language;
}
@NotNull
public String getShortName() {
return myEP == null ? getTool().getShortName() : myEP.shortName;
@@ -196,4 +196,8 @@ public final class LocalInspectionToolWrapper extends InspectionToolWrapper<Loca
public String getAlternativeID() {
return myEP == null ? getTool().getAlternativeID() : myEP.alternativeId;
}
public boolean runForWholeFile() {
return myEP == null ? getTool().runForWholeFile() : myEP.runForWholeFile;
}
}
@@ -313,7 +313,7 @@
groupName="XML" enabledByDefault="true" level="ERROR"
implementationClass="com.intellij.xml.util.CheckXmlFileWithXercesValidatorInspection"/>
<localInspection shortName="XmlDuplicatedId" bundle="messages.XmlBundle" key="xml.inspections.duplicate.id"
groupKey="xml.inspections.group.name" enabledByDefault="true" level="ERROR"
groupKey="xml.inspections.group.name" enabledByDefault="true" level="ERROR" runForWholeFile="true"
implementationClass="com.intellij.xml.util.XmlDuplicatedIdInspection"/>
<localInspection shortName="RequiredAttributes" bundle="messages.InspectionsBundle" key="inspection.required.attributes.display.name"
groupName="HTML" enabledByDefault="true" level="WARNING"
@@ -262,11 +262,11 @@
groupBundle="messages.InspectionsBundle" groupKey="group.names.probable.bugs" enabledByDefault="true" level="WARNING"
implementationClass="com.siyeh.ig.bugs.MismatchedArrayReadWriteInspection"/>
<localInspection suppressId="MismatchedQueryAndUpdateOfCollection" shortName="MismatchedCollectionQueryUpdate"
bundle="com.siyeh.InspectionGadgetsBundle" key="mismatched.update.collection.display.name"
bundle="com.siyeh.InspectionGadgetsBundle" key="mismatched.update.collection.display.name" runForWholeFile="true"
groupBundle="messages.InspectionsBundle" groupKey="group.names.probable.bugs" enabledByDefault="true" level="WARNING"
implementationClass="com.siyeh.ig.bugs.MismatchedCollectionQueryUpdateInspection"/>
<localInspection suppressId="MismatchedQueryAndUpdateOfStringBuilder" shortName="MismatchedStringBuilderQueryUpdate"
bundle="com.siyeh.InspectionGadgetsBundle" key="mismatched.string.builder.query.update.display.name"
bundle="com.siyeh.InspectionGadgetsBundle" key="mismatched.string.builder.query.update.display.name" runForWholeFile="true"
groupBundle="messages.InspectionsBundle" groupKey="group.names.probable.bugs" enabledByDefault="true" level="WARNING"
implementationClass="com.siyeh.ig.bugs.MismatchedStringBuilderQueryUpdateInspection"/>
<localInspection shortName="MisspelledCompareTo" bundle="com.siyeh.InspectionGadgetsBundle" key="misspelled.compareto.display.name"
@@ -462,7 +462,7 @@
groupKey="group.names.class.structure" enabledByDefault="false" level="WARNING"
implementationClass="com.siyeh.ig.classlayout.PublicConstructorInNonPublicClassInspection"/>
<localInspection shortName="Singleton" bundle="com.siyeh.InspectionGadgetsBundle" key="singleton.display.name"
groupBundle="messages.InspectionsBundle" groupKey="group.names.class.structure" enabledByDefault="false"
groupBundle="messages.InspectionsBundle" groupKey="group.names.class.structure" enabledByDefault="false" runForWholeFile="true"
level="WARNING" implementationClass="com.siyeh.ig.classlayout.SingletonInspection"/>
<localInspection shortName="StaticNonFinalField" bundle="com.siyeh.InspectionGadgetsBundle" key="static.non.final.field.display.name"
groupBundle="messages.InspectionsBundle" groupKey="group.names.class.structure" enabledByDefault="false"
@@ -902,7 +902,7 @@
<localInspection shortName="StaticImport" bundle="com.siyeh.InspectionGadgetsBundle" key="static.import.display.name"
groupBundle="messages.InspectionsBundle" groupKey="group.names.imports" enabledByDefault="false" level="WARNING"
implementationClass="com.siyeh.ig.imports.StaticImportInspection"/>
<localInspection shortName="UnusedImport" bundle="com.siyeh.InspectionGadgetsBundle" key="unused.import.display.name"
<localInspection shortName="UnusedImport" bundle="com.siyeh.InspectionGadgetsBundle" key="unused.import.display.name" runForWholeFile="true"
groupBundle="messages.InspectionsBundle" groupKey="group.names.imports" enabledByDefault="false" level="WARNING"
implementationClass="com.siyeh.ig.imports.UnusedImportInspection"/>
<localInspection shortName="AbstractClassExtendsConcreteClass" bundle="com.siyeh.InspectionGadgetsBundle"
@@ -1720,7 +1720,7 @@
level="WARNING" implementationClass="com.siyeh.ig.performance.FieldMayBeStaticInspection"/>
<localInspection shortName="InnerClassMayBeStatic" bundle="com.siyeh.InspectionGadgetsBundle"
key="inner.class.may.be.static.display.name" groupBundle="messages.InspectionsBundle"
groupKey="group.names.performance.issues" enabledByDefault="false" level="WARNING"
groupKey="group.names.performance.issues" enabledByDefault="false" level="WARNING" runForWholeFile="true"
implementationClass="com.siyeh.ig.performance.InnerClassMayBeStaticInspection"/>
<localInspection shortName="InstantiatingObjectToGetClassObject" bundle="com.siyeh.InspectionGadgetsBundle"
key="instantiating.object.to.get.class.object.display.name" groupBundle="messages.InspectionsBundle"
@@ -2091,10 +2091,10 @@
key="extends.object.display.name" groupBundle="messages.InspectionsBundle" groupKey="group.names.code.style.issues"
enabledByDefault="true" level="WARNING" implementationClass="com.siyeh.ig.style.ExtendsObjectInspection"/>
<localInspection shortName="FieldMayBeFinal" bundle="com.siyeh.InspectionGadgetsBundle" key="field.may.be.final.display.name"
groupBundle="messages.InspectionsBundle" groupKey="group.names.code.style.issues" enabledByDefault="false"
groupBundle="messages.InspectionsBundle" groupKey="group.names.code.style.issues" enabledByDefault="false" runForWholeFile="true"
level="WARNING" implementationClass="com.siyeh.ig.style.FieldMayBeFinalInspection"/>
<localInspection shortName="ImplicitCallToSuper" bundle="com.siyeh.InspectionGadgetsBundle" key="implicit.call.to.super.display.name"
groupBundle="messages.InspectionsBundle" groupKey="group.names.code.style.issues" enabledByDefault="false"
groupBundle="messages.InspectionsBundle" groupKey="group.names.code.style.issues" enabledByDefault="false" runForWholeFile="true"
level="WARNING" implementationClass="com.siyeh.ig.style.ImplicitCallToSuperInspection"/>
<localInspection shortName="ListIndexOfReplaceableByContains" bundle="com.siyeh.InspectionGadgetsBundle"
key="indexof.replaceable.by.contains.display.name" groupBundle="messages.InspectionsBundle"
@@ -2256,11 +2256,11 @@
enabledByDefault="false" level="WARNING" implementationClass="com.siyeh.ig.threading.ExtendsThreadInspection"/>
<localInspection shortName="FieldAccessedSynchronizedAndUnsynchronized" bundle="com.siyeh.InspectionGadgetsBundle"
key="field.accessed.synchronized.and.unsynchronized.display.name" groupBundle="messages.InspectionsBundle"
groupKey="group.names.threading.issues" enabledByDefault="false" level="WARNING"
groupKey="group.names.threading.issues" enabledByDefault="false" level="WARNING" runForWholeFile="true"
implementationClass="com.siyeh.ig.threading.FieldAccessedSynchronizedAndUnsynchronizedInspection"/>
<localInspection shortName="MethodMayBeSynchronized" bundle="com.siyeh.InspectionGadgetsBundle"
key="method.may.be.synchronized.display.name" groupBundle="messages.InspectionsBundle"
groupKey="group.names.threading.issues" enabledByDefault="false" level="WARNING"
groupKey="group.names.threading.issues" enabledByDefault="false" level="WARNING" runForWholeFile="true"
implementationClass="com.siyeh.ig.threading.MethodMayBeSynchronizedInspection"/>
<localInspection shortName="NakedNotify" bundle="com.siyeh.InspectionGadgetsBundle" key="naked.notify.display.name"
groupBundle="messages.InspectionsBundle" groupKey="group.names.threading.issues" enabledByDefault="false"
@@ -26,7 +26,7 @@
groupName="toString() issues" enabledByDefault="false" level="WARNING"
implementationClass="org.jetbrains.generate.tostring.inspection.ClassHasNoToStringMethodInspection"/>
<localInspection shortName="FieldNotUsedInToString" displayName="Field not used in toString() method" groupName="toString() issues"
enabledByDefault="false" level="WARNING"
enabledByDefault="false" level="WARNING" runForWholeFile="true"
implementationClass="org.jetbrains.generate.tostring.inspection.FieldNotUsedInToStringInspection"/>
</extensions>
@@ -20,6 +20,7 @@ import com.intellij.codeInsight.intention.IntentionManager;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.ex.InspectionProfileImpl;
import com.intellij.codeInspection.ex.InspectionProfileWrapper;
import com.intellij.codeInspection.ex.LocalInspectionToolWrapper;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiDocumentManager;
@@ -46,7 +47,7 @@ import java.util.Map;
*/
public class SpellCheckingEditorCustomization extends AbstractEditorCustomization {
private static final Map<String, LocalInspectionTool> SPELL_CHECK_TOOLS = new HashMap<String, LocalInspectionTool>();
private static final Map<String, LocalInspectionToolWrapper> SPELL_CHECK_TOOLS = new HashMap<String, LocalInspectionToolWrapper>();
private static final boolean READY = init();
@SuppressWarnings({"unchecked"})
@@ -58,7 +59,7 @@ public class SpellCheckingEditorCustomization extends AbstractEditorCustomizatio
for (Class<LocalInspectionTool> inspectionClass : inspectionClasses) {
try {
LocalInspectionTool tool = inspectionClass.newInstance();
SPELL_CHECK_TOOLS.put(tool.getID(), tool);
SPELL_CHECK_TOOLS.put(tool.getID(), new LocalInspectionToolWrapper(tool));
}
catch (Throwable e) {
return false;
@@ -144,19 +145,19 @@ public class SpellCheckingEditorCustomization extends AbstractEditorCustomizatio
}
@Override
public List<LocalInspectionTool> getHighlightingLocalInspectionTools(PsiElement element) {
List<LocalInspectionTool> result = new ArrayList<LocalInspectionTool>(myDelegate.getHighlightingLocalInspectionTools(element));
public List<LocalInspectionToolWrapper> getHighlightingLocalInspectionTools(PsiElement element) {
List<LocalInspectionToolWrapper> result = new ArrayList<LocalInspectionToolWrapper>(myDelegate.getHighlightingLocalInspectionTools(element));
if (myUseSpellCheck) {
Map<String, LocalInspectionTool> spellingTools = new HashMap<String, LocalInspectionTool>(SPELL_CHECK_TOOLS);
for (LocalInspectionTool tool : result) {
Map<String, LocalInspectionToolWrapper> spellingTools = new HashMap<String, LocalInspectionToolWrapper>(SPELL_CHECK_TOOLS);
for (LocalInspectionToolWrapper tool : result) {
spellingTools.remove(tool.getID());
}
result.addAll(spellingTools.values());
}
else {
for (int i = result.size() - 1; i >= 0; i--) {
LocalInspectionTool tool = result.get(i);
LocalInspectionToolWrapper tool = result.get(i);
if (SPELL_CHECK_TOOLS.containsKey(tool.getID())) {
result.remove(i);
}
+1 -1
View File
@@ -422,7 +422,7 @@
<localInspection shortName="Dependency" displayName="Illegal package dependencies" groupName="" enabledByDefault="true" level="ERROR"
implementationClass="com.intellij.codeInspection.dependencyViolation.DependencyInspection"/>
<localInspection shortName="FieldCanBeLocal" bundle="messages.InspectionsBundle" key="inspection.field.can.be.local.display.name"
groupName="Class structure" enabledByDefault="true" level="WARNING"
groupName="Class structure" enabledByDefault="true" level="WARNING" runForWholeFile="true"
implementationClass="com.intellij.codeInspection.varScopeCanBeNarrowed.FieldCanBeLocalInspection"/>
<localInspection shortName="NullableProblems" bundle="messages.InspectionsBundle" key="inspection.nullable.problems.display.name"
groupName="Probable bugs" enabledByDefault="true" level="WARNING"