final PsiFile file,
final BnfRule currentRule,
final List<BnfExpression> selectedExpression) {
BnfExpression firstExpression = ObjectUtils.assertNotNull(ContainerUtil.getFirstItem(selectedExpression));
BnfExpression lastExpression = ObjectUtils.assertNotNull(ContainerUtil.getLastItem(selectedExpression));
final TextRange fixedRange = new TextRange(firstExpression.getTextRange().getStartOffset(), lastExpression.getTextRange().getEndOffset());
final BnfRule ruleFromText = BnfElementFactory.createRuleFromText(file.getProject(), "a ::= " + fixedRange.substring(file.getText()));
BnfExpressionOptimizer.optimize(ruleFromText.getExpression());
final Map<OccurrencesChooser.ReplaceChoice, List<BnfExpression[]>> occurrencesMap = ContainerUtil.newLinkedHashMap();
occurrencesMap.put(OccurrencesChooser.ReplaceChoice.NO, Collections.singletonList(selectedExpression.toArray(new BnfExpression[selectedExpression.size()])));
occurrencesMap.put(OccurrencesChooser.ReplaceChoice.ALL, new ArrayList<BnfExpression[]>());
file.acceptChildren(new PsiRecursiveElementWalkingVisitor() {
@Override
public void visitElement(PsiElement element) {
if (element instanceof BnfExpression) {
findOccurrences((BnfExpression)element, selectedExpression, occurrencesMap);
}
else if (element instanceof BnfAttrs) {
return;
}
super.visitElement(element);
}
});
if (occurrencesMap.get(OccurrencesChooser.ReplaceChoice.ALL).size() <= 1 && !ApplicationManager.getApplication().isUnitTestMode()) {
occurrencesMap.remove(OccurrencesChooser.ReplaceChoice.ALL);
}
final Pass<OccurrencesChooser.ReplaceChoice> callback = new Pass<OccurrencesChooser.ReplaceChoice>() {
@Override
public void pass(final OccurrencesChooser.ReplaceChoice choice) {
new WriteCommandAction.Simple(project, REFACTORING_NAME, file) {
@Override
public void run() {
final PsiFile containingFile = currentRule.getContainingFile();
String newRuleName = choseRuleName(containingFile);
String newRuleText = "private " + newRuleName + " ::= " + ruleFromText.getExpression().getText();
BnfRule addedRule = addNextRule(project, currentRule, newRuleText);
if (choice == OccurrencesChooser.ReplaceChoice.ALL) {
List<BnfExpression[]> exprToReplace = occurrencesMap.get(OccurrencesChooser.ReplaceChoice.ALL);
replaceUsages(project, exprToReplace, addedRule.getId());
} else {
List<BnfExpression[]> exprToReplace = occurrencesMap.get(OccurrencesChooser.ReplaceChoice.NO);
replaceUsages(project, exprToReplace, addedRule.getId());
}
final BnfIntroduceRulePopup popup = new BnfIntroduceRulePopup(project, editor, addedRule, addedRule.getExpression());
editor.getCaretModel().moveToOffset(addedRule.getTextOffset());
PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.getDocument());
popup.performInplaceRefactoring(null);
}
}.execute();
}
};
if (ApplicationManager.getApplication().isUnitTestMode()) {
callback.pass(OccurrencesChooser.ReplaceChoice.ALL);
}
else {
new OccurrencesChooser<BnfExpression[]>(editor) {
@Override
protected TextRange getOccurrenceRange(BnfExpression[] occurrence) {
return new TextRange(occurrence[0].getTextRange().getStartOffset(),
occurrence[occurrence.length - 1].getTextRange().getEndOffset());
}
}.showChooser(callback, occurrencesMap);
}
}