diff options
Diffstat (limited to 'platform/analysis-impl/src')
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(); |