summaryrefslogtreecommitdiff
path: root/platform/analysis-impl/src/com
diff options
context:
space:
mode:
Diffstat (limited to 'platform/analysis-impl/src/com')
-rw-r--r--platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfo.java59
-rw-r--r--platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfoType.java4
-rw-r--r--platform/analysis-impl/src/com/intellij/codeInspection/InspectionEngine.java139
-rw-r--r--platform/analysis-impl/src/com/intellij/codeInspection/SmartHashMap.java206
-rw-r--r--platform/analysis-impl/src/com/intellij/codeInspection/actions/CleanupInspectionIntention.java119
-rw-r--r--platform/analysis-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextBase.java39
-rw-r--r--platform/analysis-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java5
-rw-r--r--platform/analysis-impl/src/com/intellij/profile/codeInspection/InspectionProfileManager.java3
8 files changed, 370 insertions, 204 deletions
diff --git a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfo.java b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfo.java
index 483f3c5b2839..88f230f8f2d3 100644
--- a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfo.java
+++ b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfo.java
@@ -21,11 +21,9 @@ import com.intellij.codeInsight.daemon.HighlightDisplayKey;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInsight.intention.IntentionManager;
import com.intellij.codeInspection.*;
-import com.intellij.codeInspection.actions.CleanupInspectionIntention;
import com.intellij.codeInspection.ex.GlobalInspectionToolWrapper;
import com.intellij.codeInspection.ex.InspectionToolWrapper;
import com.intellij.codeInspection.ex.LocalInspectionToolWrapper;
-import com.intellij.codeInspection.ex.QuickFixWrapper;
import com.intellij.lang.ASTNode;
import com.intellij.lang.annotation.Annotation;
import com.intellij.lang.annotation.HighlightSeverity;
@@ -114,8 +112,7 @@ public class HighlightInfo implements Segment {
String description = this.description;
if (toolTip == null || description == null || !toolTip.contains(DESCRIPTION_PLACEHOLDER)) return toolTip;
String decoded = StringUtil.replace(toolTip, DESCRIPTION_PLACEHOLDER, XmlStringUtil.escapeString(description));
- String niceTooltip = XmlStringUtil.wrapInHtml(decoded);
- return niceTooltip;
+ return XmlStringUtil.wrapInHtml(decoded);
}
private static String encodeTooltip(String toolTip, String description) {
@@ -177,10 +174,7 @@ public class HighlightInfo implements Segment {
return forcedTextAttributes;
}
- final EditorColorsScheme colorsScheme = getColorsScheme(editorColorsScheme);
- if (colorsScheme == null) {
- return null;
- }
+ EditorColorsScheme colorsScheme = getColorsScheme(editorColorsScheme);
if (forcedTextAttributesKey != null) {
return colorsScheme.getAttributes(forcedTextAttributesKey);
@@ -208,10 +202,7 @@ public class HighlightInfo implements Segment {
if (forcedTextAttributes != null && forcedTextAttributes.getErrorStripeColor() != null) {
return forcedTextAttributes.getErrorStripeColor();
}
- final EditorColorsScheme scheme = getColorsScheme(colorsScheme);
- if (scheme == null) {
- return null;
- }
+ EditorColorsScheme scheme = getColorsScheme(colorsScheme);
if (forcedTextAttributesKey != null) {
TextAttributes forcedTextAttributes = scheme.getAttributes(forcedTextAttributesKey);
if (forcedTextAttributes != null) {
@@ -244,7 +235,7 @@ public class HighlightInfo implements Segment {
}
- @Nullable
+ @NotNull
private static EditorColorsScheme getColorsScheme(@Nullable final EditorColorsScheme customScheme) {
if (customScheme != null) {
return customScheme;
@@ -325,6 +316,7 @@ public class HighlightInfo implements Segment {
return true;
}
+ @Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (!(obj instanceof HighlightInfo)) return false;
@@ -340,7 +332,7 @@ public class HighlightInfo implements Segment {
Comparing.strEqual(info.getDescription(), getDescription());
}
- public boolean equalsByActualOffset(HighlightInfo info) {
+ public boolean equalsByActualOffset(@NotNull HighlightInfo info) {
if (info == this) return true;
return info.getSeverity() == getSeverity() &&
@@ -353,10 +345,12 @@ public class HighlightInfo implements Segment {
Comparing.strEqual(info.getDescription(), getDescription());
}
+ @Override
public int hashCode() {
return startOffset;
}
+ @Override
@NonNls
public String toString() {
return getDescription() != null ? getDescription() : "";
@@ -658,7 +652,7 @@ public class HighlightInfo implements Segment {
public static final String ANNOTATOR_INSPECTION_SHORT_NAME = "Annotator";
- private static void appendFixes(@Nullable TextRange fixedRange, @NotNull HighlightInfo info, List<Annotation.QuickFixInfo> fixes) {
+ private static void appendFixes(@Nullable TextRange fixedRange, @NotNull HighlightInfo info, @Nullable List<Annotation.QuickFixInfo> fixes) {
if (fixes != null) {
for (final Annotation.QuickFixInfo quickFixInfo : fixes) {
TextRange range = fixedRange != null ? fixedRange : quickFixInfo.textRange;
@@ -670,6 +664,7 @@ public class HighlightInfo implements Segment {
}
}
+ @NotNull
public static HighlightInfoType convertType(@NotNull Annotation annotation) {
ProblemHighlightType type = annotation.getHighlightType();
if (type == ProblemHighlightType.LIKE_UNUSED_SYMBOL) return HighlightInfoType.UNUSED_SYMBOL;
@@ -688,6 +683,7 @@ public class HighlightInfo implements Segment {
HighlightInfoType.INFORMATION;
}
+ @NotNull
public static ProblemHighlightType convertType(HighlightInfoType infoType) {
if (infoType == HighlightInfoType.ERROR || infoType == HighlightInfoType.WRONG_REF) return ProblemHighlightType.ERROR;
if (infoType == HighlightInfoType.WARNING) return ProblemHighlightType.GENERIC_ERROR_OR_WARNING;
@@ -695,6 +691,7 @@ public class HighlightInfo implements Segment {
return ProblemHighlightType.WEAK_WARNING;
}
+ @NotNull
public static ProblemHighlightType convertSeverityToProblemHighlight(HighlightSeverity severity) {
return severity == HighlightSeverity.ERROR ? ProblemHighlightType.ERROR :
severity == HighlightSeverity.WARNING ? ProblemHighlightType.GENERIC_ERROR_OR_WARNING :
@@ -763,7 +760,7 @@ public class HighlightInfo implements Segment {
return myAction;
}
- public boolean canCleanup(PsiElement element) {
+ public boolean canCleanup(@NotNull PsiElement element) {
if (myCanCleanup == null) {
InspectionProfile profile = InspectionProjectProfileManager.getInstance(element.getProject()).getInspectionProfile();
final HighlightDisplayKey key = myKey;
@@ -794,7 +791,8 @@ public class HighlightInfo implements Segment {
if (options != null || key == null) {
return options;
}
- List<IntentionAction> newOptions = IntentionManager.getInstance().getStandardIntentionOptions(key, element);
+ IntentionManager intentionManager = IntentionManager.getInstance();
+ List<IntentionAction> newOptions = intentionManager.getStandardIntentionOptions(key, element);
InspectionProfile profile = InspectionProjectProfileManager.getInstance(element.getProject()).getInspectionProfile();
InspectionToolWrapper toolWrapper = profile.getInspectionTool(key.toString(), element);
if (!(toolWrapper instanceof LocalInspectionToolWrapper)) {
@@ -807,29 +805,9 @@ public class HighlightInfo implements Segment {
myCanCleanup = toolWrapper.isCleanupTool();
- InspectionProfileEntry wrappedTool;
- if (toolWrapper instanceof LocalInspectionToolWrapper) {
- wrappedTool = ((LocalInspectionToolWrapper)toolWrapper).getTool();
- Class aClass = myAction.getClass();
- if (myAction instanceof QuickFixWrapper) {
- aClass = ((QuickFixWrapper)myAction).getFix().getClass();
- }
- newOptions.add(new CleanupInspectionIntention(toolWrapper, aClass));
- }
- else if (toolWrapper instanceof GlobalInspectionToolWrapper) {
- wrappedTool = ((GlobalInspectionToolWrapper)toolWrapper).getTool();
- if (wrappedTool instanceof GlobalSimpleInspectionTool && (myAction instanceof LocalQuickFix || myAction instanceof QuickFixWrapper)) {
- Class aClass = myAction.getClass();
- if (myAction instanceof QuickFixWrapper) {
- aClass = ((QuickFixWrapper)myAction).getFix().getClass();
- }
- newOptions.add(new CleanupInspectionIntention(toolWrapper, aClass));
- }
- }
- else {
- throw new AssertionError("unknown tool: " + toolWrapper+"; key: "+myKey);
- }
-
+ ContainerUtil.addIfNotNull(newOptions, intentionManager.createFixAllIntention(toolWrapper, myAction));
+ InspectionProfileEntry wrappedTool = toolWrapper instanceof LocalInspectionToolWrapper ? ((LocalInspectionToolWrapper)toolWrapper).getTool()
+ : ((GlobalInspectionToolWrapper)toolWrapper).getTool();
if (wrappedTool instanceof CustomSuppressableInspectionTool) {
final IntentionAction[] suppressActions = ((CustomSuppressableInspectionTool)wrappedTool).getSuppressActions(element);
if (suppressActions != null) {
@@ -868,6 +846,7 @@ public class HighlightInfo implements Segment {
return myDisplayName;
}
+ @Override
@NonNls
public String toString() {
String text = getAction().getText();
diff --git a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfoType.java b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfoType.java
index 90116ea84f5b..d1615b93bce6 100644
--- a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfoType.java
+++ b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfoType.java
@@ -131,6 +131,7 @@ public interface HighlightInfoType {
return myAttributesKey;
}
+ @Override
@SuppressWarnings({"HardCodedStringLiteral"})
public String toString() {
return "HighlightInfoTypeImpl[severity=" + mySeverity + ", key=" + myAttributesKey + "]";
@@ -141,6 +142,7 @@ public interface HighlightInfoType {
myAttributesKey.writeExternal(element);
}
+ @Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
@@ -153,6 +155,7 @@ public interface HighlightInfoType {
return true;
}
+ @Override
public int hashCode() {
int result = mySeverity.hashCode();
result = 29 * result + myAttributesKey.hashCode();
@@ -187,6 +190,7 @@ public interface HighlightInfoType {
return myAttributesKey;
}
+ @Override
@SuppressWarnings({"HardCodedStringLiteral"})
public String toString() {
return "HighlightInfoTypeSeverityByKey[severity=" + myToolKey + ", key=" + myAttributesKey + "]";
diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/InspectionEngine.java b/platform/analysis-impl/src/com/intellij/codeInspection/InspectionEngine.java
index ab9581f1d7d9..713b545c6247 100644
--- a/platform/analysis-impl/src/com/intellij/codeInspection/InspectionEngine.java
+++ b/platform/analysis-impl/src/com/intellij/codeInspection/InspectionEngine.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,16 +25,21 @@ import com.intellij.codeInspection.reference.RefEntity;
import com.intellij.codeInspection.reference.RefManagerImpl;
import com.intellij.codeInspection.reference.RefVisitor;
import com.intellij.concurrency.JobLauncher;
+import com.intellij.lang.Language;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.EmptyProgressIndicator;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.openapi.project.DumbAware;
+import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.ProperTextRange;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.util.Processor;
import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.MultiMap;
+import com.intellij.util.containers.SmartHashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -78,29 +83,30 @@ public class InspectionEngine {
}
@NotNull
- public static List<ProblemDescriptor> inspect(@NotNull final List<LocalInspectionTool> tools,
+ public static List<ProblemDescriptor> inspect(@NotNull final List<LocalInspectionToolWrapper> toolWrappers,
@NotNull final PsiFile file,
@NotNull final InspectionManager iManager,
final boolean isOnTheFly,
boolean failFastOnAcquireReadAction,
@NotNull final ProgressIndicator indicator) {
- final Map<String, List<ProblemDescriptor>> problemDescriptors = inspectEx(tools, file, iManager, isOnTheFly, failFastOnAcquireReadAction, indicator);
+ final Map<String, List<ProblemDescriptor>> problemDescriptors = inspectEx(toolWrappers, file, iManager, isOnTheFly, failFastOnAcquireReadAction, indicator);
final List<ProblemDescriptor> result = new ArrayList<ProblemDescriptor>();
- for (List<ProblemDescriptor> group : problemDescriptors.values())
+ for (List<ProblemDescriptor> group : problemDescriptors.values()) {
result.addAll(group);
+ }
return result;
}
// public accessibility for Upsource
@NotNull
- public static Map<String, List<ProblemDescriptor>> inspectEx(@NotNull final List<LocalInspectionTool> tools,
+ public static Map<String, List<ProblemDescriptor>> inspectEx(@NotNull final List<LocalInspectionToolWrapper> toolWrappers,
@NotNull final PsiFile file,
@NotNull final InspectionManager iManager,
final boolean isOnTheFly,
boolean failFastOnAcquireReadAction,
@NotNull final ProgressIndicator indicator) {
- if (tools.isEmpty()) return Collections.emptyMap();
+ if (toolWrappers.isEmpty()) return Collections.emptyMap();
final Map<String, List<ProblemDescriptor>> resultDescriptors = new ConcurrentHashMap<String, List<ProblemDescriptor>>();
final List<PsiElement> elements = new ArrayList<PsiElement>();
@@ -109,32 +115,32 @@ public class InspectionEngine {
Divider.divideInsideAndOutside(file, range.getStartOffset(), range.getEndOffset(), range, elements, new ArrayList<ProperTextRange>(),
Collections.<PsiElement>emptyList(), Collections.<ProperTextRange>emptyList(), true, Condition.TRUE);
- boolean result = JobLauncher.getInstance().invokeConcurrentlyUnderProgress(
- tools, indicator, failFastOnAcquireReadAction,
- new Processor<LocalInspectionTool>() {
- @Override
- public boolean process(final LocalInspectionTool tool) {
- ProblemsHolder holder = new ProblemsHolder(iManager, file, isOnTheFly);
- createVisitorAndAcceptElements(tool, holder, isOnTheFly, session, elements, null);
-
- tool.inspectionFinished(session, holder);
-
- if (holder.hasResults()) {
- resultDescriptors.put(tool.getShortName(), ContainerUtil.filter(holder.getResults(), new Condition<ProblemDescriptor>() {
- @Override
- public boolean value(ProblemDescriptor descriptor) {
- PsiElement element = descriptor.getPsiElement();
- if (element != null) {
- return !SuppressionUtil.inspectionResultSuppressed(element, tool);
- }
- return true;
- }
- }));
- }
+ MultiMap<LocalInspectionToolWrapper, String> toolToLanguages = getToolsForElements(toolWrappers, DumbService.isDumb(file.getProject()), elements, Collections.<PsiElement>emptyList());
+ List<Map.Entry<LocalInspectionToolWrapper, Collection<String>>> entries = new ArrayList<Map.Entry<LocalInspectionToolWrapper, Collection<String>>>(toolToLanguages.entrySet());
+ Processor<Map.Entry<LocalInspectionToolWrapper, Collection<String>>> processor = new Processor<Map.Entry<LocalInspectionToolWrapper, Collection<String>>>() {
+ @Override
+ public boolean process(final Map.Entry<LocalInspectionToolWrapper, Collection<String>> entry) {
+ ProblemsHolder holder = new ProblemsHolder(iManager, file, isOnTheFly);
+ final LocalInspectionTool tool = entry.getKey().getTool();
+ Collection<String> languages = entry.getValue();
+ createVisitorAndAcceptElements(tool, holder, isOnTheFly, session, elements, languages);
- return true;
+ tool.inspectionFinished(session, holder);
+
+ if (holder.hasResults()) {
+ resultDescriptors.put(tool.getShortName(), ContainerUtil.filter(holder.getResults(), new Condition<ProblemDescriptor>() {
+ @Override
+ public boolean value(ProblemDescriptor descriptor) {
+ PsiElement element = descriptor.getPsiElement();
+ return element == null || !SuppressionUtil.inspectionResultSuppressed(element, tool);
+ }
+ }));
}
- });
+
+ return true;
+ }
+ };
+ JobLauncher.getInstance().invokeConcurrentlyUnderProgress(entries, indicator, failFastOnAcquireReadAction, processor);
return resultDescriptors;
}
@@ -149,8 +155,7 @@ public class InspectionEngine {
refManager.inspectionReadActionStarted();
try {
if (toolWrapper instanceof LocalInspectionToolWrapper) {
- LocalInspectionTool localTool = ((LocalInspectionToolWrapper)toolWrapper).getTool();
- return inspect(Collections.singletonList(localTool), file, inspectionManager, false, false, new EmptyProgressIndicator());
+ return inspect(Collections.singletonList((LocalInspectionToolWrapper)toolWrapper), file, inspectionManager, false, false, new EmptyProgressIndicator());
}
if (toolWrapper instanceof GlobalInspectionToolWrapper) {
final GlobalInspectionTool globalTool = ((GlobalInspectionToolWrapper)toolWrapper).getTool();
@@ -226,4 +231,74 @@ public class InspectionEngine {
}
}
}
+
+ @NotNull
+ public static <T extends InspectionToolWrapper> MultiMap<T, String> getToolsForElements(@NotNull List<T> toolWrappers,
+ boolean checkDumbAwareness,
+ @NotNull List<PsiElement> inside,
+ @NotNull List<PsiElement> outside) {
+ Set<Language> languages = new SmartHashSet<Language>();
+ Map<String, Language> langIds = new SmartHashMap<String, Language>();
+ Set<String> dialects = new SmartHashSet<String>();
+ calculateDialects(inside, languages, langIds, dialects);
+ calculateDialects(outside, languages, langIds, dialects);
+ MultiMap<T, String> toolToLanguages = new MultiMap<T, String>() {
+ @NotNull
+ @Override
+ protected Collection<String> createCollection() {
+ return new SmartHashSet<String>();
+ }
+
+ @NotNull
+ @Override
+ protected Collection<String> createEmptyCollection() {
+ return Collections.emptySet();
+ }
+ };
+ for (T wrapper : toolWrappers) {
+ ProgressManager.checkCanceled();
+ String language = wrapper.getLanguage();
+ if (language == null) {
+ InspectionProfileEntry tool = wrapper.getTool();
+ if (!checkDumbAwareness || tool instanceof DumbAware) {
+ toolToLanguages.put(wrapper, null);
+ }
+ continue;
+ }
+ Language lang = langIds.get(language);
+ if (lang != null) {
+ InspectionProfileEntry tool = wrapper.getTool();
+ if (!checkDumbAwareness || tool instanceof DumbAware) {
+ toolToLanguages.putValue(wrapper, language);
+ if (wrapper.applyToDialects()) {
+ for (Language dialect : lang.getDialects()) {
+ toolToLanguages.putValue(wrapper, dialect.getID());
+ }
+ }
+ }
+ }
+ else if (wrapper.applyToDialects() && dialects.contains(language)) {
+ InspectionProfileEntry tool = wrapper.getTool();
+ if (!checkDumbAwareness || tool instanceof DumbAware) {
+ toolToLanguages.putValue(wrapper, language);
+ }
+ }
+ }
+ return toolToLanguages;
+ }
+
+ private static void calculateDialects(@NotNull List<PsiElement> inside,
+ @NotNull Set<Language> languages,
+ @NotNull Map<String, Language> langIds,
+ @NotNull Set<String> dialects) {
+ for (PsiElement element : inside) {
+ Language language = element.getLanguage();
+ if (languages.add(language)) {
+ langIds.put(language.getID(), language);
+ for (Language dialect : language.getDialects()) {
+ dialects.add(dialect.getID());
+ }
+ }
+ }
+ }
}
diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/SmartHashMap.java b/platform/analysis-impl/src/com/intellij/codeInspection/SmartHashMap.java
new file mode 100644
index 000000000000..e66ae1ee379f
--- /dev/null
+++ b/platform/analysis-impl/src/com/intellij/codeInspection/SmartHashMap.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * 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.intellij.codeInspection;
+
+import com.intellij.openapi.util.Comparing;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.SingletonSet;
+import gnu.trove.THashMap;
+import gnu.trove.TObjectFunction;
+import gnu.trove.TObjectObjectProcedure;
+import gnu.trove.TObjectProcedure;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.AbstractMap;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Hash set (based on THashSet) which is fast when contains one or zero elements (avoids to calculate hash codes and call equals whenever possible).
+ * For other sizes it delegates to THashSet.
+ * Null keys are NOT PERMITTED.
+ */
+public class SmartHashMap<K,V> extends THashMap<K,V> {
+ private K theKey; // contains the only element if size() == 1
+ private V theValue;
+
+ @Override
+ public boolean containsKey(@NotNull Object key) {
+ K theKey = this.theKey;
+ if (theKey != null) {
+ return eq(theKey, (K)key);
+ }
+ return !super.isEmpty() && super.containsKey(key);
+ }
+
+ @Override
+ public V put(@NotNull K key, V value) {
+ K theKey = this.theKey;
+ if (theKey != null) {
+ if (eq(theKey, key)) return theValue;
+ super.put(theKey, theValue);
+ this.theKey = null;
+ // fallthrough
+ }
+ else if (super.isEmpty()) {
+ this.theKey = key;
+ theValue = value;
+ return null;
+ }
+ return super.put(key, value);
+ }
+
+ private boolean eq(K obj, K theKey) {
+ return theKey == obj || _hashingStrategy.equals(theKey, obj);
+ }
+
+ @Override
+ public boolean equals(@NotNull Object other) {
+ K theKey = this.theKey;
+ if (theKey != null) {
+ if (!(other instanceof Map) || ((Map)other).size() != 1 ) return false;
+ Map.Entry<K, V> entry = ((Map<K, V>)other).entrySet().iterator().next();
+ return eq(theKey, entry.getKey()) && Comparing.equal(theValue, entry.getValue());
+ }
+
+ return super.equals(other);
+ }
+
+ @Override
+ public int hashCode() {
+ K theKey = this.theKey;
+ if (theKey != null) {
+ return _hashingStrategy.computeHashCode(theKey);
+ }
+ return super.hashCode();
+ }
+
+ @Override
+ public void clear() {
+ theKey = null;
+ theValue = null;
+ super.clear();
+ }
+
+ @Override
+ public int size() {
+ K theKey = this.theKey;
+ if (theKey != null) {
+ return 1;
+ }
+ return super.size();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ K theKey = this.theKey;
+ return theKey == null && super.isEmpty();
+ }
+
+ @Override
+ public V remove(@NotNull Object obj) {
+ K theKey = this.theKey;
+ if (theKey != null) {
+ if (eq(theKey, (K)obj)) {
+ this.theKey = null;
+ V value = theValue;
+ theValue = null;
+ return value;
+ }
+ return null;
+ }
+ return super.remove(obj);
+ }
+
+ @NotNull
+ @Override
+ public Set<K> keySet() {
+ K theKey = this.theKey;
+ if (theKey != null) {
+ return new SingletonSet<K>(theKey);
+ }
+ return super.keySet();
+ }
+
+ @NotNull
+ @Override
+ public Collection<V> values() {
+ K theKey = this.theKey;
+ if (theKey != null) {
+ return new SingletonSet<V>(theValue);
+ }
+ return super.values();
+ }
+
+ @NotNull
+ @Override
+ public Set<Map.Entry<K, V>> entrySet() {
+ K theKey = this.theKey;
+ if (theKey != null) {
+ return new SingletonSet<Map.Entry<K, V>>(new AbstractMap.SimpleEntry<K, V>(theKey, theValue));
+ }
+ return super.entrySet();
+ }
+
+ @Override
+ public V get(Object key) {
+ K theKey = this.theKey;
+ if (theKey != null) {
+ return eq(theKey, (K)key) ? theValue : null;
+ }
+ return super.get(key);
+ }
+
+ @Override
+ public boolean containsValue(Object val) {
+ K theKey = this.theKey;
+ if (theKey != null) {
+ return Comparing.equal(theValue, val);
+ }
+ return super.containsValue(val);
+ }
+
+ @Override
+ public THashMap<K, V> clone() {
+ throw new IncorrectOperationException();
+ }
+
+ @Override
+ public void transformValues(TObjectFunction<V, V> function) {
+ throw new IncorrectOperationException();
+ }
+
+ @Override
+ public boolean retainEntries(TObjectObjectProcedure<K, V> procedure) {
+ throw new IncorrectOperationException();
+ }
+
+ @Override
+ public boolean forEachEntry(TObjectObjectProcedure<K, V> procedure) {
+ throw new IncorrectOperationException();
+ }
+
+ @Override
+ public boolean forEachValue(TObjectProcedure<V> procedure) {
+ throw new IncorrectOperationException();
+ }
+
+ @Override
+ public boolean forEachKey(TObjectProcedure<K> procedure) {
+ throw new IncorrectOperationException();
+ }
+}
diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/actions/CleanupInspectionIntention.java b/platform/analysis-impl/src/com/intellij/codeInspection/actions/CleanupInspectionIntention.java
deleted file mode 100644
index d28c9a3874f5..000000000000
--- a/platform/analysis-impl/src/com/intellij/codeInspection/actions/CleanupInspectionIntention.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * 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.intellij.codeInspection.actions;
-
-import com.intellij.codeInsight.FileModificationService;
-import com.intellij.codeInsight.intention.EmptyIntentionAction;
-import com.intellij.codeInsight.intention.HighPriorityAction;
-import com.intellij.codeInsight.intention.IntentionAction;
-import com.intellij.codeInspection.*;
-import com.intellij.codeInspection.ex.InspectionToolWrapper;
-import com.intellij.codeInspection.ex.LocalInspectionToolWrapper;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.progress.EmptyProgressIndicator;
-import com.intellij.openapi.progress.ProgressManager;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Computable;
-import com.intellij.psi.PsiDocumentManager;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiFile;
-import com.intellij.util.IncorrectOperationException;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-
-/**
- * User: anna
- * Date: 21-Feb-2006
- */
-public class CleanupInspectionIntention implements IntentionAction, HighPriorityAction {
- private final InspectionToolWrapper myToolWrapper;
- private final Class myQuickfixClass;
-
- public CleanupInspectionIntention(@NotNull InspectionToolWrapper toolWrapper, @NotNull Class quickFixClass) {
- myToolWrapper = toolWrapper;
- myQuickfixClass = quickFixClass;
- }
-
- @Override
- @NotNull
- public String getText() {
- return InspectionsBundle.message("fix.all.inspection.problems.in.file", myToolWrapper.getDisplayName());
- }
-
- @Override
- @NotNull
- public String getFamilyName() {
- return getText();
- }
-
- @Override
- public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException {
- if (!FileModificationService.getInstance().preparePsiElementForWrite(file)) return;
- final List<ProblemDescriptor> descriptions =
- ProgressManager.getInstance().runProcess(new Computable<List<ProblemDescriptor>>() {
- @Override
- public List<ProblemDescriptor> compute() {
- InspectionManager inspectionManager = InspectionManager.getInstance(project);
- return InspectionEngine.runInspectionOnFile(file, myToolWrapper, inspectionManager.createNewGlobalContext(false));
- }
- }, new EmptyProgressIndicator());
-
- Collections.sort(descriptions, new Comparator<CommonProblemDescriptor>() {
- @Override
- public int compare(final CommonProblemDescriptor o1, final CommonProblemDescriptor o2) {
- final ProblemDescriptorBase d1 = (ProblemDescriptorBase)o1;
- final ProblemDescriptorBase d2 = (ProblemDescriptorBase)o2;
- return d2.getTextRange().getStartOffset() - d1.getTextRange().getStartOffset();
- }
- });
- for (final ProblemDescriptor descriptor : descriptions) {
- final QuickFix[] fixes = descriptor.getFixes();
- if (fixes != null && fixes.length > 0) {
- for (final QuickFix<CommonProblemDescriptor> fix : fixes) {
- if (fix != null && fix.getClass().isAssignableFrom(myQuickfixClass)) {
- final PsiElement element = descriptor.getPsiElement();
- if (element != null && element.isValid()) {
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
- fix.applyFix(project, descriptor);
- }
- });
- PsiDocumentManager.getInstance(project).commitAllDocuments();
- }
- break;
- }
- }
- }
- }
- }
-
- @Override
- public boolean isAvailable(@NotNull final Project project, final Editor editor, final PsiFile file) {
- return myQuickfixClass != EmptyIntentionAction.class &&
- !(myToolWrapper instanceof LocalInspectionToolWrapper && ((LocalInspectionToolWrapper)myToolWrapper).isUnfair());
- }
-
- @Override
- public boolean startInWriteAction() {
- return false;
- }
-}
diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextBase.java b/platform/analysis-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextBase.java
index 35f1e4c520ad..2c230254f188 100644
--- a/platform/analysis-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextBase.java
+++ b/platform/analysis-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextBase.java
@@ -21,6 +21,7 @@ import com.intellij.codeInspection.*;
import com.intellij.codeInspection.lang.GlobalInspectionContextExtension;
import com.intellij.codeInspection.lang.InspectionExtensionsFactory;
import com.intellij.codeInspection.reference.*;
+import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.Extensions;
@@ -35,10 +36,7 @@ import com.intellij.openapi.util.UserDataHolderBase;
import com.intellij.profile.Profile;
import com.intellij.profile.codeInspection.InspectionProfileManager;
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
-import com.intellij.psi.PsiDocumentManager;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiFile;
-import com.intellij.psi.PsiManager;
+import com.intellij.psi.*;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.scope.packageSet.NamedScope;
import com.intellij.util.Function;
@@ -419,10 +417,35 @@ public class GlobalInspectionContextBase extends UserDataHolderBase implements G
globalContext.codeCleanup(project, scope, profile, null, runnable, false);
}
- public static void cleanupElements(Project project, Runnable runnable, PsiElement... scope) {
- GlobalInspectionContextBase globalContext = (GlobalInspectionContextBase)InspectionManager.getInstance(project).createNewGlobalContext(false);
- final InspectionProfile profile = InspectionProjectProfileManager.getInstance(project).getInspectionProfile();
- globalContext.codeCleanup(project, new AnalysisScope(new LocalSearchScope(scope), project), profile, null, runnable, true);
+ public static void cleanupElements(final Project project, final Runnable runnable, final PsiElement... scope) {
+ final List<SmartPsiElementPointer<PsiElement>> elements = new ArrayList<SmartPsiElementPointer<PsiElement>>();
+ final SmartPointerManager manager = SmartPointerManager.getInstance(project);
+ for (PsiElement element : scope) {
+ elements.add(manager.createSmartPsiElementPointer(element));
+ }
+
+ Runnable cleanupRunnable = new Runnable() {
+ public void run() {
+ final List<PsiElement> psiElements = new ArrayList<PsiElement>();
+ for (SmartPsiElementPointer<PsiElement> element : elements) {
+ PsiElement psiElement = element.getElement();
+ if (psiElement != null) {
+ psiElements.add(psiElement);
+ }
+ }
+ GlobalInspectionContextBase globalContext = (GlobalInspectionContextBase)InspectionManager.getInstance(project).createNewGlobalContext(false);
+ final InspectionProfile profile = InspectionProjectProfileManager.getInstance(project).getInspectionProfile();
+ AnalysisScope analysisScope = new AnalysisScope(new LocalSearchScope(psiElements.toArray(new PsiElement[psiElements.size()])), project);
+ globalContext.codeCleanup(project, analysisScope, profile, null, runnable, true);
+ }
+ };
+
+ Application application = ApplicationManager.getApplication();
+ if (application.isUnitTestMode() || !application.isWriteAccessAllowed()) {
+ cleanupRunnable.run();
+ } else {
+ application.invokeLater(cleanupRunnable);
+ }
}
public void close(boolean noSuspisiousCodeFound) {
diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java b/platform/analysis-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java
index f31e44e96e2c..f5ef75f8197b 100644
--- a/platform/analysis-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java
+++ b/platform/analysis-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java
@@ -102,10 +102,7 @@ public class RefManagerImpl extends RefManager {
}
if (scope != null) {
for (Module module : ModuleManager.getInstance(getProject()).getModules()) {
- //init all ref modules in scope
- if (scope.containsModule(module)) {
- getRefModule(module);
- }
+ getRefModule(module);
}
}
}
diff --git a/platform/analysis-impl/src/com/intellij/profile/codeInspection/InspectionProfileManager.java b/platform/analysis-impl/src/com/intellij/profile/codeInspection/InspectionProfileManager.java
index 7d0f203e94df..41f3c9b8e6b9 100644
--- a/platform/analysis-impl/src/com/intellij/profile/codeInspection/InspectionProfileManager.java
+++ b/platform/analysis-impl/src/com/intellij/profile/codeInspection/InspectionProfileManager.java
@@ -19,6 +19,7 @@ import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.components.NamedComponent;
import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.components.StoragePathMacros;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.profile.ApplicationProfileManager;
import com.intellij.profile.Profile;
@@ -41,7 +42,7 @@ import java.util.List;
*/
public abstract class InspectionProfileManager extends ApplicationProfileManager implements SeverityProvider, NamedComponent {
@NonNls protected static final String INSPECTION_DIR = "inspection";
- @NonNls protected static final String FILE_SPEC = "$ROOT_CONFIG$/" + INSPECTION_DIR;
+ @NonNls protected static final String FILE_SPEC = StoragePathMacros.ROOT_CONFIG + '/' + INSPECTION_DIR;
private final List<ProfileChangeAdapter> myProfileChangeAdapters = ContainerUtil.createLockFreeCopyOnWriteList();