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.JSLiteralExpression;
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.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.codeStyle.CodeStyleManager;
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 SquareBracketToDotMemberAccess extends PsiElementBaseIntentionAction implements IntentionAction {
public SquareBracketToDotMemberAccess() {
setText("Change square-bracket to dot 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;
JSIndexedPropertyAccessExpression indexedPropertyAccessExpression = PsiTreeUtil.getParentOfType(element, JSIndexedPropertyAccessExpression.class, true);
if (indexedPropertyAccessExpression != null) {
JSExpression indexExpression = indexedPropertyAccessExpression.getIndexExpression();
if ((indexExpression instanceof JSLiteralExpression) && ((JSLiteralExpression)indexExpression).isQuotedLiteral()) {
return true;
}
}
return false;
}
@Override
public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException {
PsiElement reformatElement = null;
JSIndexedPropertyAccessExpression indexedPropertyAccessExpression = PsiTreeUtil.getParentOfType(element, JSIndexedPropertyAccessExpression.class, true);
if (indexedPropertyAccessExpression != null) {
JSExpression qualifier = indexedPropertyAccessExpression.getQualifier();
JSLiteralExpression indexExpression = (JSLiteralExpression)indexedPropertyAccessExpression.getIndexExpression();
String propertyName = StringUtil.unquoteString(indexExpression.getText());
JSReferenceExpression replacementReferenceExpression = (JSReferenceExpression)JSChangeUtil.createExpressionFromText(project, "$$$." + propertyName, JavaScriptSupportLoader.ECMA_SCRIPT_L4).getPsi();
assert replacementReferenceExpression.getQualifier() != null;
replacementReferenceExpression.getQualifier().replace(qualifier);
reformatElement = indexedPropertyAccessExpression.replace(replacementReferenceExpression);
}
if (reformatElement != null) {
CodeStyleManager.getInstance(project).reformat(reformatElement, true);
}
}
}