use of com.intellij.refactoring.introduce.inplace.OccurrencesChooser in project intellij-community by JetBrains.
the class IntroduceVariableBase method invokeImpl.
protected boolean invokeImpl(final Project project, final PsiExpression expr, final Editor editor) {
if (expr != null) {
final String errorMessage = getErrorMessage(expr);
if (errorMessage != null) {
showErrorMessage(project, editor, RefactoringBundle.getCannotRefactorMessage(errorMessage));
return false;
}
}
if (expr != null && expr.getParent() instanceof PsiExpressionStatement) {
FeatureUsageTracker.getInstance().triggerFeatureUsed("refactoring.introduceVariable.incompleteStatement");
}
if (LOG.isDebugEnabled()) {
LOG.debug("expression:" + expr);
}
if (expr == null || !expr.isPhysical()) {
if (ReassignVariableUtil.reassign(editor))
return false;
if (expr == null) {
String message = RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message("selected.block.should.represent.an.expression"));
showErrorMessage(project, editor, message);
return false;
}
}
final PsiType originalType = RefactoringUtil.getTypeByExpressionWithExpectedType(expr);
if (originalType == null || LambdaUtil.notInferredType(originalType)) {
String message = RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message("unknown.expression.type"));
showErrorMessage(project, editor, message);
return false;
}
if (PsiType.VOID.equals(originalType)) {
String message = RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message("selected.expression.has.void.type"));
showErrorMessage(project, editor, message);
return false;
}
final PsiElement physicalElement = expr.getUserData(ElementToWorkOn.PARENT);
final PsiElement anchorStatement = RefactoringUtil.getParentStatement(physicalElement != null ? physicalElement : expr, false);
if (anchorStatement == null) {
return parentStatementNotFound(project, editor);
}
if (checkAnchorBeforeThisOrSuper(project, editor, anchorStatement, REFACTORING_NAME, HelpID.INTRODUCE_VARIABLE))
return false;
final PsiElement tempContainer = anchorStatement.getParent();
if (!(tempContainer instanceof PsiCodeBlock) && !RefactoringUtil.isLoopOrIf(tempContainer) && !(tempContainer instanceof PsiLambdaExpression) && (tempContainer.getParent() instanceof PsiLambdaExpression)) {
String message = RefactoringBundle.message("refactoring.is.not.supported.in.the.current.context", REFACTORING_NAME);
showErrorMessage(project, editor, message);
return false;
}
if (!NotInSuperCallOccurrenceFilter.INSTANCE.isOK(expr)) {
String message = RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message("cannot.introduce.variable.in.super.constructor.call"));
showErrorMessage(project, editor, message);
return false;
}
final PsiFile file = anchorStatement.getContainingFile();
LOG.assertTrue(file != null, "expr.getContainingFile() == null");
final PsiElement nameSuggestionContext = editor == null ? null : file.findElementAt(editor.getCaretModel().getOffset());
final RefactoringSupportProvider supportProvider = LanguageRefactoringSupport.INSTANCE.forLanguage(expr.getLanguage());
final boolean isInplaceAvailableOnDataContext = supportProvider != null && editor.getSettings().isVariableInplaceRenameEnabled() && supportProvider.isInplaceIntroduceAvailable(expr, nameSuggestionContext) && (!ApplicationManager.getApplication().isUnitTestMode() || isInplaceAvailableInTestMode()) && !isInJspHolderMethod(expr);
if (isInplaceAvailableOnDataContext) {
final MultiMap<PsiElement, String> conflicts = new MultiMap<>();
checkInLoopCondition(expr, conflicts);
if (!conflicts.isEmpty()) {
showErrorMessage(project, editor, StringUtil.join(conflicts.values(), "<br>"));
return false;
}
}
final ExpressionOccurrenceManager occurrenceManager = createOccurrenceManager(expr, tempContainer);
final PsiExpression[] occurrences = occurrenceManager.getOccurrences();
final PsiElement anchorStatementIfAll = occurrenceManager.getAnchorStatementForAll();
OccurrencesInfo occurrencesInfo = new OccurrencesInfo(occurrences);
if (!CommonRefactoringUtil.checkReadOnlyStatus(project, file))
return false;
final LinkedHashMap<JavaReplaceChoice, List<PsiExpression>> occurrencesMap = occurrencesInfo.buildOccurrencesMap(expr);
final boolean inFinalContext = occurrenceManager.isInFinalContext();
final InputValidator validator = new InputValidator(this, project, anchorStatementIfAll, anchorStatement, occurrenceManager);
final TypeSelectorManagerImpl typeSelectorManager = new TypeSelectorManagerImpl(project, originalType, expr, occurrences);
final boolean[] wasSucceed = new boolean[] { true };
final Pass<JavaReplaceChoice> callback = new Pass<JavaReplaceChoice>() {
@Override
public void pass(final JavaReplaceChoice choice) {
boolean hasWriteAccess = occurrencesInfo.myHasWriteAccess;
List<PsiExpression> nonWrite = occurrencesInfo.myNonWrite;
if (choice != null) {
final boolean noWriteChoice = choice == JavaReplaceChoice.NO_WRITE;
final boolean allChoice = choice.isAll();
final boolean replaceAll = allChoice || noWriteChoice;
typeSelectorManager.setAllOccurrences(replaceAll);
final PsiElement chosenAnchor = chooseAnchor(replaceAll, noWriteChoice, nonWrite, anchorStatementIfAll, anchorStatement);
final IntroduceVariableSettings settings = getSettings(project, editor, expr, occurrences, typeSelectorManager, inFinalContext, hasWriteAccess, validator, chosenAnchor, choice);
final boolean cantChangeFinalModifier = (hasWriteAccess || inFinalContext) && allChoice;
PsiExpression[] allOccurrences = Arrays.stream(occurrences).filter(occurrence -> !(expr.equals(occurrence) && expr.getParent() instanceof PsiExpressionStatement)).filter(occurrence -> allChoice || (noWriteChoice && !PsiUtil.isAccessedForWriting(occurrence)) || expr.equals(occurrence)).toArray(PsiExpression[]::new);
if (choice.isChain()) {
myInplaceIntroducer = new ChainCallInplaceIntroducer(project, settings, chosenAnchor, editor, expr, allOccurrences, typeSelectorManager, REFACTORING_NAME);
} else {
myInplaceIntroducer = new JavaVariableInplaceIntroducer(project, settings, chosenAnchor, editor, expr, cantChangeFinalModifier, allOccurrences, typeSelectorManager, REFACTORING_NAME);
}
if (myInplaceIntroducer.startInplaceIntroduceTemplate()) {
return;
}
}
CommandProcessor.getInstance().executeCommand(project, () -> {
if (!anchorStatement.isValid()) {
return;
}
final Editor topLevelEditor;
if (!InjectedLanguageManager.getInstance(project).isInjectedFragment(anchorStatement.getContainingFile())) {
topLevelEditor = InjectedLanguageUtil.getTopLevelEditor(editor);
} else {
topLevelEditor = editor;
}
PsiVariable variable = null;
try {
final IntroduceVariableSettings settings = getSettings(project, topLevelEditor, expr, occurrences, typeSelectorManager, inFinalContext, hasWriteAccess, validator, anchorStatement, choice);
if (!settings.isOK()) {
wasSucceed[0] = false;
return;
}
final RefactoringEventData beforeData = new RefactoringEventData();
beforeData.addElement(expr);
project.getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC).refactoringStarted(REFACTORING_ID, beforeData);
final PsiElement chosenAnchor = chooseAnchor(settings.isReplaceAllOccurrences(), hasWriteAccess, nonWrite, anchorStatementIfAll, anchorStatement);
variable = introduce(project, expr, topLevelEditor, chosenAnchor, occurrences, settings);
} finally {
final RefactoringEventData afterData = new RefactoringEventData();
afterData.addElement(variable);
project.getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC).refactoringDone(REFACTORING_ID, afterData);
}
}, REFACTORING_NAME, null);
}
};
if (!isInplaceAvailableOnDataContext) {
callback.pass(null);
} else {
JavaReplaceChoice choice = getOccurrencesChoice();
if (choice != null) {
callback.pass(choice);
} else {
String title = occurrencesInfo.myChainMethodName != null && occurrences.length == 1 ? "Lambda chain detected" : OccurrencesChooser.DEFAULT_CHOOSER_TITLE;
OccurrencesChooser.<PsiExpression>simpleChooser(editor).showChooser(callback, occurrencesMap, title);
}
}
return wasSucceed[0];
}
Aggregations