diff --git a/platform/analysis-api/src/com/intellij/codeInspection/InjectionAwareSuppressQuickFix.java b/platform/analysis-api/src/com/intellij/codeInspection/InjectionAwareSuppressQuickFix.java
new file mode 100644
index 000000000000..27baddcd3220
--- /dev/null
+++ b/platform/analysis-api/src/com/intellij/codeInspection/InjectionAwareSuppressQuickFix.java
@@ -0,0 +1,18 @@
+package com.intellij.codeInspection;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.util.ThreeState;
+
+/**
+ * This kind of suppression fix allows to clients to specify whether the fix should
+ * be invoked on injected elements or on elements of host files.
+ *
+ * By default suppression fixes on injected elements are able to make suppression inside injection only.
+ * Whereas implementation of this interface will be provided for suppressing inside injection and in injection host.
+ * See {@link InspectionProfileEntry#getBatchSuppressActions(PsiElement)} for details.
+ */
+public interface InjectionAwareSuppressQuickFix extends SuppressQuickFix {
+ ThreeState isShouldBeAppliedToInjectionHost();
+
+ void setShouldBeAppliedToInjectionHost(ThreeState shouldBeAppliedToInjectionHost);
+}
diff --git a/platform/analysis-api/src/com/intellij/codeInspection/InspectionProfileEntry.java b/platform/analysis-api/src/com/intellij/codeInspection/InspectionProfileEntry.java
index af1e65c67598..886d02aa55a2 100644
--- a/platform/analysis-api/src/com/intellij/codeInspection/InspectionProfileEntry.java
+++ b/platform/analysis-api/src/com/intellij/codeInspection/InspectionProfileEntry.java
@@ -17,6 +17,7 @@ package com.intellij.codeInspection;
import com.intellij.codeHighlighting.HighlightDisplayLevel;
import com.intellij.lang.Language;
+import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.InvalidDataException;
@@ -24,8 +25,10 @@ import com.intellij.openapi.util.WriteExternalException;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.FileViewProvider;
import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiLanguageInjectionHost;
import com.intellij.psi.templateLanguages.TemplateLanguageFileViewProvider;
import com.intellij.util.ResourceUtil;
+import com.intellij.util.ThreeState;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.xmlb.SerializationFilter;
import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters;
@@ -44,14 +47,16 @@ import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
-import java.util.*;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.Set;
/**
* @author anna
* @since 28-Nov-2005
*/
-@SuppressWarnings("JavadocReference")
-public abstract class InspectionProfileEntry implements BatchSuppressableTool{
+public abstract class InspectionProfileEntry implements BatchSuppressableTool {
public static final String GENERAL_GROUP_NAME = InspectionsBundle.message("inspection.general.tools.group.name");
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.InspectionProfileEntry");
@@ -93,22 +98,52 @@ public abstract class InspectionProfileEntry implements BatchSuppressableTool{
Set fixes = new THashSet(new TObjectHashingStrategy() {
@Override
public int computeHashCode(SuppressQuickFix object) {
- return object.getName().hashCode();
+ int result = object instanceof InjectionAwareSuppressQuickFix
+ ? ((InjectionAwareSuppressQuickFix)object).isShouldBeAppliedToInjectionHost().hashCode()
+ : 0;
+ return 31 * result + object.getName().hashCode();
}
@Override
public boolean equals(SuppressQuickFix o1, SuppressQuickFix o2) {
+ if (o1 instanceof InjectionAwareSuppressQuickFix && o2 instanceof InjectionAwareSuppressQuickFix) {
+ if (((InjectionAwareSuppressQuickFix)o1).isShouldBeAppliedToInjectionHost() != ((InjectionAwareSuppressQuickFix)o2).isShouldBeAppliedToInjectionHost()) {
+ return false;
+ }
+ }
return o1.getName().equals(o2.getName());
}
});
+
Set suppressors = getSuppressors(element);
+ final PsiLanguageInjectionHost injectionHost = InjectedLanguageManager.getInstance(element.getProject()).getInjectionHost(element);
+ if (injectionHost != null) {
+ Set injectionHostSuppressors = getSuppressors(injectionHost);
+ for (InspectionSuppressor suppressor : injectionHostSuppressors) {
+ addAllSuppressActions(fixes, injectionHost, suppressor, ThreeState.YES, getShortName());
+ }
+ }
+
for (InspectionSuppressor suppressor : suppressors) {
- SuppressQuickFix[] actions = suppressor.getSuppressActions(element, getShortName());
- fixes.addAll(Arrays.asList(actions));
+ addAllSuppressActions(fixes, element, suppressor, injectionHost != null ? ThreeState.NO : ThreeState.UNSURE, getShortName());
}
return fixes.toArray(new SuppressQuickFix[fixes.size()]);
}
+ private static void addAllSuppressActions(Set fixes,
+ PsiElement element,
+ InspectionSuppressor suppressor,
+ ThreeState appliedToInjectionHost,
+ String toolShortName) {
+ final SuppressQuickFix[] actions = suppressor.getSuppressActions(element, toolShortName);
+ for (SuppressQuickFix action : actions) {
+ if (action instanceof InjectionAwareSuppressQuickFix) {
+ ((InjectionAwareSuppressQuickFix)action).setShouldBeAppliedToInjectionHost(appliedToInjectionHost);
+ }
+ fixes.add(action);
+ }
+ }
+
private boolean isSuppressed(@NotNull String toolId,
@NotNull InspectionSuppressor suppressor,
@NotNull PsiElement element) {
@@ -132,7 +167,9 @@ public abstract class InspectionProfileEntry implements BatchSuppressableTool{
ContainerUtil.addIfNotNull(suppressors, elementLanguageSuppressor);
return suppressors;
}
- return elementLanguageSuppressor != null ? Collections.singleton(elementLanguageSuppressor) : Collections.emptySet();
+ return elementLanguageSuppressor != null
+ ? Collections.singleton(elementLanguageSuppressor)
+ : Collections.emptySet();
}
public void cleanup(Project project) {
@@ -148,9 +185,9 @@ public abstract class InspectionProfileEntry implements BatchSuppressableTool{
protected volatile DefaultNameProvider myNameProvider = null;
/**
- * @see com.intellij.codeInspection.InspectionEP#groupDisplayName
- * @see com.intellij.codeInspection.InspectionEP#groupKey
- * @see com.intellij.codeInspection.InspectionEP#groupBundle
+ * @see InspectionEP#groupDisplayName
+ * @see InspectionEP#groupKey
+ * @see InspectionEP#groupBundle
*/
@Nls
@NotNull
@@ -166,7 +203,7 @@ public abstract class InspectionProfileEntry implements BatchSuppressableTool{
}
/**
- * @see com.intellij.codeInspection.InspectionEP#groupPath
+ * @see InspectionEP#groupPath
*/
@NotNull
public String[] getGroupPath() {
@@ -178,9 +215,9 @@ public abstract class InspectionProfileEntry implements BatchSuppressableTool{
}
/**
- * @see com.intellij.codeInspection.InspectionEP#displayName
- * @see com.intellij.codeInspection.InspectionEP#key
- * @see com.intellij.codeInspection.InspectionEP#bundle
+ * @see InspectionEP#displayName
+ * @see InspectionEP#key
+ * @see InspectionEP#bundle
*/
@Nls
@NotNull
@@ -198,7 +235,7 @@ public abstract class InspectionProfileEntry implements BatchSuppressableTool{
/**
* DO NOT OVERRIDE this method.
*
- * @see com.intellij.codeInspection.InspectionEP#shortName
+ * @see InspectionEP#shortName
*/
@NonNls
@NotNull
@@ -214,13 +251,13 @@ public abstract class InspectionProfileEntry implements BatchSuppressableTool{
@NotNull
public static String getShortName(@NotNull String className) {
- return StringUtil.trimEnd(StringUtil.trimEnd(className, "Inspection"),"InspectionBase");
+ return StringUtil.trimEnd(StringUtil.trimEnd(className, "Inspection"), "InspectionBase");
}
/**
* DO NOT OVERRIDE this method.
*
- * @see com.intellij.codeInspection.InspectionEP#level
+ * @see InspectionEP#level
*/
@NotNull
public HighlightDisplayLevel getDefaultLevel() {
@@ -230,7 +267,7 @@ public abstract class InspectionProfileEntry implements BatchSuppressableTool{
/**
* DO NOT OVERRIDE this method.
*
- * @see com.intellij.codeInspection.InspectionEP#enabledByDefault
+ * @see InspectionEP#enabledByDefault
*/
public boolean isEnabledByDefault() {
return false;
@@ -238,6 +275,7 @@ public abstract class InspectionProfileEntry implements BatchSuppressableTool{
/**
* This method is called each time UI is shown.
+ *
* @return null if no UI options required.
*/
@Nullable
@@ -348,7 +386,7 @@ public abstract class InspectionProfileEntry implements BatchSuppressableTool{
* Initialize inspection with project. Is called on project opened for all profiles as well as on profile creation.
*
* @param project to be associated with this entry
- * @deprecated this won't work for inspections configured via {@link com.intellij.codeInspection.InspectionEP}
+ * @deprecated this won't work for inspections configured via {@link InspectionEP}
*/
public void projectOpened(@NotNull Project project) {
}
@@ -357,7 +395,7 @@ public abstract class InspectionProfileEntry implements BatchSuppressableTool{
* Cleanup inspection settings corresponding to the project. Is called on project closed for all profiles as well as on profile deletion.
*
* @param project to be disassociated from this entry
- * @deprecated this won't work for inspections configured via {@link com.intellij.codeInspection.InspectionEP}
+ * @deprecated this won't work for inspections configured via {@link InspectionEP}
*/
public void projectClosed(@NotNull Project project) {
}
@@ -411,7 +449,8 @@ public abstract class InspectionProfileEntry implements BatchSuppressableTool{
if (descriptionUrl == null) return null;
return ResourceUtil.loadText(descriptionUrl);
}
- catch (IOException ignored) { }
+ catch (IOException ignored) {
+ }
return null;
}
diff --git a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/actions/AbstractBatchSuppressByNoInspectionCommentFix.java b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/actions/AbstractBatchSuppressByNoInspectionCommentFix.java
index 7a8c3e3c6cde..6bc8511bd5b5 100644
--- a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/actions/AbstractBatchSuppressByNoInspectionCommentFix.java
+++ b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/actions/AbstractBatchSuppressByNoInspectionCommentFix.java
@@ -17,9 +17,9 @@
package com.intellij.codeInsight.daemon.impl.actions;
import com.intellij.codeInsight.FileModificationService;
+import com.intellij.codeInspection.InjectionAwareSuppressQuickFix;
import com.intellij.codeInspection.InspectionsBundle;
import com.intellij.codeInspection.ProblemDescriptor;
-import com.intellij.codeInspection.SuppressQuickFix;
import com.intellij.codeInspection.SuppressionUtil;
import com.intellij.icons.AllIcons;
import com.intellij.lang.Language;
@@ -32,6 +32,7 @@ import com.intellij.psi.PsiManager;
import com.intellij.psi.PsiWhiteSpace;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.ThreeState;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -43,9 +44,10 @@ import java.util.List;
* @author Roman.Chernyatchik
* @date Aug 13, 2009
*/
-public abstract class AbstractBatchSuppressByNoInspectionCommentFix implements SuppressQuickFix, Iconable {
+public abstract class AbstractBatchSuppressByNoInspectionCommentFix implements InjectionAwareSuppressQuickFix, Iconable {
@NotNull protected final String myID;
private final boolean myReplaceOtherSuppressionIds;
+ private ThreeState myShouldBeAppliedToInjectionHost = ThreeState.UNSURE;
@Nullable
public abstract PsiElement getContainer(final PsiElement context);
@@ -60,6 +62,15 @@ public abstract class AbstractBatchSuppressByNoInspectionCommentFix implements S
myReplaceOtherSuppressionIds = replaceOtherSuppressionIds;
}
+ public void setShouldBeAppliedToInjectionHost(ThreeState shouldBeAppliedToInjectionHost) {
+ myShouldBeAppliedToInjectionHost = shouldBeAppliedToInjectionHost;
+ }
+
+ @Override
+ public ThreeState isShouldBeAppliedToInjectionHost() {
+ return myShouldBeAppliedToInjectionHost;
+ }
+
@NotNull
@Override
public String getName() {
diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/SuppressIntentionActionFromFix.java b/platform/analysis-impl/src/com/intellij/codeInspection/SuppressIntentionActionFromFix.java
index 3fc800e87879..d92101c386fb 100644
--- a/platform/analysis-impl/src/com/intellij/codeInspection/SuppressIntentionActionFromFix.java
+++ b/platform/analysis-impl/src/com/intellij/codeInspection/SuppressIntentionActionFromFix.java
@@ -21,6 +21,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.ThreeState;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
@@ -59,9 +60,15 @@ public class SuppressIntentionActionFromFix extends SuppressIntentionAction {
}
}
+ public ThreeState isShouldBeAppliedToInjectionHost() {
+ return myFix instanceof InjectionAwareSuppressQuickFix
+ ? ((InjectionAwareSuppressQuickFix)myFix).isShouldBeAppliedToInjectionHost()
+ : ThreeState.UNSURE;
+ }
+
public PsiElement getContainer(PsiElement element) {
return myFix instanceof AbstractBatchSuppressByNoInspectionCommentFix
- ? ((AbstractBatchSuppressByNoInspectionCommentFix )myFix).getContainer(element) : null;
+ ? ((AbstractBatchSuppressByNoInspectionCommentFix)myFix).getContainer(element) : null;
}
@Override
@@ -72,7 +79,7 @@ public class SuppressIntentionActionFromFix extends SuppressIntentionAction {
@NotNull
@Override
public String getText() {
- return myFix.getName();
+ return myFix.getName() + (isShouldBeAppliedToInjectionHost() == ThreeState.NO ? " in injection" : "");
}
@NotNull
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/ShowIntentionActionsHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/ShowIntentionActionsHandler.java
index 8ddebd7c383f..31c1ecd533d1 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/ShowIntentionActionsHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/ShowIntentionActionsHandler.java
@@ -27,6 +27,7 @@ import com.intellij.codeInsight.lookup.LookupEx;
import com.intellij.codeInsight.lookup.LookupManager;
import com.intellij.codeInsight.template.impl.TemplateManagerImpl;
import com.intellij.codeInsight.template.impl.TemplateState;
+import com.intellij.codeInspection.SuppressIntentionActionFromFix;
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.featureStatistics.FeatureUsageTrackerImpl;
import com.intellij.injected.editor.EditorWindow;
@@ -45,6 +46,7 @@ import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.PairProcessor;
+import com.intellij.util.ThreeState;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -107,6 +109,16 @@ public class ShowIntentionActionsHandler implements CodeInsightActionHandler {
private static boolean isAvailableHere(Editor editor, PsiFile psiFile, PsiElement psiElement, boolean inProject, IntentionAction action) {
try {
Project project = psiFile.getProject();
+ if (action instanceof SuppressIntentionActionFromFix) {
+ final ThreeState shouldBeAppliedToInjectionHost = ((SuppressIntentionActionFromFix)action).isShouldBeAppliedToInjectionHost();
+ if (editor instanceof EditorWindow && shouldBeAppliedToInjectionHost == ThreeState.YES) {
+ return false;
+ }
+ if (!(editor instanceof EditorWindow) && shouldBeAppliedToInjectionHost == ThreeState.NO) {
+ return false;
+ }
+ }
+
if (action instanceof PsiElementBaseIntentionAction) {
if (!inProject || psiElement == null || !((PsiElementBaseIntentionAction)action).isAvailable(project, editor, psiElement)) return false;
}