| /* |
| * 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; |
| |
| import com.intellij.codeInsight.FileModificationService; |
| import com.intellij.codeInsight.daemon.QuickFixBundle; |
| import com.intellij.codeInspection.*; |
| import com.intellij.openapi.diagnostic.Logger; |
| import com.intellij.openapi.project.Project; |
| import com.intellij.openapi.util.Comparing; |
| 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.ArrayUtil; |
| import com.intellij.util.IncorrectOperationException; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Set; |
| |
| public class RemoveSuppressWarningAction implements LocalQuickFix { |
| private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.RemoveSuppressWarningAction"); |
| |
| private final String myID; |
| private final String myProblemLine; |
| |
| public RemoveSuppressWarningAction(final String ID, final String problemLine) { |
| myID = ID; |
| myProblemLine = problemLine; |
| } |
| |
| public RemoveSuppressWarningAction(String id) { |
| final int idx = id.indexOf(";"); |
| if (idx > -1) { |
| myID = id.substring(0, idx); |
| myProblemLine = id.substring(idx); |
| } |
| else { |
| myID = id; |
| myProblemLine = null; |
| } |
| } |
| |
| @Override |
| @NotNull |
| public String getFamilyName() { |
| return QuickFixBundle.message("remove.suppression.action.family"); |
| } |
| |
| @Override |
| public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { |
| PsiElement element = descriptor.getPsiElement(); |
| try { |
| if (element instanceof PsiIdentifier) { |
| if (!FileModificationService.getInstance().prepareFileForWrite(element.getContainingFile())) return; |
| final PsiIdentifier identifier = (PsiIdentifier)element; |
| final PsiDocCommentOwner commentOwner = PsiTreeUtil.getParentOfType(identifier, PsiDocCommentOwner.class); |
| if (commentOwner != null) { |
| final PsiElement psiElement = JavaSuppressionUtil.getElementMemberSuppressedIn(commentOwner, myID); |
| if (psiElement instanceof PsiAnnotation) { |
| removeFromAnnotation((PsiAnnotation)psiElement); |
| } else if (psiElement instanceof PsiDocComment) { |
| removeFromJavaDoc((PsiDocComment)psiElement); |
| } else { //try to remove from all comments |
| final Set<PsiComment> comments = new HashSet<PsiComment>(); |
| commentOwner.accept(new PsiRecursiveElementWalkingVisitor() { |
| @Override public void visitComment(final PsiComment comment) { |
| super.visitComment(comment); |
| if (comment.getText().contains(myID)) { |
| comments.add(comment); |
| } |
| } |
| }); |
| for (PsiComment comment : comments) { |
| try { |
| removeFromComment(comment, comments.size() > 1); |
| } |
| catch (IncorrectOperationException e) { |
| LOG.error(e); |
| } |
| } |
| } |
| } |
| } |
| } |
| catch (IncorrectOperationException e) { |
| LOG.error(e); |
| } |
| } |
| |
| @Override |
| @NotNull |
| public String getName() { |
| return QuickFixBundle.message("remove.suppression.action.name", myID); |
| } |
| |
| private void removeFromComment(final PsiComment comment, final boolean checkLine) throws IncorrectOperationException { |
| if (checkLine) { |
| final PsiStatement statement = PsiTreeUtil.getNextSiblingOfType(comment, PsiStatement.class); |
| if (statement != null && !Comparing.strEqual(statement.getText(), myProblemLine)) return; |
| } |
| String newText = removeFromElementText(comment); |
| if (newText != null) { |
| if (newText.isEmpty()) { |
| comment.delete(); |
| } |
| else { |
| PsiComment newComment = JavaPsiFacade.getInstance(comment.getProject()).getElementFactory() |
| .createCommentFromText("// " + SuppressionUtilCore.SUPPRESS_INSPECTIONS_TAG_NAME +" "+newText, comment); |
| comment.replace(newComment); |
| } |
| } |
| } |
| |
| private void removeFromJavaDoc(PsiDocComment docComment) throws IncorrectOperationException { |
| PsiDocTag tag = docComment.findTagByName(SuppressionUtilCore.SUPPRESS_INSPECTIONS_TAG_NAME); |
| if (tag == null) return; |
| String newText = removeFromElementText(tag.getDataElements()); |
| if (newText != null && newText.isEmpty()) { |
| tag.delete(); |
| } |
| else if (newText != null) { |
| newText = "@" + SuppressionUtilCore.SUPPRESS_INSPECTIONS_TAG_NAME + " " + newText; |
| PsiDocTag newTag = JavaPsiFacade.getInstance(tag.getProject()).getElementFactory().createDocTagFromText(newText); |
| tag.replace(newTag); |
| } |
| } |
| |
| @Nullable |
| private String removeFromElementText(final PsiElement... elements) { |
| String text = ""; |
| for (PsiElement element : elements) { |
| text += StringUtil.trimStart(element.getText(), "//").trim(); |
| } |
| text = StringUtil.trimStart(text, "@").trim(); |
| text = StringUtil.trimStart(text, SuppressionUtilCore.SUPPRESS_INSPECTIONS_TAG_NAME).trim(); |
| List<String> ids = StringUtil.split(text, ","); |
| int i = ArrayUtil.find(ids.toArray(), myID); |
| if (i==-1) return null; |
| ids.remove(i); |
| return StringUtil.join(ids, ","); |
| } |
| |
| private void removeFromAnnotation(final PsiAnnotation annotation) throws IncorrectOperationException { |
| PsiNameValuePair[] attributes = annotation.getParameterList().getAttributes(); |
| for (PsiNameValuePair attribute : attributes) { |
| PsiAnnotationMemberValue value = attribute.getValue(); |
| if (value instanceof PsiArrayInitializerMemberValue) { |
| PsiAnnotationMemberValue[] initializers = ((PsiArrayInitializerMemberValue)value).getInitializers(); |
| for (PsiAnnotationMemberValue initializer : initializers) { |
| if (removeFromValue(annotation, initializer, initializers.length==1)) return; |
| } |
| } |
| if (removeFromValue(annotation, value, attributes.length==1)) return; |
| } |
| } |
| |
| private boolean removeFromValue(final PsiAnnotationMemberValue parent, final PsiAnnotationMemberValue value, final boolean removeParent) throws IncorrectOperationException { |
| String text = value.getText(); |
| text = StringUtil.trimStart(text, "\""); |
| text = StringUtil.trimEnd(text, "\""); |
| if (myID.equals(text)) { |
| if (removeParent) { |
| parent.delete(); |
| } |
| else { |
| value.delete(); |
| } |
| return true; |
| } |
| return false; |
| } |
| } |