package net.jangaroo.ide.idea.exml.intentions;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction;
import com.intellij.lang.javascript.JavaScriptSupportLoader;
import com.intellij.lang.javascript.psi.JSExpression;
import com.intellij.lang.javascript.psi.JSIndexedPropertyAccessExpression;
import com.intellij.lang.javascript.psi.JSReferenceExpression;
import com.intellij.lang.javascript.psi.impl.JSChangeUtil;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.impl.source.tree.LeafPsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
/**
* This intention replaces an invocation of an EXML config class constructor using an object literal
* by a no-arg constructor invocation, followed by assigning each property separately.
* The advantage is that in contrast to the object literal, the usage of properties is type-safe
* and can be refactored.
*/
public class DotToSquareBracketMemberAccess extends PsiElementBaseIntentionAction implements IntentionAction {
public DotToSquareBracketMemberAccess() {
setText("Change dot to square-bracket member access");
}
@Nls
@NotNull
@Override
public String getFamilyName() {
return getText();
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) {
if (!element.isWritable()) return false;
JSReferenceExpression referenceExpression = PsiTreeUtil.getParentOfType(element, JSReferenceExpression.class);
if (referenceExpression != null) {
JSExpression qualifier = referenceExpression.getQualifier();
PsiElement referenceNameElement = referenceExpression.getReferenceNameElement();
if (qualifier != null && referenceNameElement instanceof LeafPsiElement) {
return true;
}
}
return false;
}
@Override
public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException {
PsiElement reformatElement = null;
JSReferenceExpression referenceExpression = PsiTreeUtil.getParentOfType(element, JSReferenceExpression.class);
if (referenceExpression != null) {
JSExpression qualifier = referenceExpression.getQualifier();
PsiElement propertyName = referenceExpression.getReferenceNameElement();
if (propertyName != null) {
JSIndexedPropertyAccessExpression replacementIndexedPropertyAccessExpression = (JSIndexedPropertyAccessExpression)JSChangeUtil.createExpressionFromText(project, "$$$['" + propertyName.getText() + "']", JavaScriptSupportLoader.ECMA_SCRIPT_L4).getPsi();
assert replacementIndexedPropertyAccessExpression.getQualifier() != null;
replacementIndexedPropertyAccessExpression.getQualifier().replace(qualifier);
reformatElement = referenceExpression.replace(replacementIndexedPropertyAccessExpression);
}
}
if (reformatElement != null) {
CodeStyleManager.getInstance(project).reformat(reformatElement, true);
}
}
}