Search in sources :

Example 1 with OccurrencesChooser

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];
}
Also used : InjectedLanguageManager(com.intellij.lang.injection.InjectedLanguageManager) com.intellij.refactoring(com.intellij.refactoring) RefactoringUIUtil(com.intellij.refactoring.util.RefactoringUIUtil) EditorColorsManager(com.intellij.openapi.editor.colors.EditorColorsManager) NullableNotNullManager(com.intellij.codeInsight.NullableNotNullManager) HighlightManager(com.intellij.codeInsight.highlighting.HighlightManager) FeatureUsageTracker(com.intellij.featureStatistics.FeatureUsageTracker) RefactoringEventData(com.intellij.refactoring.listeners.RefactoringEventData) Logger(com.intellij.openapi.diagnostic.Logger) MultiMap(com.intellij.util.containers.MultiMap) ReferencesSearch(com.intellij.psi.search.searches.ReferencesSearch) PropertiesComponent(com.intellij.ide.util.PropertiesComponent) JspCodeBlock(com.intellij.psi.impl.source.jsp.jspJava.JspCodeBlock) FieldConflictsResolver(com.intellij.refactoring.util.FieldConflictsResolver) IncorrectOperationException(com.intellij.util.IncorrectOperationException) ChainCallExtractor(com.intellij.refactoring.chainCall.ChainCallExtractor) WindowManager(com.intellij.openapi.wm.WindowManager) LookupManager(com.intellij.codeInsight.lookup.LookupManager) TextRange(com.intellij.openapi.util.TextRange) CodeStyleSettingsManager(com.intellij.psi.codeStyle.CodeStyleSettingsManager) RefactoringSupportProvider(com.intellij.lang.refactoring.RefactoringSupportProvider) ReplaceExpressionUtil(com.intellij.psi.impl.source.tree.java.ReplaceExpressionUtil) AbstractInplaceIntroducer(com.intellij.refactoring.introduce.inplace.AbstractInplaceIntroducer) Nullable(org.jetbrains.annotations.Nullable) ExpressionOccurrenceManager(com.intellij.refactoring.util.occurrences.ExpressionOccurrenceManager) TextAttributes(com.intellij.openapi.editor.markup.TextAttributes) Pass(com.intellij.openapi.util.Pass) OccurrencesChooser(com.intellij.refactoring.introduce.inplace.OccurrencesChooser) VariableKind(com.intellij.psi.codeStyle.VariableKind) ScopeHighlighter(com.intellij.codeInsight.unwrap.ScopeHighlighter) JspHolderMethod(com.intellij.psi.impl.source.jsp.jspJava.JspHolderMethod) Processor(com.intellij.util.Processor) ApplicationManager(com.intellij.openapi.application.ApplicationManager) Registry(com.intellij.openapi.util.registry.Registry) com.intellij.psi(com.intellij.psi) NotNull(org.jetbrains.annotations.NotNull) SuggestedNameInfo(com.intellij.psi.codeStyle.SuggestedNameInfo) java.util(java.util) TypeSelectorManagerImpl(com.intellij.refactoring.ui.TypeSelectorManagerImpl) DataContext(com.intellij.openapi.actionSystem.DataContext) com.intellij.openapi.editor(com.intellij.openapi.editor) NonNls(org.jetbrains.annotations.NonNls) Computable(com.intellij.openapi.util.Computable) ElementToWorkOn(com.intellij.refactoring.introduceField.ElementToWorkOn) ArrayUtilRt(com.intellij.util.ArrayUtilRt) RefactoringEventListener(com.intellij.refactoring.listeners.RefactoringEventListener) ContainerUtil(com.intellij.util.containers.ContainerUtil) CodeInsightUtil(com.intellij.codeInsight.CodeInsightUtil) JavaCodeStyleManager(com.intellij.psi.codeStyle.JavaCodeStyleManager) MessageFormat(java.text.MessageFormat) LanguageRefactoringSupport(com.intellij.lang.LanguageRefactoringSupport) Project(com.intellij.openapi.project.Project) InjectedLanguageUtil(com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil) NotInSuperCallOccurrenceFilter(com.intellij.refactoring.util.occurrences.NotInSuperCallOccurrenceFilter) ProductivityFeatureNames(com.intellij.featureStatistics.ProductivityFeatureNames) StringUtil(com.intellij.openapi.util.text.StringUtil) com.intellij.psi.util(com.intellij.psi.util) Key(com.intellij.openapi.util.Key) FileDocumentManager(com.intellij.openapi.fileEditor.FileDocumentManager) CommandProcessor(com.intellij.openapi.command.CommandProcessor) CommonRefactoringUtil(com.intellij.refactoring.util.CommonRefactoringUtil) EditorColors(com.intellij.openapi.editor.colors.EditorColors) JavaCompletionUtil(com.intellij.codeInsight.completion.JavaCompletionUtil) PsiDiamondTypeUtil(com.intellij.psi.impl.PsiDiamondTypeUtil) RefactoringUtil(com.intellij.refactoring.util.RefactoringUtil) MultiMap(com.intellij.util.containers.MultiMap) RefactoringSupportProvider(com.intellij.lang.refactoring.RefactoringSupportProvider) Pass(com.intellij.openapi.util.Pass) TypeSelectorManagerImpl(com.intellij.refactoring.ui.TypeSelectorManagerImpl) RefactoringEventData(com.intellij.refactoring.listeners.RefactoringEventData) ExpressionOccurrenceManager(com.intellij.refactoring.util.occurrences.ExpressionOccurrenceManager)

Aggregations

CodeInsightUtil (com.intellij.codeInsight.CodeInsightUtil)1 NullableNotNullManager (com.intellij.codeInsight.NullableNotNullManager)1 JavaCompletionUtil (com.intellij.codeInsight.completion.JavaCompletionUtil)1 HighlightManager (com.intellij.codeInsight.highlighting.HighlightManager)1 LookupManager (com.intellij.codeInsight.lookup.LookupManager)1 ScopeHighlighter (com.intellij.codeInsight.unwrap.ScopeHighlighter)1 FeatureUsageTracker (com.intellij.featureStatistics.FeatureUsageTracker)1 ProductivityFeatureNames (com.intellij.featureStatistics.ProductivityFeatureNames)1 PropertiesComponent (com.intellij.ide.util.PropertiesComponent)1 LanguageRefactoringSupport (com.intellij.lang.LanguageRefactoringSupport)1 InjectedLanguageManager (com.intellij.lang.injection.InjectedLanguageManager)1 RefactoringSupportProvider (com.intellij.lang.refactoring.RefactoringSupportProvider)1 DataContext (com.intellij.openapi.actionSystem.DataContext)1 ApplicationManager (com.intellij.openapi.application.ApplicationManager)1 CommandProcessor (com.intellij.openapi.command.CommandProcessor)1 Logger (com.intellij.openapi.diagnostic.Logger)1 com.intellij.openapi.editor (com.intellij.openapi.editor)1 EditorColors (com.intellij.openapi.editor.colors.EditorColors)1 EditorColorsManager (com.intellij.openapi.editor.colors.EditorColorsManager)1 TextAttributes (com.intellij.openapi.editor.markup.TextAttributes)1