mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Introduced BatchSuppressableTool which, unlike CustomSuppressableInspectionTool, provides SuppressQuickFixes, not SuppressIntentionActions.
SuppressQuickFix doesn't need Editor so it can work in batches. These fixes are available via BatchSuppressManager. Reworked some inspections to extend BatchSuppressableTool instead of CustomSuppressableInspectionTool since they don't need Editor anyway. Similarly, instead of BaseJavaLocalInspectionTool there is BaseJavaBatchLocalInspectionTool.
This commit is contained in:
@@ -25,7 +25,6 @@ import com.intellij.ide.errorTreeView.NewErrorTreeViewPanel;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
|
||||
import com.intellij.openapi.module.LanguageLevelUtil;
|
||||
import com.intellij.openapi.module.Module;
|
||||
@@ -86,7 +85,7 @@ public class CompilerErrorTreeView extends NewErrorTreeViewPanel {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
suppressInspectionFix.invoke(project, null, file.findElementAt(navigatable.getOffset()));
|
||||
suppressInspectionFix.invoke(project, file.findElementAt(navigatable.getOffset()));
|
||||
}
|
||||
catch (IncorrectOperationException e1) {
|
||||
LOG.error(e1);
|
||||
@@ -139,7 +138,7 @@ public class CompilerErrorTreeView extends NewErrorTreeViewPanel {
|
||||
}
|
||||
final String id = text[0].substring(1, text[0].indexOf("]"));
|
||||
final SuppressFix suppressInspectionFix = getSuppressAction(id);
|
||||
final boolean available = suppressInspectionFix.isAvailable(project, null, context);
|
||||
final boolean available = suppressInspectionFix.isAvailable(project, context);
|
||||
presentation.setEnabled(available);
|
||||
presentation.setVisible(available);
|
||||
if (available) {
|
||||
@@ -151,13 +150,13 @@ public class CompilerErrorTreeView extends NewErrorTreeViewPanel {
|
||||
}
|
||||
}
|
||||
|
||||
protected SuppressFix getSuppressAction(final String id) {
|
||||
protected SuppressFix getSuppressAction(@NotNull final String id) {
|
||||
return new SuppressFix(id) {
|
||||
@Override
|
||||
@SuppressWarnings({"SimplifiableIfStatement"})
|
||||
public boolean isAvailable(@NotNull final Project project, final Editor editor, @NotNull final PsiElement context) {
|
||||
public boolean isAvailable(@NotNull final Project project, @NotNull final PsiElement context) {
|
||||
if (getContainer(context) instanceof PsiClass) return false;
|
||||
return super.isAvailable(project, editor, context);
|
||||
return super.isAvailable(project, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -170,7 +169,7 @@ public class CompilerErrorTreeView extends NewErrorTreeViewPanel {
|
||||
|
||||
private class SuppressJavacWarningForClassAction extends SuppressJavacWarningsAction {
|
||||
@Override
|
||||
protected SuppressFix getSuppressAction(final String id) {
|
||||
protected SuppressFix getSuppressAction(@NotNull final String id) {
|
||||
return new SuppressForClassFix(id){
|
||||
@Override
|
||||
protected boolean use15Suppressions(@NotNull final PsiDocCommentOwner container) {
|
||||
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class AbstractBaseJavaLocalInspectionTool extends LocalInspectionTool {
|
||||
/**
|
||||
* Override this to report problems at method level.
|
||||
*
|
||||
* @param method to check.
|
||||
* @param manager InspectionManager to ask for ProblemDescriptors from.
|
||||
* @param isOnTheFly true if called during on the fly editor highlighting. Called from Inspect Code action otherwise.
|
||||
* @return <code>null</code> if no problems found or not applicable at method level.
|
||||
*/
|
||||
@Nullable
|
||||
public ProblemDescriptor[] checkMethod(@NotNull PsiMethod method, @NotNull InspectionManager manager, boolean isOnTheFly) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this to report problems at class level.
|
||||
*
|
||||
* @param aClass to check.
|
||||
* @param manager InspectionManager to ask for ProblemDescriptors from.
|
||||
* @param isOnTheFly true if called during on the fly editor highlighting. Called from Inspect Code action otherwise.
|
||||
* @return <code>null</code> if no problems found or not applicable at class level.
|
||||
*/
|
||||
@Nullable
|
||||
public ProblemDescriptor[] checkClass(@NotNull PsiClass aClass, @NotNull InspectionManager manager, boolean isOnTheFly) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this to report problems at field level.
|
||||
*
|
||||
* @param field to check.
|
||||
* @param manager InspectionManager to ask for ProblemDescriptors from.
|
||||
* @param isOnTheFly true if called during on the fly editor highlighting. Called from Inspect Code action otherwise.
|
||||
* @return <code>null</code> if no problems found or not applicable at field level.
|
||||
*/
|
||||
@Nullable
|
||||
public ProblemDescriptor[] checkField(@NotNull PsiField field, @NotNull InspectionManager manager, boolean isOnTheFly) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this to report problems at file level.
|
||||
*
|
||||
* @param file to check.
|
||||
* @param manager InspectionManager to ask for ProblemDescriptors from.
|
||||
* @param isOnTheFly true if called during on the fly editor highlighting. Called from Inspect Code action otherwise.
|
||||
* @return <code>null</code> if no problems found or not applicable at file level.
|
||||
*/
|
||||
@Override
|
||||
@Nullable
|
||||
public ProblemDescriptor[] checkFile(@NotNull PsiFile file, @NotNull InspectionManager manager, boolean isOnTheFly) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, final boolean isOnTheFly) {
|
||||
return new JavaElementVisitor() {
|
||||
@Override public void visitMethod(PsiMethod method) {
|
||||
addDescriptors(checkMethod(method, holder.getManager(), isOnTheFly));
|
||||
}
|
||||
|
||||
@Override public void visitClass(PsiClass aClass) {
|
||||
addDescriptors(checkClass(aClass, holder.getManager(), isOnTheFly));
|
||||
}
|
||||
|
||||
@Override public void visitField(PsiField field) {
|
||||
addDescriptors(checkField(field, holder.getManager(), isOnTheFly));
|
||||
}
|
||||
|
||||
@Override public void visitFile(PsiFile file) {
|
||||
addDescriptors(checkFile(file, holder.getManager(), isOnTheFly));
|
||||
}
|
||||
private void addDescriptors(final ProblemDescriptor[] descriptors) {
|
||||
if (descriptors != null) {
|
||||
for (ProblemDescriptor descriptor : descriptors) {
|
||||
holder.registerProblem(descriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiNamedElement getProblemElement(final PsiElement psiElement) {
|
||||
return PsiTreeUtil.getNonStrictParentOfType(psiElement, PsiFile.class, PsiClass.class, PsiMethod.class, PsiField.class);
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public abstract class BaseJavaBatchLocalInspectionTool extends AbstractBaseJavaLocalInspectionTool implements BatchSuppressableTool {
|
||||
@NotNull
|
||||
@Override
|
||||
public SuppressQuickFix[] getBatchSuppressActions(@Nullable PsiElement element) {
|
||||
return SuppressQuickFix.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSuppressedFor(@NotNull PsiElement element) {
|
||||
return isSuppressedFor(element, this);
|
||||
}
|
||||
|
||||
public static boolean isSuppressedFor(@NotNull PsiElement element, @NotNull LocalInspectionTool tool) {
|
||||
final BatchSuppressManager manager = BatchSuppressManager.SERVICE.getInstance();
|
||||
String alternativeId;
|
||||
String id;
|
||||
return manager.isSuppressedFor(element, id = tool.getID()) ||
|
||||
(alternativeId = tool.getAlternativeID()) != null &&
|
||||
!alternativeId.equals(id) &&
|
||||
manager.isSuppressedFor(element, alternativeId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.psi.PsiDocCommentOwner;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiModifierListOwner;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public interface BatchSuppressManager {
|
||||
class SERVICE {
|
||||
public static BatchSuppressManager getInstance() {
|
||||
return ServiceManager.getService(BatchSuppressManager.class);
|
||||
}
|
||||
}
|
||||
@NotNull
|
||||
SuppressQuickFix[] createBatchSuppressActions(@NotNull HighlightDisplayKey key);
|
||||
|
||||
boolean isSuppressedFor(@NotNull PsiElement element, String toolId);
|
||||
|
||||
PsiElement getElementMemberSuppressedIn(@NotNull PsiDocCommentOwner owner, String inspectionToolID);
|
||||
|
||||
@Nullable
|
||||
PsiElement getAnnotationMemberSuppressedIn(@NotNull PsiModifierListOwner owner, String inspectionToolID);
|
||||
|
||||
@Nullable
|
||||
PsiElement getDocCommentToolSuppressedIn(@NotNull PsiDocCommentOwner owner, String inspectionToolID);
|
||||
|
||||
@NotNull
|
||||
Collection<String> getInspectionIdsSuppressedInAnnotation(@NotNull PsiModifierListOwner owner);
|
||||
|
||||
@Nullable
|
||||
String getSuppressedInspectionIdsIn(@NotNull PsiElement element);
|
||||
|
||||
@Nullable
|
||||
PsiElement getElementToolSuppressedIn(@NotNull PsiElement place, String toolId);
|
||||
|
||||
boolean canHave15Suppressions(@NotNull PsiElement file);
|
||||
|
||||
boolean alreadyHas14Suppressions(@NotNull PsiDocCommentOwner commentOwner);
|
||||
}
|
||||
+8
-9
@@ -16,12 +16,10 @@
|
||||
package com.intellij.codeInsight.daemon.impl.actions;
|
||||
|
||||
import com.intellij.codeInsight.FileModificationService;
|
||||
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
|
||||
import com.intellij.codeInspection.InspectionsBundle;
|
||||
import com.intellij.codeInspection.SuppressManager;
|
||||
import com.intellij.codeInspection.JavaSuppressionUtil;
|
||||
import com.intellij.codeInspection.SuppressionUtil;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.javadoc.PsiDocComment;
|
||||
@@ -44,7 +42,7 @@ public class SuppressAllForClassFix extends SuppressFix {
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected PsiDocCommentOwner getContainer(final PsiElement element) {
|
||||
public PsiDocCommentOwner getContainer(final PsiElement element) {
|
||||
PsiDocCommentOwner container = super.getContainer(element);
|
||||
if (container == null) {
|
||||
return null;
|
||||
@@ -66,17 +64,17 @@ public class SuppressAllForClassFix extends SuppressFix {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) throws IncorrectOperationException {
|
||||
public void invoke(@NotNull final Project project, @NotNull final PsiElement element) throws IncorrectOperationException {
|
||||
final PsiDocCommentOwner container = getContainer(element);
|
||||
LOG.assertTrue(container != null);
|
||||
if (!FileModificationService.getInstance().preparePsiElementForWrite(container)) return;
|
||||
if (use15Suppressions(container)) {
|
||||
final PsiModifierList modifierList = container.getModifierList();
|
||||
if (modifierList != null) {
|
||||
final PsiAnnotation annotation = modifierList.findAnnotation(SuppressManager.SUPPRESS_INSPECTIONS_ANNOTATION_NAME);
|
||||
final PsiAnnotation annotation = modifierList.findAnnotation(JavaSuppressionUtil.SUPPRESS_INSPECTIONS_ANNOTATION_NAME);
|
||||
if (annotation != null) {
|
||||
annotation.replace(JavaPsiFacade.getInstance(project).getElementFactory().createAnnotationFromText("@" +
|
||||
SuppressManager.SUPPRESS_INSPECTIONS_ANNOTATION_NAME + "(\"" +
|
||||
JavaSuppressionUtil.SUPPRESS_INSPECTIONS_ANNOTATION_NAME + "(\"" +
|
||||
SuppressionUtil.ALL + "\")", container));
|
||||
return;
|
||||
}
|
||||
@@ -89,12 +87,13 @@ public class SuppressAllForClassFix extends SuppressFix {
|
||||
if (noInspectionTag != null) {
|
||||
String tagText = "@" + SuppressionUtil.SUPPRESS_INSPECTIONS_TAG_NAME + " " + SuppressionUtil.ALL;
|
||||
noInspectionTag.replace(JavaPsiFacade.getInstance(project).getElementFactory().createDocTagFromText(tagText));
|
||||
DaemonCodeAnalyzer.getInstance(project).restart();
|
||||
// todo suppress
|
||||
//DaemonCodeAnalyzer.getInstance(project).restart();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
super.invoke(project, editor, element);
|
||||
super.invoke(project, element);
|
||||
}
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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.codeInsight.daemon.impl.actions;
|
||||
|
||||
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
|
||||
import com.intellij.codeInspection.JavaSuppressionUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class SuppressByJavaCommentFix extends SuppressByCommentFix {
|
||||
public SuppressByJavaCommentFix(@NotNull HighlightDisplayKey key) {
|
||||
super(key, PsiStatement.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public PsiElement getContainer(PsiElement context) {
|
||||
if (hasJspMethodCallAsParent(context)) return null;
|
||||
return PsiTreeUtil.getParentOfType(context, PsiStatement.class, false);
|
||||
}
|
||||
|
||||
private static boolean hasJspMethodCallAsParent(PsiElement context) {
|
||||
while (true) {
|
||||
PsiMethod method = PsiTreeUtil.getParentOfType(context, PsiMethod.class);
|
||||
if (method == null) return false;
|
||||
if (method instanceof SyntheticElement) return true;
|
||||
context = method;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createSuppression(@NotNull final Project project,
|
||||
@NotNull final PsiElement element,
|
||||
@NotNull final PsiElement container) throws IncorrectOperationException {
|
||||
PsiElement declaredElement = JavaSuppressionUtil.getElementToAnnotate(element, container);
|
||||
if (declaredElement == null) {
|
||||
suppressWithComment(project, element, container);
|
||||
}
|
||||
else {
|
||||
JavaSuppressionUtil.addSuppressAnnotation(project, container, (PsiLocalVariable)declaredElement, myID);
|
||||
}
|
||||
}
|
||||
|
||||
protected void suppressWithComment(Project project, PsiElement element, PsiElement container) {
|
||||
super.createSuppression(project, element, container);
|
||||
}
|
||||
}
|
||||
+159
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* 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.codeInsight.daemon.impl.actions;
|
||||
|
||||
import com.intellij.codeInsight.FileModificationService;
|
||||
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
|
||||
import com.intellij.codeInspection.InspectionsBundle;
|
||||
import com.intellij.codeInspection.JavaSuppressionUtil;
|
||||
import com.intellij.codeInspection.SuppressionUtil;
|
||||
import com.intellij.lang.java.JavaLanguage;
|
||||
import com.intellij.openapi.command.undo.UndoUtil;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleUtilCore;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.impl.storage.ClassPathStorageUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.javadoc.PsiDocComment;
|
||||
import com.intellij.psi.javadoc.PsiDocTag;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author ven
|
||||
*/
|
||||
public class SuppressFix extends AbstractBatchSuppressByNoInspectionCommentFix {
|
||||
private String myAlternativeID;
|
||||
|
||||
public SuppressFix(@NotNull HighlightDisplayKey key) {
|
||||
this(key.getID());
|
||||
myAlternativeID = HighlightDisplayKey.getAlternativeID(key);
|
||||
}
|
||||
|
||||
public SuppressFix(@NotNull String ID) {
|
||||
super(ID, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getText() {
|
||||
String myText = super.getText();
|
||||
return StringUtil.isEmpty(myText) ? "Suppress for member" : myText;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public PsiDocCommentOwner getContainer(final PsiElement context) {
|
||||
if (context == null || !context.getManager().isInProject(context)) {
|
||||
return null;
|
||||
}
|
||||
final PsiFile containingFile = context.getContainingFile();
|
||||
if (containingFile == null) {
|
||||
// for PsiDirectory
|
||||
return null;
|
||||
}
|
||||
if (!containingFile.getLanguage().isKindOf(JavaLanguage.INSTANCE) || context instanceof PsiFile) {
|
||||
return null;
|
||||
}
|
||||
PsiElement container = context;
|
||||
while (container instanceof PsiAnonymousClass || !(container instanceof PsiDocCommentOwner) || container instanceof PsiTypeParameter) {
|
||||
container = PsiTreeUtil.getParentOfType(container, PsiDocCommentOwner.class);
|
||||
if (container == null) return null;
|
||||
}
|
||||
return (PsiDocCommentOwner)container;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(@NotNull final Project project, @NotNull final PsiElement context) {
|
||||
PsiDocCommentOwner container = getContainer(context);
|
||||
boolean isValid = container != null && !(container instanceof PsiMethod && container instanceof SyntheticElement);
|
||||
if (!isValid) {
|
||||
return false;
|
||||
}
|
||||
setText(container instanceof PsiClass
|
||||
? InspectionsBundle.message("suppress.inspection.class")
|
||||
: container instanceof PsiMethod ? InspectionsBundle.message("suppress.inspection.method") : InspectionsBundle.message("suppress.inspection.field"));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(@NotNull final Project project, @NotNull final PsiElement element) throws IncorrectOperationException {
|
||||
if (doSuppress(project, getContainer(element))) return;
|
||||
// todo suppress
|
||||
//DaemonCodeAnalyzer.getInstance(project).restart();
|
||||
UndoUtil.markPsiFileForUndo(element.getContainingFile());
|
||||
}
|
||||
|
||||
private boolean doSuppress(@NotNull Project project, PsiDocCommentOwner container) {
|
||||
assert container != null;
|
||||
if (!FileModificationService.getInstance().preparePsiElementForWrite(container)) return true;
|
||||
if (use15Suppressions(container)) {
|
||||
final PsiModifierList modifierList = container.getModifierList();
|
||||
if (modifierList != null) {
|
||||
JavaSuppressionUtil.addSuppressAnnotation(project, container, container, getID(container));
|
||||
}
|
||||
}
|
||||
else {
|
||||
PsiDocComment docComment = container.getDocComment();
|
||||
PsiManager manager = PsiManager.getInstance(project);
|
||||
if (docComment == null) {
|
||||
String commentText = "/** @" + SuppressionUtil.SUPPRESS_INSPECTIONS_TAG_NAME + " " + getID(container) + "*/";
|
||||
docComment = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createDocCommentFromText(commentText);
|
||||
PsiElement firstChild = container.getFirstChild();
|
||||
container.addBefore(docComment, firstChild);
|
||||
}
|
||||
else {
|
||||
PsiDocTag noInspectionTag = docComment.findTagByName(SuppressionUtil.SUPPRESS_INSPECTIONS_TAG_NAME);
|
||||
if (noInspectionTag != null) {
|
||||
String tagText = noInspectionTag.getText() + ", " + getID(container);
|
||||
noInspectionTag.replace(JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createDocTagFromText(tagText));
|
||||
}
|
||||
else {
|
||||
String tagText = "@" + SuppressionUtil.SUPPRESS_INSPECTIONS_TAG_NAME + " " + getID(container);
|
||||
docComment.add(JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createDocTagFromText(tagText));
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean use15Suppressions(@NotNull PsiDocCommentOwner container) {
|
||||
return JavaSuppressionUtil.canHave15Suppressions(container) &&
|
||||
!JavaSuppressionUtil.alreadyHas14Suppressions(container);
|
||||
}
|
||||
|
||||
private String getID(@NotNull PsiElement place) {
|
||||
String id = getID(place, myAlternativeID);
|
||||
return id != null ? id : myID;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static String getID(@NotNull PsiElement place, String alternativeID) {
|
||||
if (alternativeID != null) {
|
||||
final Module module = ModuleUtilCore.findModuleForPsiElement(place);
|
||||
if (module != null) {
|
||||
if (!ClassPathStorageUtil.isDefaultStorage(module)) {
|
||||
return alternativeID;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -39,7 +39,8 @@ public class SuppressForClassFix extends SuppressFix {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable protected PsiDocCommentOwner getContainer(final PsiElement element) {
|
||||
@Nullable
|
||||
public PsiDocCommentOwner getContainer(final PsiElement element) {
|
||||
PsiDocCommentOwner container = super.getContainer(element);
|
||||
if (container == null || container instanceof PsiClass){
|
||||
return null;
|
||||
+6
-6
@@ -16,7 +16,7 @@
|
||||
package com.intellij.codeInsight.daemon.impl.actions;
|
||||
|
||||
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.codeInspection.JavaSuppressionUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
@@ -27,25 +27,25 @@ import org.jetbrains.annotations.Nullable;
|
||||
* User: anna
|
||||
*/
|
||||
public class SuppressLocalWithCommentFix extends SuppressByJavaCommentFix {
|
||||
public SuppressLocalWithCommentFix(HighlightDisplayKey key) {
|
||||
public SuppressLocalWithCommentFix(@NotNull HighlightDisplayKey key) {
|
||||
super(key);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected PsiElement getContainer(PsiElement context) {
|
||||
public PsiElement getContainer(PsiElement context) {
|
||||
final PsiElement container = super.getContainer(context);
|
||||
if (container != null) {
|
||||
final PsiElement elementToAnnotate = getElementToAnnotate(context, container);
|
||||
final PsiElement elementToAnnotate = JavaSuppressionUtil.getElementToAnnotate(context, container);
|
||||
if (elementToAnnotate == null) return null;
|
||||
}
|
||||
return container;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createSuppression(Project project, Editor editor, PsiElement element, PsiElement container)
|
||||
protected void createSuppression(@NotNull Project project, @NotNull PsiElement element, @NotNull PsiElement container)
|
||||
throws IncorrectOperationException {
|
||||
suppressWithComment(project, editor, element, container);
|
||||
suppressWithComment(project, element, container);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
+18
-24
@@ -15,35 +15,31 @@
|
||||
*/
|
||||
package com.intellij.codeInsight.daemon.impl.actions;
|
||||
|
||||
import com.intellij.codeInsight.FileModificationService;
|
||||
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
|
||||
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
|
||||
import com.intellij.codeInspection.InspectionsBundle;
|
||||
import com.intellij.codeInspection.SuppressIntentionAction;
|
||||
import com.intellij.codeInspection.SuppressManager;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.codeInspection.JavaSuppressionUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiModifierList;
|
||||
import com.intellij.psi.PsiModifierListOwner;
|
||||
import com.intellij.psi.PsiParameter;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author ven
|
||||
*/
|
||||
public class SuppressParameterFix extends SuppressIntentionAction {
|
||||
private final String myID;
|
||||
public class SuppressParameterFix extends AbstractBatchSuppressByNoInspectionCommentFix {
|
||||
private String myAlternativeID;
|
||||
|
||||
public SuppressParameterFix(HighlightDisplayKey key) {
|
||||
public SuppressParameterFix(@NotNull HighlightDisplayKey key) {
|
||||
this(key.getID());
|
||||
myAlternativeID = HighlightDisplayKey.getAlternativeID(key);
|
||||
}
|
||||
|
||||
public SuppressParameterFix(String ID) {
|
||||
myID = ID;
|
||||
super(ID, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -52,28 +48,26 @@ public class SuppressParameterFix extends SuppressIntentionAction {
|
||||
return "Suppress for parameter";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
@NotNull
|
||||
public String getFamilyName() {
|
||||
return InspectionsBundle.message("suppress.inspection.family");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(@NotNull final Project project, final Editor editor, @NotNull final PsiElement context) {
|
||||
public PsiElement getContainer(PsiElement context) {
|
||||
PsiParameter psiParameter = PsiTreeUtil.getParentOfType(context, PsiParameter.class, false);
|
||||
return psiParameter != null && SuppressManager.getInstance().canHave15Suppressions(psiParameter);
|
||||
return psiParameter != null && JavaSuppressionUtil.canHave15Suppressions(psiParameter) ? psiParameter : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) throws IncorrectOperationException {
|
||||
PsiParameter container = PsiTreeUtil.getParentOfType(element, PsiParameter.class, false);
|
||||
assert container != null;
|
||||
if (!FileModificationService.getInstance().preparePsiElementForWrite(container)) return;
|
||||
protected boolean replaceSuppressionComments(PsiElement container) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createSuppression(@NotNull Project project, @NotNull PsiElement element, @NotNull PsiElement cont)
|
||||
throws IncorrectOperationException {
|
||||
PsiModifierListOwner container = (PsiModifierListOwner)cont;
|
||||
final PsiModifierList modifierList = container.getModifierList();
|
||||
if (modifierList != null) {
|
||||
final String id = SuppressFix.getID(container, myAlternativeID);
|
||||
SuppressFix.addSuppressAnnotation(project, editor, container, container, id != null ? id : myID);
|
||||
JavaSuppressionUtil.addSuppressAnnotation(project, container, container, id != null ? id : myID);
|
||||
}
|
||||
DaemonCodeAnalyzer.getInstance(project).restart();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
|
||||
import com.intellij.codeInsight.daemon.impl.actions.*;
|
||||
import com.intellij.psi.PsiDocCommentOwner;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiModifierListOwner;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class BatchSuppressManagerImpl implements BatchSuppressManager {
|
||||
@NotNull
|
||||
@Override
|
||||
public SuppressQuickFix[] createBatchSuppressActions(@NotNull HighlightDisplayKey displayKey) {
|
||||
return new SuppressQuickFix[] {
|
||||
new SuppressByJavaCommentFix(displayKey),
|
||||
new SuppressLocalWithCommentFix(displayKey),
|
||||
new SuppressParameterFix(displayKey),
|
||||
new SuppressFix(displayKey),
|
||||
new SuppressForClassFix(displayKey),
|
||||
new SuppressAllForClassFix()
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSuppressedFor(@NotNull final PsiElement element, final String toolId) {
|
||||
return JavaSuppressionUtil.getElementToolSuppressedIn(element, toolId) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public PsiElement getElementMemberSuppressedIn(@NotNull final PsiDocCommentOwner owner, final String inspectionToolID) {
|
||||
return JavaSuppressionUtil.getElementMemberSuppressedIn(owner, inspectionToolID);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public PsiElement getAnnotationMemberSuppressedIn(@NotNull final PsiModifierListOwner owner, final String inspectionToolID) {
|
||||
return JavaSuppressionUtil.getAnnotationMemberSuppressedIn(owner, inspectionToolID);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public PsiElement getDocCommentToolSuppressedIn(@NotNull final PsiDocCommentOwner owner, final String inspectionToolID) {
|
||||
return JavaSuppressionUtil.getDocCommentToolSuppressedIn(owner, inspectionToolID);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Collection<String> getInspectionIdsSuppressedInAnnotation(@NotNull final PsiModifierListOwner owner) {
|
||||
return JavaSuppressionUtil.getInspectionIdsSuppressedInAnnotation(owner);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String getSuppressedInspectionIdsIn(@NotNull PsiElement element) {
|
||||
return JavaSuppressionUtil.getSuppressedInspectionIdsIn(element);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public PsiElement getElementToolSuppressedIn(@NotNull final PsiElement place, final String toolId) {
|
||||
return JavaSuppressionUtil.getElementToolSuppressedIn(place, toolId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canHave15Suppressions(@NotNull final PsiElement file) {
|
||||
return JavaSuppressionUtil.canHave15Suppressions(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean alreadyHas14Suppressions(@NotNull final PsiDocCommentOwner commentOwner) {
|
||||
return JavaSuppressionUtil.alreadyHas14Suppressions(commentOwner);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,320 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.intellij.codeInsight.AnnotationUtil;
|
||||
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzerSettings;
|
||||
import com.intellij.codeInsight.intention.AddAnnotationPsiFix;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleUtilCore;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.JavaSdkVersion;
|
||||
import com.intellij.openapi.projectRoots.JdkVersionUtil;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.roots.ModuleRootManager;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiVariableEx;
|
||||
import com.intellij.psi.javadoc.PsiDocComment;
|
||||
import com.intellij.psi.javadoc.PsiDocTag;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.annotation.Generated;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
public class JavaSuppressionUtil {
|
||||
public static final String SUPPRESS_INSPECTIONS_ANNOTATION_NAME = "java.lang.SuppressWarnings";
|
||||
public static boolean alreadyHas14Suppressions(@NotNull PsiDocCommentOwner commentOwner) {
|
||||
final PsiDocComment docComment = commentOwner.getDocComment();
|
||||
return docComment != null && docComment.findTagByName(SuppressionUtil.SUPPRESS_INSPECTIONS_TAG_NAME) != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getInspectionIdSuppressedInAnnotationAttribute(PsiElement element) {
|
||||
if (element instanceof PsiLiteralExpression) {
|
||||
final Object value = ((PsiLiteralExpression)element).getValue();
|
||||
if (value instanceof String) {
|
||||
return (String)value;
|
||||
}
|
||||
}
|
||||
else if (element instanceof PsiReferenceExpression) {
|
||||
final PsiElement psiElement = ((PsiReferenceExpression)element).resolve();
|
||||
if (psiElement instanceof PsiVariableEx) {
|
||||
final Object val = ((PsiVariableEx)psiElement).computeConstantValue(new HashSet<PsiVariable>());
|
||||
if (val instanceof String) {
|
||||
return (String)val;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Collection<String> getInspectionIdsSuppressedInAnnotation(final PsiModifierList modifierList) {
|
||||
if (modifierList == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
final PsiModifierListOwner owner = (PsiModifierListOwner)modifierList.getParent();
|
||||
PsiAnnotation annotation = AnnotationUtil.findAnnotation(owner, SUPPRESS_INSPECTIONS_ANNOTATION_NAME);
|
||||
if (annotation == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
final PsiNameValuePair[] attributes = annotation.getParameterList().getAttributes();
|
||||
if (attributes.length == 0) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
final PsiAnnotationMemberValue attributeValue = attributes[0].getValue();
|
||||
Collection<String> result = new ArrayList<String>();
|
||||
if (attributeValue instanceof PsiArrayInitializerMemberValue) {
|
||||
final PsiAnnotationMemberValue[] initializers = ((PsiArrayInitializerMemberValue)attributeValue).getInitializers();
|
||||
for (PsiAnnotationMemberValue annotationMemberValue : initializers) {
|
||||
final String id = getInspectionIdSuppressedInAnnotationAttribute(annotationMemberValue);
|
||||
if (id != null) {
|
||||
result.add(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
final String id = getInspectionIdSuppressedInAnnotationAttribute(attributeValue);
|
||||
if (id != null) {
|
||||
result.add(id);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static PsiElement getElementMemberSuppressedIn(@NotNull PsiDocCommentOwner owner, String inspectionToolID) {
|
||||
PsiElement element = getDocCommentToolSuppressedIn(owner, inspectionToolID);
|
||||
if (element != null) return element;
|
||||
element = getAnnotationMemberSuppressedIn(owner, inspectionToolID);
|
||||
if (element != null) return element;
|
||||
PsiDocCommentOwner classContainer = PsiTreeUtil.getParentOfType(owner, PsiDocCommentOwner.class);
|
||||
while (classContainer != null) {
|
||||
element = getDocCommentToolSuppressedIn(classContainer, inspectionToolID);
|
||||
if (element != null) return element;
|
||||
|
||||
element = getAnnotationMemberSuppressedIn(classContainer, inspectionToolID);
|
||||
if (element != null) return element;
|
||||
|
||||
classContainer = PsiTreeUtil.getParentOfType(classContainer, PsiDocCommentOwner.class);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static PsiElement getAnnotationMemberSuppressedIn(@NotNull PsiModifierListOwner owner, String inspectionToolID) {
|
||||
final PsiAnnotation generatedAnnotation = AnnotationUtil.findAnnotation(owner, Generated.class.getName());
|
||||
if (generatedAnnotation != null) return generatedAnnotation;
|
||||
PsiModifierList modifierList = owner.getModifierList();
|
||||
Collection<String> suppressedIds = getInspectionIdsSuppressedInAnnotation(modifierList);
|
||||
for (String ids : suppressedIds) {
|
||||
if (SuppressionUtil.isInspectionToolIdMentioned(ids, inspectionToolID)) {
|
||||
return modifierList != null ? AnnotationUtil.findAnnotation(owner, SUPPRESS_INSPECTIONS_ANNOTATION_NAME) : null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static PsiElement getDocCommentToolSuppressedIn(@NotNull PsiDocCommentOwner owner, String inspectionToolID) {
|
||||
PsiDocComment docComment = owner.getDocComment();
|
||||
if (docComment == null && owner.getParent() instanceof PsiDeclarationStatement) {
|
||||
final PsiElement el = PsiTreeUtil.skipSiblingsBackward(owner.getParent(), PsiWhiteSpace.class);
|
||||
if (el instanceof PsiDocComment) {
|
||||
docComment = (PsiDocComment)el;
|
||||
}
|
||||
}
|
||||
if (docComment != null) {
|
||||
PsiDocTag inspectionTag = docComment.findTagByName(SuppressionUtil.SUPPRESS_INSPECTIONS_TAG_NAME);
|
||||
if (inspectionTag != null) {
|
||||
final PsiElement[] dataElements = inspectionTag.getDataElements();
|
||||
for (PsiElement dataElement : dataElements) {
|
||||
String valueText = dataElement.getText();
|
||||
if (SuppressionUtil.isInspectionToolIdMentioned(valueText, inspectionToolID)) {
|
||||
return docComment;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static Collection<String> getInspectionIdsSuppressedInAnnotation(@NotNull PsiModifierListOwner owner) {
|
||||
if (!PsiUtil.isLanguageLevel5OrHigher(owner)) return Collections.emptyList();
|
||||
PsiModifierList modifierList = owner.getModifierList();
|
||||
return getInspectionIdsSuppressedInAnnotation(modifierList);
|
||||
}
|
||||
|
||||
static String getSuppressedInspectionIdsIn(@NotNull PsiElement element) {
|
||||
if (element instanceof PsiComment) {
|
||||
String text = element.getText();
|
||||
Matcher matcher = SuppressionUtil.SUPPRESS_IN_LINE_COMMENT_PATTERN.matcher(text);
|
||||
if (matcher.matches()) {
|
||||
return matcher.group(1).trim();
|
||||
}
|
||||
}
|
||||
if (element instanceof PsiDocCommentOwner) {
|
||||
PsiDocComment docComment = ((PsiDocCommentOwner)element).getDocComment();
|
||||
if (docComment != null) {
|
||||
PsiDocTag inspectionTag = docComment.findTagByName(SuppressionUtil.SUPPRESS_INSPECTIONS_TAG_NAME);
|
||||
if (inspectionTag != null) {
|
||||
String valueText = "";
|
||||
for (PsiElement dataElement : inspectionTag.getDataElements()) {
|
||||
valueText += dataElement.getText();
|
||||
}
|
||||
return valueText;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (element instanceof PsiModifierListOwner) {
|
||||
Collection<String> suppressedIds = getInspectionIdsSuppressedInAnnotation((PsiModifierListOwner)element);
|
||||
return suppressedIds.isEmpty() ? null : StringUtil.join(suppressedIds, ",");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static PsiElement getElementToolSuppressedIn(@NotNull final PsiElement place, final String toolId) {
|
||||
if (place instanceof PsiFile) return null;
|
||||
return ApplicationManager.getApplication().runReadAction(new Computable<PsiElement>() {
|
||||
@Override
|
||||
@Nullable
|
||||
public PsiElement compute() {
|
||||
final PsiElement statement = SuppressionUtil.getStatementToolSuppressedIn(place, toolId, PsiStatement.class);
|
||||
if (statement != null) {
|
||||
return statement;
|
||||
}
|
||||
|
||||
PsiVariable local = PsiTreeUtil.getParentOfType(place, PsiVariable.class);
|
||||
if (local != null && getAnnotationMemberSuppressedIn(local, toolId) != null) {
|
||||
PsiModifierList modifierList = local.getModifierList();
|
||||
return modifierList != null ? modifierList.findAnnotation(SUPPRESS_INSPECTIONS_ANNOTATION_NAME) : null;
|
||||
}
|
||||
|
||||
PsiDocCommentOwner container = PsiTreeUtil.getNonStrictParentOfType(place, PsiDocCommentOwner.class);
|
||||
while (true) {
|
||||
if (!(container instanceof PsiTypeParameter)) break;
|
||||
container = PsiTreeUtil.getParentOfType(container, PsiDocCommentOwner.class);
|
||||
}
|
||||
|
||||
if (container != null) {
|
||||
PsiElement element = getElementMemberSuppressedIn(container, toolId);
|
||||
if (element != null) return element;
|
||||
}
|
||||
PsiDocCommentOwner classContainer = PsiTreeUtil.getParentOfType(container, PsiDocCommentOwner.class, true);
|
||||
if (classContainer != null) {
|
||||
PsiElement element = getElementMemberSuppressedIn(classContainer, toolId);
|
||||
if (element != null) return element;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void addSuppressAnnotation(@NotNull Project project,
|
||||
final PsiElement container,
|
||||
final PsiModifierListOwner modifierOwner,
|
||||
@NotNull String id) throws IncorrectOperationException {
|
||||
PsiAnnotation annotation = AnnotationUtil.findAnnotation(modifierOwner, SUPPRESS_INSPECTIONS_ANNOTATION_NAME);
|
||||
final PsiAnnotation newAnnotation = createNewAnnotation(project, container, annotation, id);
|
||||
if (newAnnotation != null) {
|
||||
if (annotation != null && annotation.isPhysical()) {
|
||||
annotation.replace(newAnnotation);
|
||||
}
|
||||
else {
|
||||
final PsiNameValuePair[] attributes = newAnnotation.getParameterList().getAttributes();
|
||||
new AddAnnotationPsiFix(SUPPRESS_INSPECTIONS_ANNOTATION_NAME, modifierOwner, attributes).applyFix();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static PsiAnnotation createNewAnnotation(@NotNull Project project,
|
||||
PsiElement container,
|
||||
PsiAnnotation annotation,
|
||||
@NotNull String id) throws IncorrectOperationException {
|
||||
if (annotation == null) {
|
||||
return JavaPsiFacade.getInstance(project).getElementFactory()
|
||||
.createAnnotationFromText("@" + SUPPRESS_INSPECTIONS_ANNOTATION_NAME + "(\"" + id + "\")", container);
|
||||
}
|
||||
final String currentSuppressedId = "\"" + id + "\"";
|
||||
if (!annotation.getText().contains("{")) {
|
||||
final PsiNameValuePair[] attributes = annotation.getParameterList().getAttributes();
|
||||
if (attributes.length == 1) {
|
||||
final String suppressedWarnings = attributes[0].getText();
|
||||
if (suppressedWarnings.contains(currentSuppressedId)) return null;
|
||||
return JavaPsiFacade.getInstance(project).getElementFactory().createAnnotationFromText(
|
||||
"@" + SUPPRESS_INSPECTIONS_ANNOTATION_NAME + "({" + suppressedWarnings + ", " + currentSuppressedId + "})", container);
|
||||
|
||||
}
|
||||
}
|
||||
else {
|
||||
final int curlyBraceIndex = annotation.getText().lastIndexOf("}");
|
||||
if (curlyBraceIndex > 0) {
|
||||
final String oldSuppressWarning = annotation.getText().substring(0, curlyBraceIndex);
|
||||
if (oldSuppressWarning.contains(currentSuppressedId)) return null;
|
||||
return JavaPsiFacade.getInstance(project).getElementFactory().createAnnotationFromText(
|
||||
oldSuppressWarning + ", " + currentSuppressedId + "})", container);
|
||||
}
|
||||
else {
|
||||
throw new IncorrectOperationException(annotation.getText());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean canHave15Suppressions(@NotNull PsiElement file) {
|
||||
final Module module = ModuleUtilCore.findModuleForPsiElement(file);
|
||||
if (module == null) return false;
|
||||
final Sdk jdk = ModuleRootManager.getInstance(module).getSdk();
|
||||
if (jdk == null) return false;
|
||||
JavaSdkVersion version = getVersion(jdk);
|
||||
if (version == null) return false;
|
||||
final boolean is_1_5 = version.isAtLeast(JavaSdkVersion.JDK_1_5);
|
||||
return DaemonCodeAnalyzerSettings.getInstance().isSuppressWarnings() && is_1_5 && PsiUtil.isLanguageLevel5OrHigher(file);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static JavaSdkVersion getVersion(@NotNull Sdk sdk) {
|
||||
String version = sdk.getVersionString();
|
||||
if (version == null) return null;
|
||||
return JdkVersionUtil.getVersion(version);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiElement getElementToAnnotate(PsiElement element, PsiElement container) {
|
||||
if (container instanceof PsiDeclarationStatement && canHave15Suppressions(element)) {
|
||||
final PsiDeclarationStatement declarationStatement = (PsiDeclarationStatement)container;
|
||||
final PsiElement[] declaredElements = declarationStatement.getDeclaredElements();
|
||||
for (PsiElement declaredElement : declaredElements) {
|
||||
if (declaredElement instanceof PsiLocalVariable) {
|
||||
final PsiModifierList modifierList = ((PsiLocalVariable)declaredElement).getModifierList();
|
||||
if (modifierList != null) {
|
||||
return declaredElement;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
-76
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2009 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.codeInsight.daemon.impl.actions;
|
||||
|
||||
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
|
||||
import com.intellij.codeInspection.SuppressManager;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.jsp.jspJava.JspMethodCall;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class SuppressByJavaCommentFix extends SuppressByCommentFix {
|
||||
public SuppressByJavaCommentFix(HighlightDisplayKey key) {
|
||||
super(key, PsiStatement.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected PsiElement getContainer(PsiElement context) {
|
||||
if (context == null || PsiTreeUtil.getParentOfType(context, JspMethodCall.class) != null) return null;
|
||||
return PsiTreeUtil.getParentOfType(context, PsiStatement.class, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createSuppression(final Project project,
|
||||
final Editor editor,
|
||||
final PsiElement element,
|
||||
final PsiElement container) throws IncorrectOperationException {
|
||||
PsiElement declaredElement = getElementToAnnotate(element, container);
|
||||
if (declaredElement != null) {
|
||||
SuppressFix.addSuppressAnnotation(project, editor, container, (PsiLocalVariable)declaredElement, myID);
|
||||
} else {
|
||||
suppressWithComment(project, editor, element, container);
|
||||
}
|
||||
}
|
||||
|
||||
protected void suppressWithComment(Project project, Editor editor, PsiElement element, PsiElement container) {
|
||||
super.createSuppression(project, editor, element, container);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected static PsiElement getElementToAnnotate(PsiElement element, PsiElement container) {
|
||||
if (container instanceof PsiDeclarationStatement && SuppressManager.getInstance().canHave15Suppressions(element)) {
|
||||
final PsiDeclarationStatement declarationStatement = (PsiDeclarationStatement)container;
|
||||
final PsiElement[] declaredElements = declarationStatement.getDeclaredElements();
|
||||
for (PsiElement declaredElement : declaredElements) {
|
||||
if (declaredElement instanceof PsiLocalVariable) {
|
||||
final PsiModifierList modifierList = ((PsiLocalVariable)declaredElement).getModifierList();
|
||||
if (modifierList != null) {
|
||||
return declaredElement;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,222 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2011 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.codeInsight.daemon.impl.actions;
|
||||
|
||||
import com.intellij.codeInsight.AnnotationUtil;
|
||||
import com.intellij.codeInsight.FileModificationService;
|
||||
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
|
||||
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
|
||||
import com.intellij.codeInsight.intention.AddAnnotationFix;
|
||||
import com.intellij.codeInspection.InspectionsBundle;
|
||||
import com.intellij.codeInspection.SuppressIntentionAction;
|
||||
import com.intellij.codeInspection.SuppressManager;
|
||||
import com.intellij.codeInspection.SuppressionUtil;
|
||||
import com.intellij.lang.StdLanguages;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleUtilCore;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.impl.storage.ClasspathStorage;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.jsp.jspJava.JspHolderMethod;
|
||||
import com.intellij.psi.javadoc.PsiDocComment;
|
||||
import com.intellij.psi.javadoc.PsiDocTag;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author ven
|
||||
*/
|
||||
public class SuppressFix extends SuppressIntentionAction {
|
||||
private final String myID;
|
||||
private String myAlternativeID;
|
||||
private String myText;
|
||||
|
||||
public SuppressFix(HighlightDisplayKey key) {
|
||||
this(key.getID());
|
||||
myAlternativeID = HighlightDisplayKey.getAlternativeID(key);
|
||||
}
|
||||
|
||||
public SuppressFix(String ID) {
|
||||
myID = ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getText() {
|
||||
return myText == null ? "Suppress for member" : myText;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected PsiDocCommentOwner getContainer(final PsiElement context) {
|
||||
if (context == null || !context.getManager().isInProject(context)) {
|
||||
return null;
|
||||
}
|
||||
final PsiFile containingFile = context.getContainingFile();
|
||||
if (containingFile == null) {
|
||||
// for PsiDirectory
|
||||
return null;
|
||||
}
|
||||
if (!containingFile.getLanguage().isKindOf(StdLanguages.JAVA) || context instanceof PsiFile) {
|
||||
return null;
|
||||
}
|
||||
PsiElement container = context;
|
||||
while (container instanceof PsiAnonymousClass || !(container instanceof PsiDocCommentOwner) || container instanceof PsiTypeParameter) {
|
||||
container = PsiTreeUtil.getParentOfType(container, PsiDocCommentOwner.class);
|
||||
if (container == null) return null;
|
||||
}
|
||||
return (PsiDocCommentOwner)container;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getFamilyName() {
|
||||
return InspectionsBundle.message("suppress.inspection.family");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(@NotNull final Project project, final Editor editor, @NotNull final PsiElement context) {
|
||||
PsiDocCommentOwner container = getContainer(context);
|
||||
boolean isValid = container != null && !(container instanceof JspHolderMethod);
|
||||
if (!isValid) {
|
||||
return false;
|
||||
}
|
||||
myText = container instanceof PsiClass
|
||||
? InspectionsBundle.message("suppress.inspection.class")
|
||||
: container instanceof PsiMethod ? InspectionsBundle.message("suppress.inspection.method") : InspectionsBundle.message("suppress.inspection.field");
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) throws IncorrectOperationException {
|
||||
PsiDocCommentOwner container = getContainer(element);
|
||||
assert container != null;
|
||||
if (!FileModificationService.getInstance().preparePsiElementForWrite(container)) return;
|
||||
if (use15Suppressions(container)) {
|
||||
final PsiModifierList modifierList = container.getModifierList();
|
||||
if (modifierList != null) {
|
||||
addSuppressAnnotation(project, editor, container, container, getID(container));
|
||||
}
|
||||
}
|
||||
else {
|
||||
PsiDocComment docComment = container.getDocComment();
|
||||
PsiManager manager = PsiManager.getInstance(project);
|
||||
if (docComment == null) {
|
||||
String commentText = "/** @" + SuppressionUtil.SUPPRESS_INSPECTIONS_TAG_NAME + " " + getID(container) + "*/";
|
||||
docComment = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createDocCommentFromText(commentText);
|
||||
PsiElement firstChild = container.getFirstChild();
|
||||
container.addBefore(docComment, firstChild);
|
||||
}
|
||||
else {
|
||||
PsiDocTag noInspectionTag = docComment.findTagByName(SuppressionUtil.SUPPRESS_INSPECTIONS_TAG_NAME);
|
||||
if (noInspectionTag != null) {
|
||||
String tagText = noInspectionTag.getText() + ", " + getID(container);
|
||||
noInspectionTag.replace(JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createDocTagFromText(tagText));
|
||||
}
|
||||
else {
|
||||
String tagText = "@" + SuppressionUtil.SUPPRESS_INSPECTIONS_TAG_NAME + " " + getID(container);
|
||||
docComment.add(JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createDocTagFromText(tagText));
|
||||
}
|
||||
}
|
||||
}
|
||||
DaemonCodeAnalyzer.getInstance(project).restart();
|
||||
}
|
||||
|
||||
public static void addSuppressAnnotation(final Project project,
|
||||
final Editor editor,
|
||||
final PsiElement container,
|
||||
final PsiModifierListOwner modifierOwner,
|
||||
final String id) throws IncorrectOperationException {
|
||||
PsiAnnotation annotation = AnnotationUtil.findAnnotation(modifierOwner, SuppressManager.SUPPRESS_INSPECTIONS_ANNOTATION_NAME);
|
||||
final PsiAnnotation newAnnotation = createNewAnnotation(project, editor, container, annotation, id);
|
||||
if (newAnnotation != null) {
|
||||
if (annotation != null && annotation.isPhysical()) {
|
||||
annotation.replace(newAnnotation);
|
||||
}
|
||||
else {
|
||||
final PsiNameValuePair[] attributes = newAnnotation.getParameterList().getAttributes();
|
||||
new AddAnnotationFix(SuppressManager.SUPPRESS_INSPECTIONS_ANNOTATION_NAME, modifierOwner, attributes).invoke(project, editor, container.getContainingFile());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static PsiAnnotation createNewAnnotation(final Project project,
|
||||
final Editor editor,
|
||||
final PsiElement container,
|
||||
@Nullable final PsiAnnotation annotation,
|
||||
final String id) {
|
||||
|
||||
if (annotation != null) {
|
||||
final String currentSuppressedId = "\"" + id + "\"";
|
||||
if (!annotation.getText().contains("{")) {
|
||||
final PsiNameValuePair[] attributes = annotation.getParameterList().getAttributes();
|
||||
if (attributes.length == 1) {
|
||||
final String suppressedWarnings = attributes[0].getText();
|
||||
if (suppressedWarnings.contains(currentSuppressedId)) return null;
|
||||
return JavaPsiFacade.getInstance(project).getElementFactory().createAnnotationFromText(
|
||||
"@" + SuppressManager.SUPPRESS_INSPECTIONS_ANNOTATION_NAME + "({" + suppressedWarnings + ", " + currentSuppressedId + "})", container);
|
||||
|
||||
}
|
||||
}
|
||||
else {
|
||||
final int curlyBraceIndex = annotation.getText().lastIndexOf("}");
|
||||
if (curlyBraceIndex > 0) {
|
||||
final String oldSuppressWarning = annotation.getText().substring(0, curlyBraceIndex);
|
||||
if (oldSuppressWarning.contains(currentSuppressedId)) return null;
|
||||
return JavaPsiFacade.getInstance(project).getElementFactory().createAnnotationFromText(
|
||||
oldSuppressWarning + ", " + currentSuppressedId + "})", container);
|
||||
}
|
||||
else if (!ApplicationManager.getApplication().isUnitTestMode() && editor != null) {
|
||||
Messages.showErrorDialog(editor.getComponent(),
|
||||
InspectionsBundle.message("suppress.inspection.annotation.syntax.error", annotation.getText()));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
return JavaPsiFacade.getInstance(project).getElementFactory()
|
||||
.createAnnotationFromText("@" + SuppressManager.SUPPRESS_INSPECTIONS_ANNOTATION_NAME + "(\"" + id + "\")", container);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected boolean use15Suppressions(final PsiDocCommentOwner container) {
|
||||
return SuppressManager.getInstance().canHave15Suppressions(container) &&
|
||||
!SuppressManager.getInstance().alreadyHas14Suppressions(container);
|
||||
}
|
||||
|
||||
private String getID(PsiElement place) {
|
||||
String id = getID(place, myAlternativeID);
|
||||
return id != null ? id : myID;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static String getID(PsiElement place, String alternativeID) {
|
||||
if (alternativeID != null) {
|
||||
final Module module = ModuleUtilCore.findModuleForPsiElement(place);
|
||||
if (module != null) {
|
||||
if (!ClasspathStorage.getStorageType(module).equals(ClasspathStorage.DEFAULT_STORAGE)) {
|
||||
return alternativeID;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -16,139 +16,41 @@
|
||||
|
||||
package com.intellij.codeInsight.intention;
|
||||
|
||||
import com.intellij.codeInsight.AnnotationUtil;
|
||||
import com.intellij.codeInsight.CodeInsightBundle;
|
||||
import com.intellij.codeInsight.ExternalAnnotationsManager;
|
||||
import com.intellij.codeInsight.FileModificationService;
|
||||
import com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement;
|
||||
import com.intellij.lang.findUsages.FindUsagesProvider;
|
||||
import com.intellij.lang.findUsages.LanguageFindUsages;
|
||||
import com.intellij.openapi.command.undo.UndoUtil;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiModifierListOwner;
|
||||
import com.intellij.psi.PsiNameValuePair;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author ven
|
||||
*/
|
||||
public class AddAnnotationFix extends LocalQuickFixAndIntentionActionOnPsiElement {
|
||||
protected final String myAnnotation;
|
||||
private final String[] myAnnotationsToRemove;
|
||||
private final PsiNameValuePair[] myPairs; // not used when registering local quick fix
|
||||
private static final Logger LOG = Logger.getInstance("#" + AddAnnotationFix.class.getName());
|
||||
private final String myText;
|
||||
|
||||
public class AddAnnotationFix extends AddAnnotationPsiFix implements IntentionAction {
|
||||
public AddAnnotationFix(@NotNull String fqn, @NotNull PsiModifierListOwner modifierListOwner, @NotNull String... annotationsToRemove) {
|
||||
this(fqn, modifierListOwner, PsiNameValuePair.EMPTY_ARRAY, annotationsToRemove);
|
||||
}
|
||||
|
||||
public AddAnnotationFix(@NotNull String fqn, @NotNull PsiModifierListOwner modifierListOwner, @NotNull PsiNameValuePair[] values, @NotNull String... annotationsToRemove) {
|
||||
super(modifierListOwner);
|
||||
myAnnotation = fqn;
|
||||
myAnnotationsToRemove = annotationsToRemove;
|
||||
myPairs = values;
|
||||
|
||||
myText = calcText(modifierListOwner, myAnnotation);
|
||||
}
|
||||
|
||||
public static String calcText(PsiModifierListOwner modifierListOwner, @NotNull String annotation) {
|
||||
final String shortName = annotation.substring(annotation.lastIndexOf('.') + 1);
|
||||
if (modifierListOwner instanceof PsiNamedElement) {
|
||||
final String name = ((PsiNamedElement)modifierListOwner).getName();
|
||||
if (name != null) {
|
||||
FindUsagesProvider provider = LanguageFindUsages.INSTANCE.forLanguage(modifierListOwner.getLanguage());
|
||||
return CodeInsightBundle
|
||||
.message("inspection.i18n.quickfix.annotate.element.as", provider.getType(modifierListOwner), name, shortName);
|
||||
}
|
||||
}
|
||||
return CodeInsightBundle.message("inspection.i18n.quickfix.annotate.as", shortName);
|
||||
public AddAnnotationFix(@NotNull String fqn,
|
||||
@NotNull PsiModifierListOwner modifierListOwner,
|
||||
@NotNull PsiNameValuePair[] values,
|
||||
@NotNull String... annotationsToRemove) {
|
||||
super(fqn, modifierListOwner, values, annotationsToRemove);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getText() {
|
||||
return myText;
|
||||
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
|
||||
return isAvailable();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getFamilyName() {
|
||||
return CodeInsightBundle.message("intention.add.annotation.family");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiModifierListOwner getContainer(final PsiElement element) {
|
||||
PsiModifierListOwner listOwner = PsiTreeUtil.getParentOfType(element, PsiParameter.class, false);
|
||||
if (listOwner == null) {
|
||||
final PsiIdentifier psiIdentifier = PsiTreeUtil.getParentOfType(element, PsiIdentifier.class, false);
|
||||
if (psiIdentifier != null && psiIdentifier.getParent() instanceof PsiModifierListOwner) {
|
||||
listOwner = (PsiModifierListOwner)psiIdentifier.getParent();
|
||||
}
|
||||
}
|
||||
return listOwner;
|
||||
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
|
||||
applyFix();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(@NotNull Project project,
|
||||
@NotNull PsiFile file,
|
||||
@NotNull PsiElement startElement,
|
||||
@NotNull PsiElement endElement) {
|
||||
if (!startElement.isValid()) return false;
|
||||
if (!PsiUtil.isLanguageLevel5OrHigher(startElement)) return false;
|
||||
final PsiModifierListOwner myModifierListOwner = (PsiModifierListOwner)startElement;
|
||||
|
||||
return !AnnotationUtil.isAnnotated(myModifierListOwner, myAnnotation, false, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(@NotNull Project project,
|
||||
@NotNull PsiFile file,
|
||||
@Nullable("is null when called from inspection") Editor editor,
|
||||
@NotNull PsiElement startElement,
|
||||
@NotNull PsiElement endElement) {
|
||||
final PsiModifierListOwner myModifierListOwner = (PsiModifierListOwner)startElement;
|
||||
|
||||
final ExternalAnnotationsManager annotationsManager = ExternalAnnotationsManager.getInstance(project);
|
||||
final PsiModifierList modifierList = myModifierListOwner.getModifierList();
|
||||
LOG.assertTrue(modifierList != null);
|
||||
if (modifierList.findAnnotation(myAnnotation) != null) return;
|
||||
final ExternalAnnotationsManager.AnnotationPlace annotationAnnotationPlace = annotationsManager.chooseAnnotationsPlace(myModifierListOwner);
|
||||
if (annotationAnnotationPlace == ExternalAnnotationsManager.AnnotationPlace.NOWHERE) return;
|
||||
if (annotationAnnotationPlace == ExternalAnnotationsManager.AnnotationPlace.EXTERNAL) {
|
||||
for (String fqn : myAnnotationsToRemove) {
|
||||
annotationsManager.deannotate(myModifierListOwner, fqn);
|
||||
}
|
||||
annotationsManager.annotateExternally(myModifierListOwner, myAnnotation, file, myPairs);
|
||||
}
|
||||
else {
|
||||
final PsiFile containingFile = myModifierListOwner.getContainingFile();
|
||||
if (!FileModificationService.getInstance().preparePsiElementForWrite(containingFile)) return;
|
||||
for (String fqn : myAnnotationsToRemove) {
|
||||
PsiAnnotation annotation = AnnotationUtil.findAnnotation(myModifierListOwner, fqn);
|
||||
if (annotation != null) {
|
||||
annotation.delete();
|
||||
}
|
||||
}
|
||||
|
||||
PsiAnnotation inserted = modifierList.addAnnotation(myAnnotation);
|
||||
for (PsiNameValuePair pair : myPairs) {
|
||||
inserted.setDeclaredAttributeValue(pair.getName(), pair.getValue());
|
||||
}
|
||||
JavaCodeStyleManager.getInstance(project).shortenClassReferences(inserted);
|
||||
if (containingFile != file) {
|
||||
UndoUtil.markPsiFileForUndo(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String[] getAnnotationsToRemove() {
|
||||
return myAnnotationsToRemove;
|
||||
public boolean startInWriteAction() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
+4
-3
@@ -25,6 +25,7 @@ package com.intellij.codeInsight.intention.impl;
|
||||
import com.intellij.codeInsight.AnnotationUtil;
|
||||
import com.intellij.codeInsight.CodeInsightBundle;
|
||||
import com.intellij.codeInsight.intention.AddAnnotationFix;
|
||||
import com.intellij.codeInsight.intention.AddAnnotationPsiFix;
|
||||
import com.intellij.openapi.editor.CaretModel;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -59,7 +60,7 @@ public abstract class AddAnnotationIntention extends BaseIntentionAction {
|
||||
if (!PsiUtil.isLanguageLevel5OrHigher(element)) return false;
|
||||
final PsiModifierListOwner owner;
|
||||
if (!element.getManager().isInProject(element) || CodeStyleSettingsManager.getSettings(project).USE_EXTERNAL_ANNOTATIONS) {
|
||||
owner = AddAnnotationFix.getContainer(element);
|
||||
owner = AddAnnotationPsiFix.getContainer(element);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
@@ -69,7 +70,7 @@ public abstract class AddAnnotationIntention extends BaseIntentionAction {
|
||||
String toAdd = annotations.first;
|
||||
String[] toRemove = annotations.second;
|
||||
if (toRemove.length > 0 && AnnotationUtil.isAnnotated(owner, toRemove[0], false, false)) return false;
|
||||
setText(AddAnnotationFix.calcText(owner, toAdd));
|
||||
setText(AddAnnotationPsiFix.calcText(owner, toAdd));
|
||||
if (AnnotationUtil.isAnnotated(owner, toAdd, false, false)) return false;
|
||||
|
||||
if (owner instanceof PsiMethod) {
|
||||
@@ -86,7 +87,7 @@ public abstract class AddAnnotationIntention extends BaseIntentionAction {
|
||||
int position = caretModel.getOffset();
|
||||
PsiElement element = file.findElementAt(position);
|
||||
|
||||
PsiModifierListOwner owner = AddAnnotationFix.getContainer(element);
|
||||
PsiModifierListOwner owner = AddAnnotationPsiFix.getContainer(element);
|
||||
if (owner == null || !owner.isValid()) return;
|
||||
Pair<String, String[]> annotations = getAnnotations(project);
|
||||
String toAdd = annotations.first;
|
||||
|
||||
@@ -20,260 +20,84 @@
|
||||
*/
|
||||
package com.intellij.codeInspection;
|
||||
|
||||
import com.intellij.codeInsight.AnnotationUtil;
|
||||
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzerSettings;
|
||||
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
|
||||
import com.intellij.codeInsight.daemon.impl.actions.*;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleUtilCore;
|
||||
import com.intellij.openapi.projectRoots.JavaSdk;
|
||||
import com.intellij.openapi.projectRoots.JavaSdkVersion;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.roots.ModuleRootManager;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiVariableEx;
|
||||
import com.intellij.psi.javadoc.PsiDocComment;
|
||||
import com.intellij.psi.javadoc.PsiDocTag;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.codeInspection.ex.InspectionManagerEx;
|
||||
import com.intellij.psi.PsiDocCommentOwner;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiModifierListOwner;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.annotation.Generated;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
public class SuppressManagerImpl extends SuppressManager {
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public SuppressIntentionAction[] createSuppressActions(@NotNull final HighlightDisplayKey displayKey) {
|
||||
return new SuppressIntentionAction[]{
|
||||
new SuppressByJavaCommentFix(displayKey),
|
||||
new SuppressLocalWithCommentFix(displayKey),
|
||||
new SuppressParameterFix(displayKey),
|
||||
new SuppressFix(displayKey),
|
||||
new SuppressForClassFix(displayKey),
|
||||
new SuppressAllForClassFix()
|
||||
};
|
||||
SuppressQuickFix[] batchSuppressActions = createBatchSuppressActions(displayKey);
|
||||
return convertBatchToSuppressIntentionActions(batchSuppressActions);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static SuppressIntentionAction[] convertBatchToSuppressIntentionActions(@NotNull SuppressQuickFix[] actions) {
|
||||
return ContainerUtil.map2Array(actions, SuppressIntentionAction.class, new Function<SuppressQuickFix, SuppressIntentionAction>() {
|
||||
@Override
|
||||
public SuppressIntentionAction fun(SuppressQuickFix fix) {
|
||||
return InspectionManagerEx.convertBatchToSuppressIntentionAction(fix);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSuppressedFor(@NotNull final PsiElement element, final String toolId) {
|
||||
return getElementToolSuppressedIn(element, toolId) != null;
|
||||
return JavaSuppressionUtil.getElementToolSuppressedIn(element, toolId) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public PsiElement getElementMemberSuppressedIn(@NotNull final PsiDocCommentOwner owner, final String inspectionToolID) {
|
||||
PsiElement element = getDocCommentToolSuppressedIn(owner, inspectionToolID);
|
||||
if (element != null) return element;
|
||||
element = getAnnotationMemberSuppressedIn(owner, inspectionToolID);
|
||||
if (element != null) return element;
|
||||
PsiDocCommentOwner classContainer = PsiTreeUtil.getParentOfType(owner, PsiDocCommentOwner.class);
|
||||
while (classContainer != null) {
|
||||
element = getDocCommentToolSuppressedIn(classContainer, inspectionToolID);
|
||||
if (element != null) return element;
|
||||
|
||||
element = getAnnotationMemberSuppressedIn(classContainer, inspectionToolID);
|
||||
if (element != null) return element;
|
||||
|
||||
classContainer = PsiTreeUtil.getParentOfType(classContainer, PsiDocCommentOwner.class);
|
||||
}
|
||||
return null;
|
||||
return JavaSuppressionUtil.getElementMemberSuppressedIn(owner, inspectionToolID);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public PsiElement getAnnotationMemberSuppressedIn(@NotNull final PsiModifierListOwner owner, final String inspectionToolID) {
|
||||
final PsiAnnotation generatedAnnotation = AnnotationUtil.findAnnotation(owner, Generated.class.getName());
|
||||
if (generatedAnnotation != null) return generatedAnnotation;
|
||||
PsiModifierList modifierList = owner.getModifierList();
|
||||
Collection<String> suppressedIds = getInspectionIdsSuppressedInAnnotation(modifierList);
|
||||
for (String ids : suppressedIds) {
|
||||
if (SuppressionUtil.isInspectionToolIdMentioned(ids, inspectionToolID)) {
|
||||
return modifierList != null ? AnnotationUtil.findAnnotation(owner, SUPPRESS_INSPECTIONS_ANNOTATION_NAME) : null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return JavaSuppressionUtil.getAnnotationMemberSuppressedIn(owner, inspectionToolID);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public PsiElement getDocCommentToolSuppressedIn(@NotNull final PsiDocCommentOwner owner, final String inspectionToolID) {
|
||||
PsiDocComment docComment = owner.getDocComment();
|
||||
if (docComment == null && owner.getParent() instanceof PsiDeclarationStatement) {
|
||||
final PsiElement el = PsiTreeUtil.skipSiblingsBackward(owner.getParent(), PsiWhiteSpace.class);
|
||||
if (el instanceof PsiDocComment) {
|
||||
docComment = (PsiDocComment)el;
|
||||
}
|
||||
}
|
||||
if (docComment != null) {
|
||||
PsiDocTag inspectionTag = docComment.findTagByName(SuppressionUtil.SUPPRESS_INSPECTIONS_TAG_NAME);
|
||||
if (inspectionTag != null) {
|
||||
final PsiElement[] dataElements = inspectionTag.getDataElements();
|
||||
for (PsiElement dataElement : dataElements) {
|
||||
String valueText = dataElement.getText();
|
||||
if (SuppressionUtil.isInspectionToolIdMentioned(valueText, inspectionToolID)) {
|
||||
return docComment;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return JavaSuppressionUtil.getDocCommentToolSuppressedIn(owner, inspectionToolID);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Collection<String> getInspectionIdsSuppressedInAnnotation(@NotNull final PsiModifierListOwner owner) {
|
||||
if (!PsiUtil.isLanguageLevel5OrHigher(owner)) return Collections.emptyList();
|
||||
PsiModifierList modifierList = owner.getModifierList();
|
||||
return getInspectionIdsSuppressedInAnnotation(modifierList);
|
||||
return JavaSuppressionUtil.getInspectionIdsSuppressedInAnnotation(owner);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String getSuppressedInspectionIdsIn(@NotNull PsiElement element) {
|
||||
if (element instanceof PsiComment) {
|
||||
String text = element.getText();
|
||||
Matcher matcher = SuppressionUtil.SUPPRESS_IN_LINE_COMMENT_PATTERN.matcher(text);
|
||||
if (matcher.matches()) {
|
||||
return matcher.group(1).trim();
|
||||
}
|
||||
}
|
||||
if (element instanceof PsiDocCommentOwner) {
|
||||
PsiDocComment docComment = ((PsiDocCommentOwner)element).getDocComment();
|
||||
if (docComment != null) {
|
||||
PsiDocTag inspectionTag = docComment.findTagByName(SuppressionUtil.SUPPRESS_INSPECTIONS_TAG_NAME);
|
||||
if (inspectionTag != null) {
|
||||
String valueText = "";
|
||||
for (PsiElement dataElement : inspectionTag.getDataElements()) {
|
||||
valueText += dataElement.getText();
|
||||
}
|
||||
return valueText;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (element instanceof PsiModifierListOwner) {
|
||||
Collection<String> suppressedIds = getInspectionIdsSuppressedInAnnotation((PsiModifierListOwner)element);
|
||||
return suppressedIds.isEmpty() ? null : StringUtil.join(suppressedIds, ",");
|
||||
}
|
||||
return null;
|
||||
return JavaSuppressionUtil.getSuppressedInspectionIdsIn(element);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public PsiElement getElementToolSuppressedIn(@NotNull final PsiElement place, final String toolId) {
|
||||
if (place instanceof PsiFile) return null;
|
||||
return ApplicationManager.getApplication().runReadAction(new Computable<PsiElement>() {
|
||||
@Override
|
||||
@Nullable
|
||||
public PsiElement compute() {
|
||||
final PsiElement statement = SuppressionUtil.getStatementToolSuppressedIn(place, toolId, PsiStatement.class);
|
||||
if (statement != null) {
|
||||
return statement;
|
||||
}
|
||||
|
||||
PsiVariable local = PsiTreeUtil.getParentOfType(place, PsiVariable.class);
|
||||
if (local != null && getAnnotationMemberSuppressedIn(local, toolId) != null) {
|
||||
PsiModifierList modifierList = local.getModifierList();
|
||||
return modifierList != null ? modifierList.findAnnotation(SUPPRESS_INSPECTIONS_ANNOTATION_NAME) : null;
|
||||
}
|
||||
|
||||
PsiDocCommentOwner container = PsiTreeUtil.getNonStrictParentOfType(place, PsiDocCommentOwner.class);
|
||||
while (true) {
|
||||
if (!(container instanceof PsiTypeParameter)) break;
|
||||
container = PsiTreeUtil.getParentOfType(container, PsiDocCommentOwner.class);
|
||||
}
|
||||
|
||||
if (container != null) {
|
||||
PsiElement element = getElementMemberSuppressedIn(container, toolId);
|
||||
if (element != null) return element;
|
||||
}
|
||||
PsiDocCommentOwner classContainer = PsiTreeUtil.getParentOfType(container, PsiDocCommentOwner.class, true);
|
||||
if (classContainer != null) {
|
||||
PsiElement element = getElementMemberSuppressedIn(classContainer, toolId);
|
||||
if (element != null) return element;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Collection<String> getInspectionIdsSuppressedInAnnotation(final PsiModifierList modifierList) {
|
||||
if (modifierList == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
final PsiModifierListOwner owner = (PsiModifierListOwner)modifierList.getParent();
|
||||
PsiAnnotation annotation = AnnotationUtil.findAnnotation(owner, SUPPRESS_INSPECTIONS_ANNOTATION_NAME);
|
||||
if (annotation == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
final PsiNameValuePair[] attributes = annotation.getParameterList().getAttributes();
|
||||
if (attributes.length == 0) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
final PsiAnnotationMemberValue attributeValue = attributes[0].getValue();
|
||||
Collection<String> result = new ArrayList<String>();
|
||||
if (attributeValue instanceof PsiArrayInitializerMemberValue) {
|
||||
final PsiAnnotationMemberValue[] initializers = ((PsiArrayInitializerMemberValue)attributeValue).getInitializers();
|
||||
for (PsiAnnotationMemberValue annotationMemberValue : initializers) {
|
||||
final String id = getInspectionIdSuppressedInAnnotationAttribute(annotationMemberValue);
|
||||
if (id != null) {
|
||||
result.add(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
final String id = getInspectionIdSuppressedInAnnotationAttribute(attributeValue);
|
||||
if (id != null) {
|
||||
result.add(id);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getInspectionIdSuppressedInAnnotationAttribute(PsiElement element) {
|
||||
if (element instanceof PsiLiteralExpression) {
|
||||
final Object value = ((PsiLiteralExpression)element).getValue();
|
||||
if (value instanceof String) {
|
||||
return (String)value;
|
||||
}
|
||||
}
|
||||
else if (element instanceof PsiReferenceExpression) {
|
||||
final PsiElement psiElement = ((PsiReferenceExpression)element).resolve();
|
||||
if (psiElement instanceof PsiVariableEx) {
|
||||
final Object val = ((PsiVariableEx)psiElement).computeConstantValue(new HashSet<PsiVariable>());
|
||||
if (val instanceof String) {
|
||||
return (String)val;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return JavaSuppressionUtil.getElementToolSuppressedIn(place, toolId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canHave15Suppressions(@NotNull final PsiElement file) {
|
||||
final Module module = ModuleUtilCore.findModuleForPsiElement(file);
|
||||
if (module == null) return false;
|
||||
final Sdk jdk = ModuleRootManager.getInstance(module).getSdk();
|
||||
if (jdk == null) return false;
|
||||
final boolean is_1_5 = JavaSdk.getInstance().isOfVersionOrHigher(jdk, JavaSdkVersion.JDK_1_5);
|
||||
return DaemonCodeAnalyzerSettings.getInstance().SUPPRESS_WARNINGS && is_1_5 && PsiUtil.isLanguageLevel5OrHigher(file);
|
||||
return JavaSuppressionUtil.canHave15Suppressions(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean alreadyHas14Suppressions(@NotNull final PsiDocCommentOwner commentOwner) {
|
||||
final PsiDocComment docComment = commentOwner.getDocComment();
|
||||
return docComment != null && docComment.findTagByName(SuppressionUtil.SUPPRESS_INSPECTIONS_TAG_NAME) != null;
|
||||
return JavaSuppressionUtil.alreadyHas14Suppressions(commentOwner);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,21 +56,8 @@ public class JavaSdkImpl extends JavaSdk {
|
||||
@NonNls private final Pattern myVersionStringPattern = Pattern.compile("^(.*)java version \"([1234567890_.]*)\"(.*)$");
|
||||
@NonNls private static final String JAVA_VERSION_PREFIX = "java version ";
|
||||
@NonNls private static final String OPENJDK_VERSION_PREFIX = "openjdk version ";
|
||||
private static final Map<JavaSdkVersion, String[]> VERSION_STRINGS = new EnumMap<JavaSdkVersion, String[]>(JavaSdkVersion.class);
|
||||
public static final DataKey<Boolean> KEY = DataKey.create("JavaSdk");
|
||||
|
||||
static {
|
||||
VERSION_STRINGS.put(JavaSdkVersion.JDK_1_0, new String[]{"1.0"});
|
||||
VERSION_STRINGS.put(JavaSdkVersion.JDK_1_1, new String[]{"1.1"});
|
||||
VERSION_STRINGS.put(JavaSdkVersion.JDK_1_2, new String[]{"1.2"});
|
||||
VERSION_STRINGS.put(JavaSdkVersion.JDK_1_3, new String[]{"1.3"});
|
||||
VERSION_STRINGS.put(JavaSdkVersion.JDK_1_4, new String[]{"1.4"});
|
||||
VERSION_STRINGS.put(JavaSdkVersion.JDK_1_5, new String[]{"1.5", "5.0"});
|
||||
VERSION_STRINGS.put(JavaSdkVersion.JDK_1_6, new String[]{"1.6", "6.0"});
|
||||
VERSION_STRINGS.put(JavaSdkVersion.JDK_1_7, new String[]{"1.7", "7.0"});
|
||||
VERSION_STRINGS.put(JavaSdkVersion.JDK_1_8, new String[]{"1.8", "8.0"});
|
||||
}
|
||||
|
||||
public JavaSdkImpl() {
|
||||
super("JavaSDK");
|
||||
}
|
||||
@@ -264,11 +251,11 @@ public class JavaSdkImpl extends JavaSdk {
|
||||
if (SystemInfo.isMac) {
|
||||
File home = new File(homePath, MAC_HOME_PATH);
|
||||
if (home.exists()) return home.getPath();
|
||||
|
||||
|
||||
home = new File(new File(homePath, "Contents"), "Home");
|
||||
if (home.exists()) return home.getPath();
|
||||
}
|
||||
|
||||
|
||||
return homePath;
|
||||
}
|
||||
|
||||
@@ -302,7 +289,7 @@ public class JavaSdkImpl extends JavaSdk {
|
||||
@NotNull
|
||||
private static String getVersionNumber(@NotNull String versionString) {
|
||||
if (versionString.startsWith(JAVA_VERSION_PREFIX) || versionString.startsWith(OPENJDK_VERSION_PREFIX)) {
|
||||
boolean openJdk = versionString.startsWith(OPENJDK_VERSION_PREFIX);
|
||||
boolean openJdk = versionString.startsWith(OPENJDK_VERSION_PREFIX);
|
||||
versionString = versionString.substring(openJdk ? OPENJDK_VERSION_PREFIX.length() : JAVA_VERSION_PREFIX.length());
|
||||
if (versionString.startsWith("\"") && versionString.endsWith("\"")) {
|
||||
versionString = versionString.substring(1, versionString.length() - 1);
|
||||
@@ -440,22 +427,19 @@ public class JavaSdkImpl extends JavaSdk {
|
||||
|
||||
@Override
|
||||
public JavaSdkVersion getVersion(@NotNull Sdk sdk) {
|
||||
return getVersion1(sdk);
|
||||
}
|
||||
|
||||
private static JavaSdkVersion getVersion1(Sdk sdk) {
|
||||
String version = sdk.getVersionString();
|
||||
if (version == null) return null;
|
||||
return getVersion(version);
|
||||
return JdkVersionUtil.getVersion(version);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public JavaSdkVersion getVersion(@NotNull String versionString) {
|
||||
for (Map.Entry<JavaSdkVersion, String[]> entry : VERSION_STRINGS.entrySet()) {
|
||||
for (String s : entry.getValue()) {
|
||||
if (versionString.contains(s)) {
|
||||
return entry.getKey();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return JdkVersionUtil.getVersion(versionString);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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.openapi.projectRoots;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.EnumMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class JdkVersionUtil {
|
||||
private static final Map<JavaSdkVersion, String[]> VERSION_STRINGS = new EnumMap<JavaSdkVersion, String[]>(JavaSdkVersion.class);
|
||||
|
||||
static {
|
||||
VERSION_STRINGS.put(JavaSdkVersion.JDK_1_0, new String[]{"1.0"});
|
||||
VERSION_STRINGS.put(JavaSdkVersion.JDK_1_1, new String[]{"1.1"});
|
||||
VERSION_STRINGS.put(JavaSdkVersion.JDK_1_2, new String[]{"1.2"});
|
||||
VERSION_STRINGS.put(JavaSdkVersion.JDK_1_3, new String[]{"1.3"});
|
||||
VERSION_STRINGS.put(JavaSdkVersion.JDK_1_4, new String[]{"1.4"});
|
||||
VERSION_STRINGS.put(JavaSdkVersion.JDK_1_5, new String[]{"1.5", "5.0"});
|
||||
VERSION_STRINGS.put(JavaSdkVersion.JDK_1_6, new String[]{"1.6", "6.0"});
|
||||
VERSION_STRINGS.put(JavaSdkVersion.JDK_1_7, new String[]{"1.7", "7.0"});
|
||||
VERSION_STRINGS.put(JavaSdkVersion.JDK_1_8, new String[]{"1.8", "8.0"});
|
||||
}
|
||||
|
||||
public static JavaSdkVersion getVersion(@NotNull String versionString) {
|
||||
for (Map.Entry<JavaSdkVersion, String[]> entry : VERSION_STRINGS.entrySet()) {
|
||||
for (String s : entry.getValue()) {
|
||||
if (versionString.contains(s)) {
|
||||
return entry.getKey();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* 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.codeInsight.intention;
|
||||
|
||||
import com.intellij.codeInsight.AnnotationUtil;
|
||||
import com.intellij.codeInsight.CodeInsightBundle;
|
||||
import com.intellij.codeInsight.ExternalAnnotationsManager;
|
||||
import com.intellij.codeInsight.FileModificationService;
|
||||
import com.intellij.codeInspection.LocalQuickFixOnPsiElement;
|
||||
import com.intellij.lang.findUsages.FindUsagesProvider;
|
||||
import com.intellij.lang.findUsages.LanguageFindUsages;
|
||||
import com.intellij.openapi.command.undo.UndoUtil;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class AddAnnotationPsiFix extends LocalQuickFixOnPsiElement {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.intention.AddAnnotationPsiFix");
|
||||
protected final String myAnnotation;
|
||||
protected final String[] myAnnotationsToRemove;
|
||||
protected final PsiNameValuePair[] myPairs; // not used when registering local quick fix
|
||||
protected final String myText;
|
||||
|
||||
public AddAnnotationPsiFix(@NotNull String fqn,
|
||||
@NotNull PsiModifierListOwner modifierListOwner,
|
||||
@NotNull PsiNameValuePair[] values,
|
||||
@NotNull String... annotationsToRemove) {
|
||||
super(modifierListOwner);
|
||||
myAnnotation = fqn;
|
||||
myPairs = values;
|
||||
myAnnotationsToRemove = annotationsToRemove;
|
||||
myText = calcText(modifierListOwner, myAnnotation);
|
||||
}
|
||||
|
||||
public static String calcText(PsiModifierListOwner modifierListOwner, @NotNull String annotation) {
|
||||
final String shortName = annotation.substring(annotation.lastIndexOf('.') + 1);
|
||||
if (modifierListOwner instanceof PsiNamedElement) {
|
||||
final String name = ((PsiNamedElement)modifierListOwner).getName();
|
||||
if (name != null) {
|
||||
FindUsagesProvider provider = LanguageFindUsages.INSTANCE.forLanguage(modifierListOwner.getLanguage());
|
||||
return CodeInsightBundle
|
||||
.message("inspection.i18n.quickfix.annotate.element.as", provider.getType(modifierListOwner), name, shortName);
|
||||
}
|
||||
}
|
||||
return CodeInsightBundle.message("inspection.i18n.quickfix.annotate.as", shortName);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiModifierListOwner getContainer(final PsiElement element) {
|
||||
PsiModifierListOwner listOwner = PsiTreeUtil.getParentOfType(element, PsiParameter.class, false);
|
||||
if (listOwner == null) {
|
||||
final PsiIdentifier psiIdentifier = PsiTreeUtil.getParentOfType(element, PsiIdentifier.class, false);
|
||||
if (psiIdentifier != null && psiIdentifier.getParent() instanceof PsiModifierListOwner) {
|
||||
listOwner = (PsiModifierListOwner)psiIdentifier.getParent();
|
||||
}
|
||||
}
|
||||
return listOwner;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getText() {
|
||||
return myText;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getFamilyName() {
|
||||
return CodeInsightBundle.message("intention.add.annotation.family");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(@NotNull Project project,
|
||||
@NotNull PsiFile file,
|
||||
@NotNull PsiElement startElement,
|
||||
@NotNull PsiElement endElement) {
|
||||
if (!startElement.isValid()) return false;
|
||||
if (!PsiUtil.isLanguageLevel5OrHigher(startElement)) return false;
|
||||
final PsiModifierListOwner myModifierListOwner = (PsiModifierListOwner)startElement;
|
||||
|
||||
return !AnnotationUtil.isAnnotated(myModifierListOwner, myAnnotation, false, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(@NotNull Project project,
|
||||
@NotNull PsiFile file,
|
||||
@NotNull PsiElement startElement,
|
||||
@NotNull PsiElement endElement) {
|
||||
final PsiModifierListOwner myModifierListOwner = (PsiModifierListOwner)startElement;
|
||||
|
||||
final ExternalAnnotationsManager annotationsManager = ExternalAnnotationsManager.getInstance(project);
|
||||
final PsiModifierList modifierList = myModifierListOwner.getModifierList();
|
||||
LOG.assertTrue(modifierList != null);
|
||||
if (modifierList.findAnnotation(myAnnotation) != null) return;
|
||||
final ExternalAnnotationsManager.AnnotationPlace annotationAnnotationPlace = annotationsManager.chooseAnnotationsPlace(myModifierListOwner);
|
||||
if (annotationAnnotationPlace == ExternalAnnotationsManager.AnnotationPlace.NOWHERE) return;
|
||||
if (annotationAnnotationPlace == ExternalAnnotationsManager.AnnotationPlace.EXTERNAL) {
|
||||
for (String fqn : myAnnotationsToRemove) {
|
||||
annotationsManager.deannotate(myModifierListOwner, fqn);
|
||||
}
|
||||
annotationsManager.annotateExternally(myModifierListOwner, myAnnotation, file, myPairs);
|
||||
}
|
||||
else {
|
||||
final PsiFile containingFile = myModifierListOwner.getContainingFile();
|
||||
if (!FileModificationService.getInstance().preparePsiElementForWrite(containingFile)) return;
|
||||
for (String fqn : myAnnotationsToRemove) {
|
||||
PsiAnnotation annotation = AnnotationUtil.findAnnotation(myModifierListOwner, fqn);
|
||||
if (annotation != null) {
|
||||
annotation.delete();
|
||||
}
|
||||
}
|
||||
|
||||
PsiAnnotation inserted = modifierList.addAnnotation(myAnnotation);
|
||||
for (PsiNameValuePair pair : myPairs) {
|
||||
inserted.setDeclaredAttributeValue(pair.getName(), pair.getValue());
|
||||
}
|
||||
JavaCodeStyleManager.getInstance(project).shortenClassReferences(inserted);
|
||||
if (containingFile != file) {
|
||||
UndoUtil.markPsiFileForUndo(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String[] getAnnotationsToRemove() {
|
||||
return myAnnotationsToRemove;
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
package com.intellij.codeInsight;
|
||||
|
||||
import com.intellij.codeInsight.intention.AddAnnotationFix;
|
||||
import com.intellij.codeInsight.intention.AddAnnotationPsiFix;
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.codeInsight.intention.impl.DeannotateIntentionAction;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
@@ -110,7 +110,7 @@ public class AddAnnotationFixTest extends UsefulTestCase {
|
||||
int position = caretModel.getOffset();
|
||||
PsiElement element = myFixture.getFile().findElementAt(position);
|
||||
assert element != null;
|
||||
PsiModifierListOwner container = AddAnnotationFix.getContainer(element);
|
||||
PsiModifierListOwner container = AddAnnotationPsiFix.getContainer(element);
|
||||
assert container != null;
|
||||
return container;
|
||||
}
|
||||
|
||||
@@ -16,10 +16,8 @@
|
||||
package com.intellij.codeInspection;
|
||||
|
||||
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Implement this abstract class in order to provide new inspection tool functionality. The major API limitation here is
|
||||
@@ -30,94 +28,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
*
|
||||
* @see GlobalInspectionTool
|
||||
*/
|
||||
public abstract class BaseJavaLocalInspectionTool extends LocalInspectionTool implements CustomSuppressableInspectionTool {
|
||||
/**
|
||||
* Override this to report problems at method level.
|
||||
*
|
||||
* @param method to check.
|
||||
* @param manager InspectionManager to ask for ProblemDescriptors from.
|
||||
* @param isOnTheFly true if called during on the fly editor highlighting. Called from Inspect Code action otherwise.
|
||||
* @return <code>null</code> if no problems found or not applicable at method level.
|
||||
*/
|
||||
@Nullable
|
||||
public ProblemDescriptor[] checkMethod(@NotNull PsiMethod method, @NotNull InspectionManager manager, boolean isOnTheFly) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this to report problems at class level.
|
||||
*
|
||||
* @param aClass to check.
|
||||
* @param manager InspectionManager to ask for ProblemDescriptors from.
|
||||
* @param isOnTheFly true if called during on the fly editor highlighting. Called from Inspect Code action otherwise.
|
||||
* @return <code>null</code> if no problems found or not applicable at class level.
|
||||
*/
|
||||
@Nullable
|
||||
public ProblemDescriptor[] checkClass(@NotNull PsiClass aClass, @NotNull InspectionManager manager, boolean isOnTheFly) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this to report problems at field level.
|
||||
*
|
||||
* @param field to check.
|
||||
* @param manager InspectionManager to ask for ProblemDescriptors from.
|
||||
* @param isOnTheFly true if called during on the fly editor highlighting. Called from Inspect Code action otherwise.
|
||||
* @return <code>null</code> if no problems found or not applicable at field level.
|
||||
*/
|
||||
@Nullable
|
||||
public ProblemDescriptor[] checkField(@NotNull PsiField field, @NotNull InspectionManager manager, boolean isOnTheFly) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this to report problems at file level.
|
||||
*
|
||||
* @param file to check.
|
||||
* @param manager InspectionManager to ask for ProblemDescriptors from.
|
||||
* @param isOnTheFly true if called during on the fly editor highlighting. Called from Inspect Code action otherwise.
|
||||
* @return <code>null</code> if no problems found or not applicable at file level.
|
||||
*/
|
||||
@Override
|
||||
@Nullable
|
||||
public ProblemDescriptor[] checkFile(@NotNull PsiFile file, @NotNull InspectionManager manager, boolean isOnTheFly) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, final boolean isOnTheFly) {
|
||||
return new JavaElementVisitor() {
|
||||
@Override public void visitMethod(PsiMethod method) {
|
||||
addDescriptors(checkMethod(method, holder.getManager(), isOnTheFly));
|
||||
}
|
||||
|
||||
@Override public void visitClass(PsiClass aClass) {
|
||||
addDescriptors(checkClass(aClass, holder.getManager(), isOnTheFly));
|
||||
}
|
||||
|
||||
@Override public void visitField(PsiField field) {
|
||||
addDescriptors(checkField(field, holder.getManager(), isOnTheFly));
|
||||
}
|
||||
|
||||
@Override public void visitFile(PsiFile file) {
|
||||
addDescriptors(checkFile(file, holder.getManager(), isOnTheFly));
|
||||
}
|
||||
private void addDescriptors(final ProblemDescriptor[] descriptors) {
|
||||
if (descriptors != null) {
|
||||
for (ProblemDescriptor descriptor : descriptors) {
|
||||
holder.registerProblem(descriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiNamedElement getProblemElement(final PsiElement psiElement) {
|
||||
return PsiTreeUtil.getNonStrictParentOfType(psiElement, PsiFile.class, PsiClass.class, PsiMethod.class, PsiField.class);
|
||||
}
|
||||
|
||||
public abstract class BaseJavaLocalInspectionTool extends AbstractBaseJavaLocalInspectionTool implements CustomSuppressableInspectionTool {
|
||||
@Override
|
||||
public SuppressIntentionAction[] getSuppressActions(final PsiElement element) {
|
||||
return SuppressManager.getInstance().createSuppressActions(HighlightDisplayKey.find(getShortName()));
|
||||
@@ -129,12 +40,6 @@ public abstract class BaseJavaLocalInspectionTool extends LocalInspectionTool i
|
||||
}
|
||||
|
||||
public static boolean isSuppressedFor(@NotNull PsiElement element, @NotNull LocalInspectionTool tool) {
|
||||
final SuppressManager manager = SuppressManager.getInstance();
|
||||
String alternativeId;
|
||||
String id;
|
||||
return manager.isSuppressedFor(element, id = tool.getID()) ||
|
||||
(alternativeId = tool.getAlternativeID()) != null &&
|
||||
!alternativeId.equals(id) &&
|
||||
manager.isSuppressedFor(element, alternativeId);
|
||||
return BaseJavaBatchLocalInspectionTool.isSuppressedFor(element, tool);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,48 +22,31 @@ package com.intellij.codeInspection;
|
||||
|
||||
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.PsiAnnotation;
|
||||
import com.intellij.psi.PsiCodeBlock;
|
||||
import com.intellij.psi.PsiField;
|
||||
import com.intellij.psi.PsiLiteralExpression;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public abstract class SuppressManager {
|
||||
public abstract class SuppressManager implements BatchSuppressManager {
|
||||
public static final String SUPPRESS_INSPECTIONS_ANNOTATION_NAME = "java.lang.SuppressWarnings";
|
||||
|
||||
public static SuppressManager getInstance() {
|
||||
return ServiceManager.getService(SuppressManager.class);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public abstract SuppressIntentionAction[] createSuppressActions(@NotNull HighlightDisplayKey key);
|
||||
|
||||
public abstract boolean isSuppressedFor(@NotNull PsiElement element, final String toolId);
|
||||
|
||||
public abstract PsiElement getElementMemberSuppressedIn(@NotNull PsiDocCommentOwner owner, final String inspectionToolID);
|
||||
|
||||
@Nullable
|
||||
public abstract PsiElement getAnnotationMemberSuppressedIn(@NotNull PsiModifierListOwner owner, String inspectionToolID);
|
||||
|
||||
@Nullable
|
||||
public abstract PsiElement getDocCommentToolSuppressedIn(@NotNull PsiDocCommentOwner owner, String inspectionToolID);
|
||||
|
||||
@NotNull
|
||||
public abstract Collection<String> getInspectionIdsSuppressedInAnnotation(@NotNull PsiModifierListOwner owner);
|
||||
|
||||
@Nullable
|
||||
public abstract String getSuppressedInspectionIdsIn(@NotNull PsiElement element);
|
||||
|
||||
@Nullable
|
||||
public abstract PsiElement getElementToolSuppressedIn(@NotNull PsiElement place, String toolId);
|
||||
|
||||
public abstract boolean canHave15Suppressions(@NotNull PsiElement file);
|
||||
|
||||
public abstract boolean alreadyHas14Suppressions(@NotNull PsiDocCommentOwner commentOwner);
|
||||
|
||||
public static boolean isSuppressedInspectionName(PsiLiteralExpression expression) {
|
||||
PsiAnnotation annotation = PsiTreeUtil.getParentOfType(expression, PsiAnnotation.class, true, PsiCodeBlock.class, PsiField.class);
|
||||
return annotation != null && SUPPRESS_INSPECTIONS_ANNOTATION_NAME.equals(annotation.getQualifiedName());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public SuppressQuickFix[] createBatchSuppressActions(@NotNull HighlightDisplayKey key) {
|
||||
return BatchSuppressManager.SERVICE.getInstance().createBatchSuppressActions(key);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public abstract SuppressIntentionAction[] createSuppressActions(@NotNull HighlightDisplayKey key);
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface BatchSuppressableTool {
|
||||
/**
|
||||
* Checks if the inspection is suppressed for the specified element.
|
||||
*
|
||||
* @param element the element to check
|
||||
* @return true if the inspection is suppressed, false otherwise.
|
||||
*/
|
||||
boolean isSuppressedFor(@NotNull PsiElement element);
|
||||
|
||||
|
||||
/**
|
||||
* Returns the list of suppression actions for the specified element.
|
||||
*
|
||||
* @param element the element on which Alt-Enter is pressed, or null if getting the list of available suppression actions in
|
||||
* Inspections tool window
|
||||
* @return the list of suppression actions.
|
||||
*/
|
||||
@NotNull
|
||||
SuppressQuickFix[] getBatchSuppressActions(@Nullable final PsiElement element);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.SmartPointerManager;
|
||||
import com.intellij.psi.SmartPsiElementPointer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public abstract class LocalQuickFixOnPsiElement implements LocalQuickFix {
|
||||
protected static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.LocalQuickFixAndIntentionAction");
|
||||
protected final SmartPsiElementPointer<PsiElement> myStartElement;
|
||||
protected final SmartPsiElementPointer<PsiElement> myEndElement;
|
||||
|
||||
protected LocalQuickFixOnPsiElement(@NotNull PsiElement element) {
|
||||
this(element, element);
|
||||
}
|
||||
|
||||
public LocalQuickFixOnPsiElement(PsiElement startElement, PsiElement endElement) {
|
||||
if (startElement == null || endElement == null) {
|
||||
myStartElement = myEndElement = null;
|
||||
return;
|
||||
}
|
||||
LOG.assertTrue(startElement.isValid());
|
||||
PsiFile startContainingFile = startElement.getContainingFile();
|
||||
PsiFile endContainingFile = startElement == endElement ? startContainingFile : endElement.getContainingFile();
|
||||
if (startElement != endElement) {
|
||||
LOG.assertTrue(endElement.isValid());
|
||||
LOG.assertTrue(startContainingFile == endContainingFile, "Both elements must be from the same file");
|
||||
}
|
||||
Project project = startContainingFile == null ? startElement.getProject() : startContainingFile.getProject(); // containingFile can be null for a directory
|
||||
myStartElement = SmartPointerManager.getInstance(project).createSmartPsiElementPointer(startElement, startContainingFile);
|
||||
myEndElement = endElement == startElement ? null : SmartPointerManager.getInstance(project).createSmartPsiElementPointer(endElement, endContainingFile);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public final String getName() {
|
||||
return getText();
|
||||
}
|
||||
|
||||
public boolean isAvailable(@NotNull Project project,
|
||||
@NotNull PsiFile file,
|
||||
@NotNull PsiElement startElement,
|
||||
@NotNull PsiElement endElement) {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean isAvailable() {
|
||||
if (myStartElement == null) return false;
|
||||
final PsiElement startElement = myStartElement.getElement();
|
||||
final PsiElement endElement = myEndElement == null ? startElement : myEndElement.getElement();
|
||||
PsiFile file = myStartElement.getContainingFile();
|
||||
Project project = myStartElement.getProject();
|
||||
return startElement != null &&
|
||||
endElement != null &&
|
||||
startElement.isValid() &&
|
||||
(endElement == startElement || endElement.isValid()) &&
|
||||
file != null &&
|
||||
isAvailable(project, file, startElement, endElement);
|
||||
}
|
||||
|
||||
public PsiElement getStartElement() {
|
||||
return myStartElement == null ? null : myStartElement.getElement();
|
||||
}
|
||||
|
||||
public PsiElement getEndElement() {
|
||||
return myEndElement == null ? null : myEndElement.getElement();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public abstract String getText();
|
||||
|
||||
@Override
|
||||
public final void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
|
||||
applyFix();
|
||||
}
|
||||
|
||||
public void applyFix() {
|
||||
if (myStartElement == null) return;
|
||||
final PsiElement startElement = myStartElement.getElement();
|
||||
final PsiElement endElement = myEndElement == null ? startElement : myEndElement.getElement();
|
||||
if (startElement == null || endElement == null) return;
|
||||
PsiFile file = startElement.getContainingFile();
|
||||
if (file == null) return;
|
||||
invoke(file.getProject(), file, startElement, endElement);
|
||||
}
|
||||
|
||||
public abstract void invoke(@NotNull Project project,
|
||||
@NotNull PsiFile file,
|
||||
@NotNull PsiElement startElement,
|
||||
@NotNull PsiElement endElement);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public interface SuppressQuickFix extends LocalQuickFix {
|
||||
SuppressQuickFix[] EMPTY_ARRAY = new SuppressQuickFix[0];
|
||||
boolean isAvailable(@NotNull final Project project, @NotNull final PsiElement context);
|
||||
}
|
||||
+155
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* 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.codeInsight.daemon.impl.actions;
|
||||
|
||||
import com.intellij.codeInsight.FileModificationService;
|
||||
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.openapi.command.undo.UndoUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Iconable;
|
||||
import com.intellij.psi.PsiComment;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.PsiWhiteSpace;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Roman.Chernyatchik
|
||||
* @date Aug 13, 2009
|
||||
*/
|
||||
public abstract class AbstractBatchSuppressByNoInspectionCommentFix implements SuppressQuickFix, Iconable {
|
||||
@NotNull protected final String myID;
|
||||
private final boolean myReplaceOtherSuppressionIds;
|
||||
|
||||
@Nullable
|
||||
public abstract PsiElement getContainer(final PsiElement context);
|
||||
|
||||
/**
|
||||
* @param ID Inspection ID
|
||||
* @param replaceOtherSuppressionIds Merge suppression policy. If false new tool id will be append to the end
|
||||
* otherwise replace other ids
|
||||
*/
|
||||
public AbstractBatchSuppressByNoInspectionCommentFix(@NotNull String ID, final boolean replaceOtherSuppressionIds) {
|
||||
myID = ID;
|
||||
myReplaceOtherSuppressionIds = replaceOtherSuppressionIds;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return getText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Icon getIcon(int flags) {
|
||||
return AllIcons.General.InspectionsOff;
|
||||
}
|
||||
|
||||
private String myText = "";
|
||||
@NotNull
|
||||
public String getText() {
|
||||
return myText;
|
||||
}
|
||||
|
||||
protected void setText(@NotNull String text) {
|
||||
myText = text;
|
||||
}
|
||||
|
||||
public boolean startInWriteAction() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
|
||||
PsiElement element = descriptor.getStartElement();
|
||||
if (element == null) return;
|
||||
invoke(project, element);
|
||||
}
|
||||
|
||||
protected final void replaceSuppressionComment(@NotNull final PsiElement comment) {
|
||||
SuppressionUtil.replaceSuppressionComment(comment, myID, myReplaceOtherSuppressionIds);
|
||||
}
|
||||
|
||||
protected void createSuppression(@NotNull Project project,
|
||||
@NotNull PsiElement element,
|
||||
@NotNull PsiElement container) throws IncorrectOperationException {
|
||||
SuppressionUtil.createSuppression(project, element, container, myID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(@NotNull final Project project, @NotNull final PsiElement context) {
|
||||
return context.isValid() && PsiManager.getInstance(project).isInProject(context) && getContainer(context) != null;
|
||||
}
|
||||
|
||||
public void invoke(@NotNull final Project project, @NotNull final PsiElement element) throws IncorrectOperationException {
|
||||
if (!isAvailable(project, element)) return;
|
||||
PsiElement container = getContainer(element);
|
||||
if (container == null) return;
|
||||
|
||||
if (!FileModificationService.getInstance().preparePsiElementForWrite(container)) return;
|
||||
|
||||
if (replaceSuppressionComments(container)) return;
|
||||
|
||||
createSuppression(project, element, container);
|
||||
UndoUtil.markPsiFileForUndo(element.getContainingFile());
|
||||
}
|
||||
|
||||
protected boolean replaceSuppressionComments(PsiElement container) {
|
||||
final List<? extends PsiElement> comments = getCommentsFor(container);
|
||||
if (comments != null) {
|
||||
for (PsiElement comment : comments) {
|
||||
if (comment instanceof PsiComment && SuppressionUtil.isSuppressionComment(comment)) {
|
||||
replaceSuppressionComment(comment);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected List<? extends PsiElement> getCommentsFor(@NotNull final PsiElement container) {
|
||||
final PsiElement prev = PsiTreeUtil.skipSiblingsBackward(container, PsiWhiteSpace.class);
|
||||
if (prev == null) {
|
||||
return null;
|
||||
}
|
||||
return Collections.singletonList(prev);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getFamilyName() {
|
||||
return InspectionsBundle.message("suppress.inspection.family");
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -26,7 +26,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
/**
|
||||
* @author ven
|
||||
*/
|
||||
public class SuppressByCommentFix extends AbstractSuppressByNoInspectionCommentFix {
|
||||
public class SuppressByCommentFix extends AbstractBatchSuppressByNoInspectionCommentFix {
|
||||
protected Class<? extends PsiElement> mySuppressionHolderClass;
|
||||
|
||||
public SuppressByCommentFix(@NotNull HighlightDisplayKey key, @NotNull Class<? extends PsiElement> suppressionHolderClass) {
|
||||
@@ -46,7 +46,7 @@ public class SuppressByCommentFix extends AbstractSuppressByNoInspectionCommentF
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected PsiElement getContainer(PsiElement context) {
|
||||
public PsiElement getContainer(PsiElement context) {
|
||||
return PsiTreeUtil.getParentOfType(context, mySuppressionHolderClass);
|
||||
}
|
||||
}
|
||||
+82
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -16,11 +16,16 @@
|
||||
|
||||
package com.intellij.codeInspection;
|
||||
|
||||
import com.intellij.lang.Commenter;
|
||||
import com.intellij.lang.LanguageCommenters;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.NullableComputable;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiComment;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiParserFacade;
|
||||
import com.intellij.psi.PsiWhiteSpace;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
@@ -100,4 +105,80 @@ public class SuppressionUtil {
|
||||
}
|
||||
}) != null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PsiComment createComment(@NotNull Project project, @NotNull PsiElement element, @NotNull String commentText) {
|
||||
final PsiParserFacade parserFacade = PsiParserFacade.SERVICE.getInstance(project);
|
||||
return parserFacade.createLineOrBlockCommentFromText(element.getLanguage(), commentText);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Pair<String, String> getBlockPrefixSuffixPair(PsiElement comment) {
|
||||
final Commenter commenter = LanguageCommenters.INSTANCE.forLanguage(comment.getLanguage());
|
||||
if (commenter != null) {
|
||||
final String prefix = commenter.getBlockCommentPrefix();
|
||||
final String suffix = commenter.getBlockCommentSuffix();
|
||||
if (prefix != null || suffix != null) {
|
||||
return Pair.create(StringUtil.notNullize(prefix), StringUtil.notNullize(suffix));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getLineCommentPrefix(@NotNull final PsiElement comment) {
|
||||
final Commenter commenter = LanguageCommenters.INSTANCE.forLanguage(comment.getLanguage());
|
||||
return commenter == null ? null : commenter.getLineCommentPrefix();
|
||||
}
|
||||
|
||||
public static boolean isSuppressionComment(@NotNull PsiElement comment) {
|
||||
final String prefix = getLineCommentPrefix(comment);
|
||||
final String commentText = comment.getText();
|
||||
if (prefix != null) {
|
||||
return commentText.startsWith(prefix + SUPPRESS_INSPECTIONS_TAG_NAME);
|
||||
}
|
||||
final Pair<String, String> prefixSuffixPair = getBlockPrefixSuffixPair(comment);
|
||||
return prefixSuffixPair != null
|
||||
&& commentText.startsWith(prefixSuffixPair.first + SUPPRESS_INSPECTIONS_TAG_NAME)
|
||||
&& commentText.endsWith(prefixSuffixPair.second);
|
||||
}
|
||||
|
||||
public static void replaceSuppressionComment(@NotNull PsiElement comment, @NotNull String id, boolean replaceOtherSuppressionIds) {
|
||||
final String oldSuppressionCommentText = comment.getText();
|
||||
final String lineCommentPrefix = getLineCommentPrefix(comment);
|
||||
Pair<String, String> blockPrefixSuffix = null;
|
||||
if (lineCommentPrefix == null) {
|
||||
blockPrefixSuffix = getBlockPrefixSuffixPair(comment);
|
||||
}
|
||||
assert blockPrefixSuffix != null
|
||||
&& oldSuppressionCommentText.startsWith(blockPrefixSuffix.first)
|
||||
&& oldSuppressionCommentText.endsWith(blockPrefixSuffix.second)
|
||||
|| lineCommentPrefix != null && oldSuppressionCommentText.startsWith(lineCommentPrefix)
|
||||
: "Unexpected suppression comment " + oldSuppressionCommentText;
|
||||
|
||||
// append new suppression tool id or replace
|
||||
final String newText;
|
||||
if(replaceOtherSuppressionIds) {
|
||||
newText = SUPPRESS_INSPECTIONS_TAG_NAME + " " + id;
|
||||
}
|
||||
else if (lineCommentPrefix == null) {
|
||||
newText = oldSuppressionCommentText.substring(blockPrefixSuffix.first.length(),
|
||||
oldSuppressionCommentText.length() - blockPrefixSuffix.second.length()) + "," + id;
|
||||
}
|
||||
else {
|
||||
newText = oldSuppressionCommentText.substring(lineCommentPrefix.length()) + "," + id;
|
||||
}
|
||||
|
||||
PsiElement parent = comment.getParent();
|
||||
comment.replace(createComment(comment.getProject(), parent != null ? parent : comment, newText));
|
||||
}
|
||||
|
||||
public static void createSuppression(@NotNull Project project,
|
||||
@NotNull PsiElement element,
|
||||
@NotNull PsiElement container,
|
||||
@NotNull String id) {
|
||||
final String text = SUPPRESS_INSPECTIONS_TAG_NAME + " " + id;
|
||||
PsiComment comment = createComment(project, element, text);
|
||||
container.getParent().addBefore(comment, container);
|
||||
}
|
||||
}
|
||||
+7
-50
@@ -16,46 +16,20 @@
|
||||
package com.intellij.codeInspection;
|
||||
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.SmartPointerManager;
|
||||
import com.intellij.psi.SmartPsiElementPointer;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public abstract class LocalQuickFixAndIntentionActionOnPsiElement implements LocalQuickFix, IntentionAction {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.LocalQuickFixAndIntentionAction");
|
||||
private final SmartPsiElementPointer<PsiElement> myStartElement;
|
||||
private final SmartPsiElementPointer<PsiElement> myEndElement;
|
||||
|
||||
public abstract class LocalQuickFixAndIntentionActionOnPsiElement extends LocalQuickFixOnPsiElement implements IntentionAction {
|
||||
protected LocalQuickFixAndIntentionActionOnPsiElement(@Nullable PsiElement element) {
|
||||
this(element, element);
|
||||
}
|
||||
protected LocalQuickFixAndIntentionActionOnPsiElement(@Nullable PsiElement startElement, @Nullable PsiElement endElement) {
|
||||
if (startElement == null || endElement == null) {
|
||||
myStartElement = myEndElement = null;
|
||||
return;
|
||||
}
|
||||
LOG.assertTrue(startElement.isValid());
|
||||
PsiFile startContainingFile = startElement.getContainingFile();
|
||||
PsiFile endContainingFile = startElement == endElement ? startContainingFile : endElement.getContainingFile();
|
||||
if (startElement != endElement) {
|
||||
LOG.assertTrue(endElement.isValid());
|
||||
LOG.assertTrue(startContainingFile == endContainingFile, "Both elements must be from the same file");
|
||||
}
|
||||
Project project = startContainingFile == null ? startElement.getProject() : startContainingFile.getProject(); // containingFile can be null for a directory
|
||||
myStartElement = SmartPointerManager.getInstance(project).createSmartPsiElementPointer(startElement, startContainingFile);
|
||||
myEndElement = endElement == startElement ? null : SmartPointerManager.getInstance(project).createSmartPsiElementPointer(endElement, endContainingFile);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public final String getName() {
|
||||
return getText();
|
||||
super(startElement, endElement);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -67,17 +41,6 @@ public abstract class LocalQuickFixAndIntentionActionOnPsiElement implements Loc
|
||||
invoke(project, file, editor, startElement, endElement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
|
||||
if (myStartElement == null) return;
|
||||
final PsiElement startElement = myStartElement.getElement();
|
||||
final PsiElement endElement = myEndElement == null ? startElement : myEndElement.getElement();
|
||||
if (startElement == null || endElement == null) return;
|
||||
PsiFile file = startElement.getContainingFile();
|
||||
if (file == null) return;
|
||||
invoke(project, file, null, startElement, endElement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
|
||||
if (myStartElement == null) return false;
|
||||
@@ -91,23 +54,17 @@ public abstract class LocalQuickFixAndIntentionActionOnPsiElement implements Loc
|
||||
isAvailable(project, file, startElement, endElement);
|
||||
}
|
||||
|
||||
public boolean isAvailable(@NotNull Project project,
|
||||
@NotNull PsiFile file,
|
||||
@NotNull PsiElement startElement,
|
||||
@NotNull PsiElement endElement) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public PsiElement getStartElement() {
|
||||
return myStartElement == null ? null : myStartElement.getElement();
|
||||
}
|
||||
|
||||
public abstract void invoke(@NotNull Project project,
|
||||
@NotNull PsiFile file,
|
||||
@Nullable("is null when called from inspection") Editor editor,
|
||||
@NotNull PsiElement startElement,
|
||||
@NotNull PsiElement endElement);
|
||||
|
||||
@Override
|
||||
public void invoke(@NotNull Project project, @NotNull PsiFile file, @NotNull PsiElement startElement, @NotNull PsiElement endElement) {
|
||||
invoke(project, file, null, startElement, endElement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startInWriteAction() {
|
||||
return true;
|
||||
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class LocalQuickFixAsIntentionAdapter implements IntentionAction {
|
||||
private final LocalQuickFix myFix;
|
||||
@NotNull private final ProblemDescriptor myProblemDescriptor;
|
||||
|
||||
public LocalQuickFixAsIntentionAdapter(@NotNull LocalQuickFix fix, @NotNull ProblemDescriptor problemDescriptor) {
|
||||
myFix = fix;
|
||||
myProblemDescriptor = problemDescriptor;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getText() {
|
||||
return myFix.getName();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getFamilyName() {
|
||||
return myFix.getFamilyName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
|
||||
return myProblemDescriptor.getStartElement() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
|
||||
myFix.applyFix(project, myProblemDescriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startInWriteAction() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,16 +20,95 @@
|
||||
*/
|
||||
package com.intellij.codeInspection;
|
||||
|
||||
import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction;
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.editor.CaretModel;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Iconable;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public abstract class SuppressIntentionAction extends PsiElementBaseIntentionAction implements Iconable {
|
||||
public abstract class SuppressIntentionAction implements Iconable, IntentionAction {
|
||||
private String myText = "";
|
||||
public static SuppressIntentionAction[] EMPTY_ARRAY = new SuppressIntentionAction[0];
|
||||
|
||||
@Override
|
||||
public Icon getIcon(int flags) {
|
||||
return AllIcons.General.InspectionsOff;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getText() {
|
||||
return myText;
|
||||
}
|
||||
|
||||
protected void setText(@NotNull String text) {
|
||||
myText = text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startInWriteAction() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
|
||||
if (!file.getManager().isInProject(file)) return;
|
||||
final PsiElement element = getElement(editor, file);
|
||||
if (element != null) {
|
||||
invoke(project, editor, element);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes intention action for the element under caret.
|
||||
*
|
||||
* @param project the project in which the file is opened.
|
||||
* @param editor the editor for the file.
|
||||
* @param element the element under cursor.
|
||||
* @throws com.intellij.util.IncorrectOperationException
|
||||
*
|
||||
*/
|
||||
public abstract void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException;
|
||||
|
||||
@Override
|
||||
public final boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
|
||||
if (file == null) return false;
|
||||
final PsiManager manager = file.getManager();
|
||||
if (manager == null) return false;
|
||||
if (!manager.isInProject(file)) return false;
|
||||
final PsiElement element = getElement(editor, file);
|
||||
return element != null && isAvailable(project, editor, element);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether this intention is available at a caret offset in file.
|
||||
* If this method returns true, a light bulb for this intention is shown.
|
||||
*
|
||||
* @param project the project in which the availability is checked.
|
||||
* @param editor the editor in which the intention will be invoked.
|
||||
* @param element the element under caret.
|
||||
* @return true if the intention is available, false otherwise.
|
||||
*/
|
||||
public abstract boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element);
|
||||
|
||||
@Nullable
|
||||
private static PsiElement getElement(@NotNull Editor editor, @NotNull PsiFile file) {
|
||||
CaretModel caretModel = editor.getCaretModel();
|
||||
int position = caretModel.getOffset();
|
||||
return file.findElementAt(position);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,7 @@ package com.intellij.lang.annotation;
|
||||
|
||||
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.codeInspection.LocalQuickFix;
|
||||
import com.intellij.codeInspection.ProblemHighlightType;
|
||||
import com.intellij.codeInspection.*;
|
||||
import com.intellij.openapi.editor.HighlighterColors;
|
||||
import com.intellij.openapi.editor.colors.CodeInsightColors;
|
||||
import com.intellij.openapi.editor.colors.TextAttributesKey;
|
||||
@@ -75,7 +74,7 @@ public final class Annotation implements Segment {
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
public QuickFixInfo(final IntentionAction fix, final TextRange range, @Nullable final HighlightDisplayKey key) {
|
||||
public QuickFixInfo(@NotNull IntentionAction fix, final TextRange range, @Nullable final HighlightDisplayKey key) {
|
||||
this.key = key;
|
||||
quickFix = fix;
|
||||
textRange = range;
|
||||
@@ -123,6 +122,16 @@ public final class Annotation implements Segment {
|
||||
registerFix(fix,range, null);
|
||||
}
|
||||
|
||||
public void registerFix(@NotNull LocalQuickFix fix, TextRange range, HighlightDisplayKey key, @NotNull ProblemDescriptor problemDescriptor) {
|
||||
if (range == null) {
|
||||
range = new TextRange(myStartOffset, myEndOffset);
|
||||
}
|
||||
if (myQuickFixes == null) {
|
||||
myQuickFixes = new ArrayList<QuickFixInfo>();
|
||||
}
|
||||
myQuickFixes.add(new QuickFixInfo(new LocalQuickFixAsIntentionAdapter(fix, problemDescriptor), range, key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a quick fix for the annotation which is only available on a particular range of text
|
||||
* within the annotation.
|
||||
@@ -159,8 +168,8 @@ public final class Annotation implements Segment {
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a quickfix which would be available during batch mode only,
|
||||
* in particular during com.intellij.codeInspection.DefaultHighlightVisitorBasedInspection run
|
||||
* Registers a quickfix which would be available during batch mode only,
|
||||
* in particular during com.intellij.codeInspection.DefaultHighlightVisitorBasedInspection run
|
||||
*/
|
||||
public <T extends IntentionAction & LocalQuickFix> void registerBatchFix(@NotNull T fix, @Nullable TextRange range, @Nullable final HighlightDisplayKey key) {
|
||||
if (range == null) {
|
||||
@@ -302,7 +311,7 @@ public final class Annotation implements Segment {
|
||||
public List<QuickFixInfo> getQuickFixes() {
|
||||
return myQuickFixes;
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
public List<QuickFixInfo> getBatchFixes() {
|
||||
return myBatchFixes;
|
||||
|
||||
@@ -22,9 +22,7 @@ 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.LocalInspectionToolWrapper;
|
||||
import com.intellij.codeInspection.ex.QuickFixWrapper;
|
||||
import com.intellij.codeInspection.ex.*;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.lang.annotation.Annotation;
|
||||
import com.intellij.lang.annotation.HighlightSeverity;
|
||||
@@ -48,6 +46,7 @@ import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.util.ArrayUtilRt;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.xml.util.XmlStringUtil;
|
||||
import org.intellij.lang.annotations.MagicConstant;
|
||||
@@ -727,11 +726,18 @@ public class HighlightInfo implements Segment {
|
||||
this(action, null, null, icon);
|
||||
}
|
||||
|
||||
public IntentionActionDescriptor(@NotNull IntentionAction action, @Nullable final List<IntentionAction> options, @Nullable final String displayName, @Nullable Icon icon) {
|
||||
public IntentionActionDescriptor(@NotNull IntentionAction action,
|
||||
@Nullable final List<IntentionAction> options,
|
||||
@Nullable final String displayName,
|
||||
@Nullable Icon icon) {
|
||||
this(action, options, displayName, icon, null);
|
||||
}
|
||||
|
||||
public IntentionActionDescriptor(@NotNull IntentionAction action, @Nullable final List<IntentionAction> options, @Nullable final String displayName, @Nullable Icon icon, @Nullable HighlightDisplayKey key) {
|
||||
public IntentionActionDescriptor(@NotNull IntentionAction action,
|
||||
@Nullable final List<IntentionAction> options,
|
||||
@Nullable final String displayName,
|
||||
@Nullable Icon icon,
|
||||
@Nullable HighlightDisplayKey key) {
|
||||
myAction = action;
|
||||
myOptions = options;
|
||||
myDisplayName = displayName;
|
||||
@@ -788,6 +794,15 @@ public class HighlightInfo implements Segment {
|
||||
ContainerUtil.addAll(newOptions, suppressActions);
|
||||
}
|
||||
}
|
||||
if (wrappedTool instanceof BatchSuppressableTool) {
|
||||
final SuppressQuickFix[] suppressActions = ((BatchSuppressableTool)wrappedTool).getBatchSuppressActions(element);
|
||||
ContainerUtil.addAll(newOptions, ContainerUtil.map(suppressActions, new Function<SuppressQuickFix, IntentionAction>() {
|
||||
@Override
|
||||
public IntentionAction fun(SuppressQuickFix fix) {
|
||||
return InspectionManagerEx.convertBatchToSuppressIntentionAction(fix);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
synchronized (this) {
|
||||
options = myOptions;
|
||||
|
||||
+19
-78
@@ -16,20 +16,17 @@
|
||||
|
||||
package com.intellij.codeInsight.daemon.impl.actions;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.intellij.codeInsight.FileModificationService;
|
||||
import com.intellij.codeInspection.InspectionsBundle;
|
||||
import com.intellij.codeInspection.SuppressIntentionAction;
|
||||
import com.intellij.codeInspection.SuppressionUtil;
|
||||
import com.intellij.lang.Commenter;
|
||||
import com.intellij.lang.LanguageCommenters;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.undo.UndoUtil;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.psi.PsiComment;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiParserFacade;
|
||||
import com.intellij.psi.PsiWhiteSpace;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
@@ -44,7 +41,7 @@ import java.util.List;
|
||||
* @date Aug 13, 2009
|
||||
*/
|
||||
public abstract class AbstractSuppressByNoInspectionCommentFix extends SuppressIntentionAction {
|
||||
protected final String myID;
|
||||
@NotNull protected final String myID;
|
||||
private final boolean myReplaceOtherSuppressionIds;
|
||||
|
||||
@Nullable
|
||||
@@ -55,71 +52,19 @@ public abstract class AbstractSuppressByNoInspectionCommentFix extends SuppressI
|
||||
* @param replaceOtherSuppressionIds Merge suppression policy. If false new tool id will be append to the end
|
||||
* otherwise replace other ids
|
||||
*/
|
||||
public AbstractSuppressByNoInspectionCommentFix(final String ID, final boolean replaceOtherSuppressionIds) {
|
||||
public AbstractSuppressByNoInspectionCommentFix(@NotNull String ID, final boolean replaceOtherSuppressionIds) {
|
||||
myID = ID;
|
||||
myReplaceOtherSuppressionIds = replaceOtherSuppressionIds;
|
||||
}
|
||||
|
||||
protected final void replaceSuppressionComment(@NotNull final PsiElement comment) {
|
||||
final String oldSuppressionCommentText = comment.getText();
|
||||
final String lineCommentPrefix = getLineCommentPrefix(comment);
|
||||
Pair<String, String> blockPrefixSuffix = null;
|
||||
if (lineCommentPrefix == null) {
|
||||
blockPrefixSuffix = getBlockPrefixSuffixPair(comment);
|
||||
}
|
||||
assert (blockPrefixSuffix != null && oldSuppressionCommentText.startsWith(blockPrefixSuffix.first)) && oldSuppressionCommentText.endsWith(blockPrefixSuffix.second)
|
||||
|| (lineCommentPrefix != null && oldSuppressionCommentText.startsWith(lineCommentPrefix))
|
||||
: "Unexpected suppression comment " + oldSuppressionCommentText;
|
||||
|
||||
// append new suppression tool id or replace
|
||||
final String newText;
|
||||
if(myReplaceOtherSuppressionIds) {
|
||||
newText = SuppressionUtil.SUPPRESS_INSPECTIONS_TAG_NAME + " " + myID;
|
||||
} else {
|
||||
if (lineCommentPrefix != null) {
|
||||
newText = oldSuppressionCommentText.substring(lineCommentPrefix.length()) + "," + myID;
|
||||
} else {
|
||||
newText = oldSuppressionCommentText.substring(blockPrefixSuffix.first.length(),
|
||||
oldSuppressionCommentText.length() - blockPrefixSuffix.second.length()) + "," + myID;
|
||||
}
|
||||
}
|
||||
|
||||
PsiElement parent = comment.getParent();
|
||||
comment.replace(createComment(comment.getProject(), parent != null ? parent : comment, newText));
|
||||
SuppressionUtil.replaceSuppressionComment(comment, myID, myReplaceOtherSuppressionIds);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String getLineCommentPrefix(@NotNull final PsiElement comment) {
|
||||
final Commenter commenter = LanguageCommenters.INSTANCE.forLanguage(comment.getLanguage());
|
||||
return commenter == null ? null : commenter.getLineCommentPrefix();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Pair<String, String> getBlockPrefixSuffixPair(PsiElement comment) {
|
||||
final Commenter commenter = LanguageCommenters.INSTANCE.forLanguage(comment.getLanguage());
|
||||
if (commenter != null) {
|
||||
final String prefix = commenter.getBlockCommentPrefix();
|
||||
final String suffix = commenter.getBlockCommentSuffix();
|
||||
if (prefix != null || suffix != null) {
|
||||
return Pair.create(Strings.nullToEmpty(prefix), Strings.nullToEmpty(suffix));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void createSuppression(final Project project,
|
||||
final Editor editor,
|
||||
final PsiElement element,
|
||||
final PsiElement container) throws IncorrectOperationException {
|
||||
final String text = SuppressionUtil.SUPPRESS_INSPECTIONS_TAG_NAME + " " + myID;
|
||||
PsiComment comment = createComment(project, element, text);
|
||||
container.getParent().addBefore(comment, container);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected PsiComment createComment(Project project, PsiElement element, String commentText) {
|
||||
final PsiParserFacade parserFacade = PsiParserFacade.SERVICE.getInstance(project);
|
||||
return parserFacade.createLineOrBlockCommentFromText(element.getLanguage(), commentText);
|
||||
protected void createSuppression(@NotNull Project project,
|
||||
@NotNull PsiElement element,
|
||||
@NotNull PsiElement container) throws IncorrectOperationException {
|
||||
SuppressionUtil.createSuppression(project, element, container, myID);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -137,7 +82,7 @@ public abstract class AbstractSuppressByNoInspectionCommentFix extends SuppressI
|
||||
final List<? extends PsiElement> comments = getCommentsFor(container);
|
||||
if (comments != null) {
|
||||
for (PsiElement comment : comments) {
|
||||
if (comment instanceof PsiComment && isSuppressionComment(comment)) {
|
||||
if (comment instanceof PsiComment && SuppressionUtil.isSuppressionComment(comment)) {
|
||||
replaceSuppressionComment(comment);
|
||||
return;
|
||||
}
|
||||
@@ -145,7 +90,15 @@ public abstract class AbstractSuppressByNoInspectionCommentFix extends SuppressI
|
||||
}
|
||||
|
||||
boolean caretWasBeforeStatement = editor != null && editor.getCaretModel().getOffset() == container.getTextRange().getStartOffset();
|
||||
createSuppression(project, editor, element, container);
|
||||
try {
|
||||
createSuppression(project, element, container);
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
if (!ApplicationManager.getApplication().isUnitTestMode() && editor != null) {
|
||||
Messages.showErrorDialog(editor.getComponent(),
|
||||
InspectionsBundle.message("suppress.inspection.annotation.syntax.error", e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
if (caretWasBeforeStatement) {
|
||||
editor.getCaretModel().moveToOffset(container.getTextRange().getStartOffset());
|
||||
@@ -153,18 +106,6 @@ public abstract class AbstractSuppressByNoInspectionCommentFix extends SuppressI
|
||||
UndoUtil.markPsiFileForUndo(element.getContainingFile());
|
||||
}
|
||||
|
||||
public static boolean isSuppressionComment(PsiElement comment) {
|
||||
final String prefix = getLineCommentPrefix(comment);
|
||||
final String commentText = comment.getText();
|
||||
if (prefix != null) {
|
||||
return commentText.startsWith(prefix + SuppressionUtil.SUPPRESS_INSPECTIONS_TAG_NAME);
|
||||
}
|
||||
final Pair<String, String> prefixSuffixPair = getBlockPrefixSuffixPair(comment);
|
||||
return prefixSuffixPair != null
|
||||
&& commentText.startsWith(prefixSuffixPair.first + SuppressionUtil.SUPPRESS_INSPECTIONS_TAG_NAME)
|
||||
&& commentText.endsWith(prefixSuffixPair.second);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected List<? extends PsiElement> getCommentsFor(@NotNull final PsiElement container) {
|
||||
final PsiElement prev = PsiTreeUtil.skipSiblingsBackward(container, PsiWhiteSpace.class);
|
||||
|
||||
+33
-20
@@ -105,7 +105,7 @@ public class FileReferenceQuickFixProvider {
|
||||
|
||||
final VirtualFile virtualFile = context.getVirtualFile();
|
||||
if (virtualFile == null) return Collections.emptyList();
|
||||
|
||||
|
||||
final PsiDirectory directory = context.getManager().findDirectory(virtualFile);
|
||||
if (directory == null) return Collections.emptyList();
|
||||
|
||||
@@ -147,25 +147,7 @@ public class FileReferenceQuickFixProvider {
|
||||
isdirectory = false;
|
||||
}
|
||||
|
||||
final CreateFileFix action = new CreateFileFix(isdirectory, newFileName, directory) {
|
||||
@Override
|
||||
protected String getFileText() {
|
||||
if (!isdirectory) {
|
||||
String templateName = reference.getNewFileTemplateName();
|
||||
if (templateName != null) {
|
||||
FileTemplate template = FileTemplateManager.getInstance().getTemplate(templateName);
|
||||
if (template != null) {
|
||||
try {
|
||||
return template.getText(FileTemplateManager.getInstance().getDefaultProperties(directory.getProject()));
|
||||
} catch (IOException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.getFileText();
|
||||
}
|
||||
};
|
||||
final CreateFileFix action = new MyCreateFileFix(isdirectory, newFileName, directory, reference);
|
||||
QuickFixAction.registerQuickFixAction(info, action);
|
||||
return Arrays.asList(action);
|
||||
}
|
||||
@@ -176,4 +158,35 @@ public class FileReferenceQuickFixProvider {
|
||||
VirtualFile file = context.getVirtualFile();
|
||||
return file != null ? ModuleUtil.findModuleForFile(file, context.getProject()) : null;
|
||||
}
|
||||
|
||||
private static class MyCreateFileFix extends CreateFileFix {
|
||||
private final boolean isDirectory;
|
||||
private final PsiDirectory myDirectory;
|
||||
private final FileReference myReference;
|
||||
|
||||
public MyCreateFileFix(boolean isdirectory, String newFileName, PsiDirectory directory, FileReference reference) {
|
||||
super(isdirectory, newFileName, directory);
|
||||
isDirectory = isdirectory;
|
||||
myDirectory = directory;
|
||||
myReference = reference;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFileText() {
|
||||
if (!isDirectory) {
|
||||
String templateName = myReference.getNewFileTemplateName();
|
||||
if (templateName != null) {
|
||||
FileTemplate template = FileTemplateManager.getInstance().getTemplate(templateName);
|
||||
if (template != null) {
|
||||
try {
|
||||
return template.getText(FileTemplateManager.getInstance().getDefaultProperties(myDirectory.getProject()));
|
||||
} catch (IOException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.getFileText();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,13 +22,16 @@
|
||||
|
||||
package com.intellij.codeInspection.ex;
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.actions.AbstractBatchSuppressByNoInspectionCommentFix;
|
||||
import com.intellij.codeInspection.*;
|
||||
import com.intellij.codeInspection.lang.InspectionExtensionsFactory;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.ide.impl.ContentManagerWatcher;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.NotNullLazyValue;
|
||||
import com.intellij.openapi.wm.ToolWindow;
|
||||
import com.intellij.openapi.wm.ToolWindowAnchor;
|
||||
@@ -40,6 +43,7 @@ import com.intellij.psi.PsiElement;
|
||||
import com.intellij.ui.content.ContentFactory;
|
||||
import com.intellij.ui.content.ContentManager;
|
||||
import com.intellij.ui.content.TabbedPaneContentUI;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -82,6 +86,53 @@ public class InspectionManagerEx extends InspectionManagerBase {
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static SuppressIntentionAction convertBatchToSuppressIntentionAction(@NotNull final SuppressQuickFix fix) {
|
||||
return new SuppressIntentionAction() {
|
||||
@Override
|
||||
public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException {
|
||||
PsiElement container = fix instanceof AbstractBatchSuppressByNoInspectionCommentFix
|
||||
? ((AbstractBatchSuppressByNoInspectionCommentFix )fix).getContainer(element) : null;
|
||||
boolean caretWasBeforeStatement = editor != null && container != null && editor.getCaretModel().getOffset() == container.getTextRange().getStartOffset();
|
||||
try {
|
||||
ProblemDescriptor descriptor =
|
||||
new ProblemDescriptorImpl(element, element, "", null, ProblemHighlightType.GENERIC_ERROR_OR_WARNING, false, null, false);
|
||||
fix.applyFix(project, descriptor);
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
if (!ApplicationManager.getApplication().isUnitTestMode() && editor != null) {
|
||||
Messages.showErrorDialog(editor.getComponent(),
|
||||
InspectionsBundle.message("suppress.inspection.annotation.syntax.error", e.getMessage()));
|
||||
}
|
||||
else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
if (caretWasBeforeStatement) {
|
||||
editor.getCaretModel().moveToOffset(container.getTextRange().getStartOffset());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) {
|
||||
return fix.isAvailable(project, element);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getText() {
|
||||
return fix.getName();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getFamilyName() {
|
||||
return fix.getFamilyName();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
public ProblemDescriptor createProblemDescriptor(@NotNull final PsiElement psiElement,
|
||||
@@ -133,6 +184,9 @@ public class InspectionManagerEx extends InspectionManagerBase {
|
||||
if (tool instanceof CustomSuppressableInspectionTool) {
|
||||
return ((CustomSuppressableInspectionTool)tool).isSuppressedFor(place);
|
||||
}
|
||||
if (tool instanceof BatchSuppressableTool) {
|
||||
return ((BatchSuppressableTool)tool).isSuppressedFor(place);
|
||||
}
|
||||
String alternativeId;
|
||||
String id;
|
||||
|
||||
|
||||
@@ -16,15 +16,14 @@
|
||||
package com.intellij.codeInspection.ex;
|
||||
|
||||
import com.intellij.codeHighlighting.HighlightDisplayLevel;
|
||||
import com.intellij.codeInspection.CustomSuppressableInspectionTool;
|
||||
import com.intellij.codeInspection.InspectionEP;
|
||||
import com.intellij.codeInspection.InspectionProfileEntry;
|
||||
import com.intellij.codeInspection.SuppressIntentionAction;
|
||||
import com.intellij.codeInspection.*;
|
||||
import com.intellij.openapi.application.Application;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.InvalidDataException;
|
||||
import com.intellij.openapi.util.WriteExternalException;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -185,14 +184,23 @@ public abstract class InspectionToolWrapper<T extends InspectionProfileEntry, E
|
||||
return super.getDescriptionUrl();
|
||||
}
|
||||
String fileName = getDescriptionFileName();
|
||||
if (fileName == null) return null;
|
||||
return myEP.getLoaderForClass().getResource("/inspectionDescriptions/" + fileName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SuppressIntentionAction[] getSuppressActions() {
|
||||
if (getTool() instanceof CustomSuppressableInspectionTool) {
|
||||
return ((CustomSuppressableInspectionTool)getTool()).getSuppressActions(null);
|
||||
T tool = getTool();
|
||||
if (tool instanceof CustomSuppressableInspectionTool) {
|
||||
return ((CustomSuppressableInspectionTool)tool).getSuppressActions(null);
|
||||
}
|
||||
if (tool instanceof BatchSuppressableTool) {
|
||||
LocalQuickFix[] actions = ((BatchSuppressableTool)tool).getBatchSuppressActions(null);
|
||||
return ContainerUtil.map2Array(actions, SuppressIntentionAction.class, new Function<LocalQuickFix, SuppressIntentionAction>() {
|
||||
@Override
|
||||
public SuppressIntentionAction fun(final LocalQuickFix fix) {
|
||||
return InspectionManagerEx.convertBatchToSuppressIntentionAction((SuppressQuickFix)fix);
|
||||
}
|
||||
});
|
||||
}
|
||||
return super.getSuppressActions();
|
||||
}
|
||||
|
||||
+2
-1
@@ -26,6 +26,7 @@ import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ModuleRootManager;
|
||||
import com.intellij.openapi.roots.ModuleRootModel;
|
||||
import com.intellij.openapi.roots.impl.storage.ClassPathStorageUtil;
|
||||
import com.intellij.openapi.roots.impl.storage.ClasspathStorage;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
@@ -65,7 +66,7 @@ public class ExportEclipseProjectsAction extends AnAction implements DumbAware {
|
||||
final List<Module> modules = new ArrayList<Module>();
|
||||
final List<Module> incompatibleModules = new ArrayList<Module>();
|
||||
for (Module module : ModuleManager.getInstance(project).getModules()) {
|
||||
if (!JpsEclipseClasspathSerializer.CLASSPATH_STORAGE_ID.equals(ClasspathStorage.getStorageType(module))) {
|
||||
if (!JpsEclipseClasspathSerializer.CLASSPATH_STORAGE_ID.equals(ClassPathStorageUtil.getStorageType(module))) {
|
||||
try {
|
||||
ClasspathStorage.getProvider(JpsEclipseClasspathSerializer.CLASSPATH_STORAGE_ID).assertCompatible(ModuleRootManager.getInstance(module));
|
||||
modules.add(module);
|
||||
|
||||
+7
-5
@@ -44,22 +44,24 @@ import java.util.regex.Matcher;
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public abstract class GroovySuppressableInspectionTool extends LocalInspectionTool implements CustomSuppressableInspectionTool {
|
||||
@Nullable
|
||||
public SuppressIntentionAction[] getSuppressActions(final PsiElement element) {
|
||||
public abstract class GroovySuppressableInspectionTool extends LocalInspectionTool implements BatchSuppressableTool {
|
||||
@NotNull
|
||||
@Override
|
||||
public SuppressQuickFix[] getBatchSuppressActions(@Nullable PsiElement element) {
|
||||
return getSuppressActions(getShortName());
|
||||
|
||||
}
|
||||
|
||||
public static SuppressIntentionAction[] getSuppressActions(String name) {
|
||||
public static SuppressQuickFix[] getSuppressActions(String name) {
|
||||
final HighlightDisplayKey displayKey = HighlightDisplayKey.find(name);
|
||||
return new SuppressIntentionAction[]{
|
||||
return new SuppressQuickFix[] {
|
||||
new SuppressByGroovyCommentFix(displayKey),
|
||||
new SuppressForMemberFix(displayKey, false),
|
||||
new SuppressForMemberFix(displayKey, true),
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSuppressedFor(@NotNull final PsiElement element) {
|
||||
return isElementToolSuppressedIn(element, getID());
|
||||
}
|
||||
|
||||
+2
-1
@@ -31,8 +31,9 @@ public class SuppressByGroovyCommentFix extends SuppressByCommentFix {
|
||||
super(key, GrStatement.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected PsiElement getContainer(PsiElement context) {
|
||||
public PsiElement getContainer(PsiElement context) {
|
||||
return PsiUtil.findEnclosingStatement(context);
|
||||
}
|
||||
|
||||
|
||||
+19
-20
@@ -16,13 +16,11 @@
|
||||
|
||||
package org.jetbrains.plugins.groovy.codeInspection;
|
||||
|
||||
import com.intellij.codeInsight.FileModificationService;
|
||||
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
|
||||
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
|
||||
import com.intellij.codeInsight.daemon.impl.actions.AbstractBatchSuppressByNoInspectionCommentFix;
|
||||
import com.intellij.codeInspection.InspectionsBundle;
|
||||
import com.intellij.codeInspection.SuppressIntentionAction;
|
||||
import com.intellij.codeInspection.SuppressManager;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
@@ -43,18 +41,18 @@ import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeParameter;
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class SuppressForMemberFix extends SuppressIntentionAction {
|
||||
private final String myID;
|
||||
public class SuppressForMemberFix extends AbstractBatchSuppressByNoInspectionCommentFix {
|
||||
private String myKey;
|
||||
private final boolean myForClass;
|
||||
|
||||
public SuppressForMemberFix(HighlightDisplayKey key, boolean forClass) {
|
||||
myID = key.getID();
|
||||
public SuppressForMemberFix(@NotNull HighlightDisplayKey key, boolean forClass) {
|
||||
super(key.getID(), false);
|
||||
myForClass = forClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected GrDocCommentOwner getContainer(final PsiElement context) {
|
||||
public GrDocCommentOwner getContainer(final PsiElement context) {
|
||||
if (context == null || context instanceof PsiFile) {
|
||||
return null;
|
||||
}
|
||||
@@ -76,7 +74,7 @@ public class SuppressForMemberFix extends SuppressIntentionAction {
|
||||
if (myForClass) {
|
||||
while (container != null ) {
|
||||
final GrTypeDefinition parentClass = PsiTreeUtil.getParentOfType(container, GrTypeDefinition.class);
|
||||
if ((parentClass == null) && container instanceof GrTypeDefinition){
|
||||
if (parentClass == null && container instanceof GrTypeDefinition){
|
||||
return container;
|
||||
}
|
||||
container = parentClass;
|
||||
@@ -85,28 +83,29 @@ public class SuppressForMemberFix extends SuppressIntentionAction {
|
||||
return container;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getText() {
|
||||
return myKey != null ? InspectionsBundle.message(myKey) : "Suppress for member";
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
public String getFamilyName() {
|
||||
return InspectionsBundle.message("suppress.inspection.family");
|
||||
}
|
||||
|
||||
public boolean isAvailable(@NotNull final Project project, final Editor editor, @NotNull final PsiElement context) {
|
||||
@Override
|
||||
public boolean isAvailable(@NotNull final Project project, @NotNull final PsiElement context) {
|
||||
final GrDocCommentOwner container = getContainer(context);
|
||||
myKey = container instanceof PsiClass ? "suppress.inspection.class" : container instanceof PsiMethod ? "suppress.inspection.method" : "suppress.inspection.field";
|
||||
return container != null && context.getManager().isInProject(context);
|
||||
}
|
||||
|
||||
public void invoke(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) throws IncorrectOperationException {
|
||||
GrDocCommentOwner container = getContainer(element);
|
||||
assert container != null;
|
||||
if (!FileModificationService.getInstance().preparePsiElementForWrite(container)) return;
|
||||
final GrModifierList modifierList = (GrModifierList)container.getModifierList();
|
||||
@Override
|
||||
protected boolean replaceSuppressionComments(PsiElement container) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createSuppression(@NotNull Project project, @NotNull PsiElement element, @NotNull PsiElement container)
|
||||
throws IncorrectOperationException {
|
||||
final GrModifierList modifierList = (GrModifierList)((PsiModifierListOwner)container).getModifierList();
|
||||
if (modifierList != null) {
|
||||
addSuppressAnnotation(project, modifierList, myID);
|
||||
}
|
||||
|
||||
+3
-3
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package org.jetbrains.plugins.groovy.codeInspection.spellchecker;
|
||||
|
||||
import com.intellij.codeInspection.SuppressIntentionAction;
|
||||
import com.intellij.codeInspection.SuppressQuickFix;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.javadoc.PsiDocComment;
|
||||
import com.intellij.spellchecker.inspections.PlainTextSplitter;
|
||||
@@ -34,7 +34,7 @@ import org.jetbrains.plugins.groovy.lang.psi.util.GrStringUtil;
|
||||
*/
|
||||
public class GroovySpellcheckingStrategy extends SuppressibleSpellcheckingStrategy {
|
||||
private final GrDocCommentTokenizer myDocCommentTokenizer = new GrDocCommentTokenizer();
|
||||
private Tokenizer<PsiElement> myStringTokenizer = new Tokenizer<PsiElement>() {
|
||||
private final Tokenizer<PsiElement> myStringTokenizer = new Tokenizer<PsiElement>() {
|
||||
@Override
|
||||
public void tokenize(@NotNull PsiElement literal, TokenConsumer consumer) {
|
||||
String text = GrStringUtil.removeQuotes(literal.getText());
|
||||
@@ -73,7 +73,7 @@ public class GroovySpellcheckingStrategy extends SuppressibleSpellcheckingStrate
|
||||
}
|
||||
|
||||
@Override
|
||||
public SuppressIntentionAction[] getSuppressActions(@NotNull PsiElement element, @NotNull String name) {
|
||||
public SuppressQuickFix[] getSuppressActions(@NotNull PsiElement element, @NotNull String name) {
|
||||
return GroovySuppressableInspectionTool.getSuppressActions(name);
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -19,7 +19,7 @@ import com.intellij.codeInsight.FileModificationService;
|
||||
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
|
||||
import com.intellij.codeInspection.InspectionsBundle;
|
||||
import com.intellij.codeInspection.SuppressIntentionAction;
|
||||
import com.intellij.lang.StdLanguages;
|
||||
import com.intellij.lang.java.JavaLanguage;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
@@ -76,13 +76,13 @@ class SuppressByCommentOutAction extends SuppressIntentionAction {
|
||||
if (!element.isValid()) {
|
||||
return false;
|
||||
}
|
||||
// find java code up there, going through injecttions if necessary
|
||||
// find java code up there, going through injections if necessary
|
||||
return findJavaCodeUpThere(element) != null;
|
||||
}
|
||||
|
||||
private static PsiElement findJavaCodeUpThere(PsiElement element) {
|
||||
while (element != null) {
|
||||
if (element.getLanguage() == StdLanguages.JAVA) return element;
|
||||
if (element.getLanguage() == JavaLanguage.INSTANCE) return element;
|
||||
element = element.getContext();
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -16,8 +16,9 @@
|
||||
package com.intellij.spellchecker;
|
||||
|
||||
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
|
||||
import com.intellij.codeInspection.SuppressIntentionAction;
|
||||
import com.intellij.codeInspection.BatchSuppressManager;
|
||||
import com.intellij.codeInspection.SuppressManager;
|
||||
import com.intellij.codeInspection.SuppressQuickFix;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiLiteralExpression;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
@@ -64,7 +65,7 @@ public class JavaSpellcheckingStrategy extends SuppressibleSpellcheckingStrategy
|
||||
}
|
||||
|
||||
@Override
|
||||
public SuppressIntentionAction[] getSuppressActions(@NotNull PsiElement element, @NotNull String name) {
|
||||
return SuppressManager.getInstance().createSuppressActions(HighlightDisplayKey.find(name));
|
||||
public SuppressQuickFix[] getSuppressActions(@NotNull PsiElement element, @NotNull String name) {
|
||||
return BatchSuppressManager.SERVICE.getInstance().createBatchSuppressActions(HighlightDisplayKey.find(name));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1078,6 +1078,8 @@
|
||||
|
||||
<applicationService serviceInterface="com.intellij.codeInspection.SuppressManager"
|
||||
serviceImplementation="com.intellij.codeInspection.SuppressManagerImpl"/>
|
||||
<applicationService serviceInterface="com.intellij.codeInspection.BatchSuppressManager"
|
||||
serviceImplementation="com.intellij.codeInspection.BatchSuppressManagerImpl"/>
|
||||
|
||||
<declarationRangeHandler key="com.intellij.psi.PsiMethod"
|
||||
implementationClass="com.intellij.codeInsight.hint.MethodDeclarationRangeHandler"/>
|
||||
|
||||
@@ -40,8 +40,7 @@ import java.awt.*;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
public class SpellCheckingInspection extends LocalInspectionTool implements CustomSuppressableInspectionTool {
|
||||
|
||||
public class SpellCheckingInspection extends LocalInspectionTool implements BatchSuppressableTool {
|
||||
public static final String SPELL_CHECKING_INSPECTION_TOOL_NAME = "SpellCheckingInspection";
|
||||
|
||||
@Override
|
||||
@@ -58,15 +57,16 @@ public class SpellCheckingInspection extends LocalInspectionTool implements Cust
|
||||
return SpellCheckerBundle.message("spellchecking.inspection.name");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public SuppressIntentionAction[] getSuppressActions(@Nullable PsiElement element) {
|
||||
public SuppressQuickFix[] getBatchSuppressActions(@Nullable PsiElement element) {
|
||||
if (element != null) {
|
||||
SpellcheckingStrategy strategy = LanguageSpellchecking.INSTANCE.forLanguage(element.getLanguage());
|
||||
if(strategy instanceof SuppressibleSpellcheckingStrategy) {
|
||||
return ((SuppressibleSpellcheckingStrategy)strategy).getSuppressActions(element, getShortName());
|
||||
}
|
||||
}
|
||||
return SuppressIntentionAction.EMPTY_ARRAY;
|
||||
return SuppressQuickFix.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package com.intellij.spellchecker.tokenizer;
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.actions.AbstractSuppressByNoInspectionCommentFix;
|
||||
import com.intellij.codeInspection.SuppressionUtil;
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
@@ -51,7 +51,7 @@ public class SpellcheckingStrategy {
|
||||
public Tokenizer getTokenizer(PsiElement element) {
|
||||
if (element instanceof PsiNameIdentifierOwner) return new PsiIdentifierOwnerTokenizer();
|
||||
if (element instanceof PsiComment) {
|
||||
if (AbstractSuppressByNoInspectionCommentFix.isSuppressionComment(element)) {
|
||||
if (SuppressionUtil.isSuppressionComment(element)) {
|
||||
return EMPTY_TOKENIZER;
|
||||
}
|
||||
return myCommentTokenizer;
|
||||
|
||||
+3
-3
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package com.intellij.spellchecker.tokenizer;
|
||||
|
||||
import com.intellij.codeInspection.SuppressIntentionAction;
|
||||
import com.intellij.codeInspection.SuppressQuickFix;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -30,7 +30,7 @@ public abstract class SuppressibleSpellcheckingStrategy extends SpellcheckingStr
|
||||
public abstract boolean isSuppressedFor(@NotNull PsiElement element, @NotNull String name);
|
||||
|
||||
/**
|
||||
* @see com.intellij.codeInspection.CustomSuppressableInspectionTool#getSuppressActions(com.intellij.psi.PsiElement)
|
||||
* @see com.intellij.codeInspection.BatchSuppressableTool#getBatchSuppressActions(com.intellij.psi.PsiElement)
|
||||
*/
|
||||
public abstract SuppressIntentionAction[] getSuppressActions(@NotNull PsiElement element, @NotNull String name);
|
||||
public abstract SuppressQuickFix[] getSuppressActions(@NotNull PsiElement element, @NotNull String name);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.intellij.spellchecker.xml;
|
||||
|
||||
import com.intellij.codeInspection.SuppressIntentionAction;
|
||||
import com.intellij.codeInspection.SuppressQuickFix;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.spellchecker.tokenizer.SuppressibleSpellcheckingStrategy;
|
||||
import com.intellij.util.xml.DomElement;
|
||||
@@ -25,7 +25,7 @@ public class XmlSpellcheckingStrategy extends SuppressibleSpellcheckingStrategy
|
||||
}
|
||||
|
||||
@Override
|
||||
public SuppressIntentionAction[] getSuppressActions(@NotNull PsiElement element, @NotNull String name) {
|
||||
return SuppressIntentionAction.EMPTY_ARRAY;
|
||||
public SuppressQuickFix[] getSuppressActions(@NotNull PsiElement element, @NotNull String name) {
|
||||
return SuppressQuickFix.EMPTY_ARRAY;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,22 +16,22 @@
|
||||
|
||||
package com.intellij.codeInspection;
|
||||
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.xml.XmlFile;
|
||||
import com.intellij.psi.xml.XmlTag;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public abstract class XmlSuppressableInspectionTool extends LocalInspectionTool implements CustomSuppressableInspectionTool {
|
||||
public abstract class XmlSuppressableInspectionTool extends LocalInspectionTool implements BatchSuppressableTool {
|
||||
@NonNls static final String ALL = "ALL";
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public SuppressIntentionAction[] getSuppressActions(final PsiElement element) {
|
||||
return new SuppressIntentionAction[]{new SuppressTag(), new SuppressForFile(getID()), new SuppressAllForFile()};
|
||||
public SuppressQuickFix[] getBatchSuppressActions(@Nullable PsiElement element) {
|
||||
return new SuppressQuickFix[]{new SuppressTag(), new SuppressForFile(getID()), new SuppressAllForFile()};
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -40,81 +40,83 @@ public abstract class XmlSuppressableInspectionTool extends LocalInspectionTool
|
||||
}
|
||||
|
||||
public class SuppressTag extends SuppressTagStatic {
|
||||
|
||||
public SuppressTag() {
|
||||
super(getID());
|
||||
}
|
||||
}
|
||||
|
||||
public static class SuppressTagStatic extends SuppressIntentionAction {
|
||||
public static class SuppressTagStatic implements SuppressQuickFix {
|
||||
private final String id;
|
||||
|
||||
public SuppressTagStatic(@NotNull String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getText() {
|
||||
@Override
|
||||
public String getName() {
|
||||
return InspectionsBundle.message("xml.suppressable.for.tag.title");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(@NotNull Project project, @NotNull PsiElement context) {
|
||||
return context.isValid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
|
||||
PsiElement element = descriptor.getPsiElement();
|
||||
if (PsiTreeUtil.getParentOfType(element, XmlTag.class) == null) return;
|
||||
XmlSuppressionProvider.getProvider(element.getContainingFile()).suppressForTag(element, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getFamilyName() {
|
||||
return getText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) {
|
||||
return PsiTreeUtil.getParentOfType(element, XmlTag.class) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) throws IncorrectOperationException {
|
||||
XmlSuppressionProvider.getProvider(element.getContainingFile()).suppressForTag(element, id);
|
||||
return getName();
|
||||
}
|
||||
}
|
||||
|
||||
public static class SuppressForFile extends SuppressIntentionAction {
|
||||
public static class SuppressForFile implements SuppressQuickFix {
|
||||
private final String myInspectionId;
|
||||
|
||||
public SuppressForFile(@NotNull String inspectionId) {
|
||||
myInspectionId = inspectionId;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getText() {
|
||||
@Override
|
||||
public String getName() {
|
||||
return InspectionsBundle.message("xml.suppressable.for.file.title");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
|
||||
PsiElement element = descriptor.getPsiElement();
|
||||
if (element == null || !element.isValid() || !(element.getContainingFile() instanceof XmlFile)) return;
|
||||
XmlSuppressionProvider.getProvider(element.getContainingFile()).suppressForFile(element, myInspectionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(@NotNull Project project, @NotNull PsiElement context) {
|
||||
return context.isValid();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getFamilyName() {
|
||||
return getText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) throws IncorrectOperationException {
|
||||
XmlSuppressionProvider.getProvider(element.getContainingFile()).suppressForFile(element, myInspectionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) {
|
||||
return element.isValid() && element.getContainingFile() instanceof XmlFile;
|
||||
return getName();
|
||||
}
|
||||
}
|
||||
|
||||
public static class SuppressAllForFile extends SuppressForFile {
|
||||
|
||||
public SuppressAllForFile() {
|
||||
super(ALL);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getText() {
|
||||
@Override
|
||||
public String getName() {
|
||||
return InspectionsBundle.message("xml.suppressable.all.for.file.title");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,11 +16,8 @@
|
||||
|
||||
package org.intellij.plugins.relaxNG.inspections;
|
||||
|
||||
import com.intellij.codeInspection.ProblemsHolder;
|
||||
import com.intellij.codeInspection.SuppressIntentionAction;
|
||||
import com.intellij.codeInspection.XmlSuppressableInspectionTool;
|
||||
import com.intellij.codeInspection.*;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
@@ -31,7 +28,6 @@ import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.intellij.plugins.relaxNG.compact.psi.*;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
@@ -45,6 +41,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
* Date: 25.11.2007
|
||||
*/
|
||||
public abstract class BaseInspection extends XmlSuppressableInspectionTool {
|
||||
@Override
|
||||
@Nls
|
||||
@NotNull
|
||||
public final String getGroupDisplayName() {
|
||||
@@ -88,65 +85,69 @@ public abstract class BaseInspection extends XmlSuppressableInspectionTool {
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
@Nullable
|
||||
public SuppressIntentionAction[] getSuppressActions(PsiElement element) {
|
||||
public SuppressQuickFix[] getBatchSuppressActions(@Nullable PsiElement element) {
|
||||
if (element.getContainingFile() instanceof RncFile) {
|
||||
return ArrayUtil.mergeArrays(new SuppressIntentionAction[]{
|
||||
return ArrayUtil.mergeArrays(new SuppressQuickFix[] {
|
||||
new SuppressAction("Define") {
|
||||
@Override
|
||||
protected PsiElement getTarget(PsiElement element) {
|
||||
return PsiTreeUtil.getParentOfType(element, RncDefine.class, false);
|
||||
}
|
||||
},
|
||||
new SuppressAction("Grammar") {
|
||||
@Override
|
||||
protected PsiElement getTarget(PsiElement element) {
|
||||
final RncDefine define = PsiTreeUtil.getParentOfType(element, RncDefine.class, false);
|
||||
return define != null ? PsiTreeUtil.getParentOfType(define, RncGrammar.class, false) : null;
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "SSBasedInspection" })
|
||||
public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) {
|
||||
return super.isAvailable(project, editor, element) && getTarget(element).getText().startsWith("grammar ");
|
||||
RncGrammar target = define != null ? PsiTreeUtil.getParentOfType(define, RncGrammar.class, false) : null;
|
||||
return target != null && target.getText().startsWith("grammar ") ? target : null;
|
||||
}
|
||||
}
|
||||
}, getXmlOnlySuppressions(element));
|
||||
} else {
|
||||
return super.getSuppressActions(element);
|
||||
}
|
||||
else {
|
||||
return super.getBatchSuppressActions(element);
|
||||
}
|
||||
}
|
||||
|
||||
private SuppressIntentionAction[] getXmlOnlySuppressions(PsiElement element) {
|
||||
return ContainerUtil.map(super.getSuppressActions(element), new Function<SuppressIntentionAction, SuppressIntentionAction>() {
|
||||
public SuppressIntentionAction fun(final SuppressIntentionAction action) {
|
||||
return new SuppressIntentionAction() {
|
||||
public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException {
|
||||
action.invoke(project, editor, element);
|
||||
}
|
||||
|
||||
public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) {
|
||||
return element.getContainingFile().getFileType() == StdFileTypes.XML && action.isAvailable(project, editor, element);
|
||||
}
|
||||
|
||||
private SuppressQuickFix[] getXmlOnlySuppressions(PsiElement element) {
|
||||
return ContainerUtil.map(super.getBatchSuppressActions(element), new Function<SuppressQuickFix, SuppressQuickFix>() {
|
||||
@Override
|
||||
public SuppressQuickFix fun(final SuppressQuickFix action) {
|
||||
return new SuppressQuickFix() {
|
||||
@NotNull
|
||||
public String getText() {
|
||||
return action.getText();
|
||||
@Override
|
||||
public String getName() {
|
||||
return action.getName();
|
||||
}
|
||||
|
||||
public boolean startInWriteAction() {
|
||||
return action.startInWriteAction();
|
||||
@Override
|
||||
public boolean isAvailable(@NotNull Project project, @NotNull PsiElement context) {
|
||||
return context.isValid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
|
||||
PsiElement element = descriptor.getPsiElement();
|
||||
PsiFile file = element == null ? null : element.getContainingFile();
|
||||
if (file == null || file.getFileType() != StdFileTypes.XML) return;
|
||||
action.applyFix(project, descriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getFamilyName() {
|
||||
return action.getFamilyName();
|
||||
}
|
||||
};
|
||||
}
|
||||
}, new SuppressIntentionAction[0]);
|
||||
}, SuppressQuickFix.EMPTY_ARRAY);
|
||||
}
|
||||
|
||||
private void suppress(PsiFile file, @NotNull PsiElement location) {
|
||||
suppress(file, location, "#suppress " + getID(), new Function<String, String>() {
|
||||
@Override
|
||||
public String fun(final String text) {
|
||||
return text + ", " + getID();
|
||||
}
|
||||
@@ -160,7 +161,7 @@ public abstract class BaseInspection extends XmlSuppressableInspectionTool {
|
||||
if (vfile == null || ReadonlyStatusHandler.getInstance(project).ensureFilesWritable(vfile).hasReadonlyFiles()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
final Document doc = PsiDocumentManager.getInstance(project).getDocument(file);
|
||||
assert doc != null;
|
||||
|
||||
@@ -188,7 +189,7 @@ public abstract class BaseInspection extends XmlSuppressableInspectionTool {
|
||||
@NotNull
|
||||
public abstract RncElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly);
|
||||
|
||||
private abstract class SuppressAction extends SuppressIntentionAction {
|
||||
private abstract class SuppressAction implements SuppressQuickFix {
|
||||
private final String myLocation;
|
||||
|
||||
public SuppressAction(String location) {
|
||||
@@ -196,21 +197,28 @@ public abstract class BaseInspection extends XmlSuppressableInspectionTool {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getText() {
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Suppress for " + myLocation;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getFamilyName() {
|
||||
return getDisplayName();
|
||||
}
|
||||
|
||||
public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException {
|
||||
suppress(element.getContainingFile(), getTarget(element));
|
||||
@Override
|
||||
public boolean isAvailable(@NotNull Project project, @NotNull PsiElement context) {
|
||||
return context.isValid();
|
||||
}
|
||||
|
||||
public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) {
|
||||
return getTarget(element) != null;
|
||||
@Override
|
||||
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
|
||||
PsiElement element = descriptor.getPsiElement();
|
||||
PsiElement target = getTarget(element);
|
||||
if (target == null) return;
|
||||
suppress(element.getContainingFile(), target);
|
||||
}
|
||||
|
||||
protected abstract PsiElement getTarget(PsiElement element);
|
||||
|
||||
Reference in New Issue
Block a user