package de.plushnikov.intellij.plugin.quickfix;
import com.intellij.codeInsight.CodeInsightUtil;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.command.undo.UndoUtil;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiAnnotation;
import com.intellij.psi.PsiElementFactory;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiNameValuePair;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author Plushnikov Michail
*/
public class ChangeAnnotationParameterQuickFix implements IntentionAction, LocalQuickFix {
private final PsiAnnotation myAnnotation;
private final String myName;
private final String myNewValue;
public ChangeAnnotationParameterQuickFix(@NotNull PsiAnnotation psiAnnotation, @NotNull String name) {
this(psiAnnotation, name, null);
}
public ChangeAnnotationParameterQuickFix(@NotNull PsiAnnotation psiAnnotation, @NotNull String name, @Nullable String newValue) {
myAnnotation = psiAnnotation;
myName = name;
myNewValue = newValue;
}
@NotNull
public String getText() {
if (null == myNewValue) {
return String.format("Remove annotation parameter '%s'", myName);
} else {
return String.format("Set annotation parameter '%s = %s'", myName, myNewValue);
}
}
@NotNull
public String getName() {
return getText();
}
@NotNull
public String getFamilyName() {
return getText();
}
public void applyFix(@NotNull final Project project, @NotNull ProblemDescriptor descriptor) {
applyFixInner(project);
}
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
return true;
}
public void invoke(@NotNull Project project, Editor editor, PsiFile file) {
applyFixInner(project);
}
private void applyFixInner(final Project project) {
final PsiFile file = myAnnotation.getContainingFile();
final Editor editor = CodeInsightUtil.positionCursor(project, file, myAnnotation);
if (editor != null) {
new WriteCommandAction(project, file) {
protected void run(@NotNull Result result) throws Throwable {
final PsiNameValuePair valuePair = selectAnnotationAttribute();
if (null != valuePair) {
// delete this parameter
valuePair.delete();
}
if (null != myNewValue) {
//add new parameter
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(myAnnotation.getProject());
PsiAnnotation newAnnotation = elementFactory.createAnnotationFromText("@" + myAnnotation.getQualifiedName() + "(" + myName + "=" + myNewValue + ")", myAnnotation.getContext());
final PsiNameValuePair[] attributes = newAnnotation.getParameterList().getAttributes();
myAnnotation.setDeclaredAttributeValue(attributes[0].getName(), attributes[0].getValue());
}
UndoUtil.markPsiFileForUndo(file);
}
@Override
protected boolean isGlobalUndoAction() {
return true;
}
}.execute();
}
}
private PsiNameValuePair selectAnnotationAttribute() {
PsiNameValuePair result = null;
PsiNameValuePair[] attributes = myAnnotation.getParameterList().getAttributes();
for (PsiNameValuePair attribute : attributes) {
@NonNls final String attributeName = attribute.getName();
if (equals(myName, attributeName) || attributeName == null && myName.equals(PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME)) {
result = attribute;
break;
}
}
return result;
}
private boolean equals(CharSequence cs1, CharSequence cs2) {
return cs1 == null ? cs2 == null : cs1.equals(cs2);
}
public boolean startInWriteAction() {
return false;
}
}