src/org/intellij/grammar/intention/BnfConvertOptExpressionIntention.java (91 lines of code) (raw):
/*
* Copyright 2011-2024 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package org.intellij.grammar.intention;
import com.intellij.codeInsight.intention.impl.BaseIntentionAction;
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.util.IncorrectOperationException;
import org.intellij.grammar.GrammarKitBundle;
import org.intellij.grammar.psi.*;
import org.intellij.grammar.psi.impl.BnfElementFactory;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import static com.intellij.psi.util.PsiTreeUtil.getParentOfType;
final class BnfConvertOptExpressionIntention extends BaseIntentionAction {
@Override
public @Nls(capitalization = Nls.Capitalization.Sentence) @NotNull String getFamilyName() {
return GrammarKitBundle.message("intention.convert.opt.expression.family");
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
if (editor == null || file == null) return false;
int offset = editor.getCaretModel().getOffset();
PsiElement element = file.getViewProvider().findElementAt(offset);
if (getQuantifiedOptExpression(element) != null) {
setText(GrammarKitBundle.message("intention.convert.opt.expression.text1"));
return true;
}
else if (getParenOptExpression(element) != null) {
setText(GrammarKitBundle.message("intention.convert.opt.expression.text2"));
return true;
}
else {
return false;
}
}
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
int offset = editor.getCaretModel().getOffset();
PsiElement element = file.getViewProvider().findElementAt(offset);
BnfQuantified quantified = getQuantifiedOptExpression(element);
if (quantified != null) {
handleQuantifier(project, quantified);
return;
}
BnfParenOptExpression parenOpt = getParenOptExpression(element);
if (parenOpt != null) {
handleParenOpt(project, parenOpt);
}
}
private static @Nullable BnfQuantified getQuantifiedOptExpression(PsiElement element) {
BnfQuantified quantified = getParentOfType(element, BnfQuantified.class);
return quantified != null && quantified.getQuantifier().getNode().getFirstChildNode().getElementType() == BnfTypes.BNF_OP_OPT
? quantified
: null;
}
@Contract("null -> null")
private static BnfParenOptExpression getParenOptExpression(PsiElement element) {
return getParentOfType(element, BnfParenOptExpression.class);
}
private static void handleQuantifier(@NotNull Project project, @NotNull BnfQuantified expr) {
BnfExpression operand = skipParenthesesDown(expr.getExpression());
String newText = "[" + operand.getText() + "]";
expr.replace(BnfElementFactory.createExpressionFromText(project, newText));
}
private static void handleParenOpt(@NotNull Project project, @NotNull BnfParenOptExpression expr) {
BnfExpression operand = skipBracketsDown(expr.getExpression());
String newText = isSimple(operand) ? operand.getText() + "?" : "(" + operand.getText() + ")?";
expr.replace(BnfElementFactory.createExpressionFromText(project, newText));
}
private static BnfExpression skipParenthesesDown(BnfExpression expr) {
while (expr instanceof BnfParenthesized) {
expr = ((BnfParenthesized)expr).getExpression();
}
return expr;
}
private static BnfExpression skipBracketsDown(BnfExpression expr) {
while (expr instanceof BnfParenOptExpression) {
expr = ((BnfParenOptExpression)expr).getExpression();
}
return expr;
}
@Contract(pure = true)
private static boolean isSimple(@NotNull BnfExpression expression) {
return expression instanceof BnfReferenceOrToken ||
expression instanceof BnfLiteralExpression ||
expression instanceof BnfParenthesized ||
expression instanceof BnfExternalExpression;
}
}