Search in sources :

Example 1 with PrepareFailedException

use of com.intellij.refactoring.extractMethod.PrepareFailedException in project intellij-community by JetBrains.

the class IntroduceParameterHandler method introduceStrategy.

@VisibleForTesting
public boolean introduceStrategy(final Project project, final Editor editor, PsiFile file, final PsiElement[] elements) {
    if (elements.length > 0) {
        final AbstractInplaceIntroducer inplaceIntroducer = AbstractInplaceIntroducer.getActiveIntroducer(editor);
        if (inplaceIntroducer instanceof InplaceIntroduceParameterPopup) {
            return false;
        }
        final PsiMethod containingMethod = Util.getContainingMethod(elements[0]);
        if (containingMethod == null) {
            return false;
        }
        final List<PsiMethod> enclosingMethods = getEnclosingMethods(containingMethod);
        if (enclosingMethods.isEmpty()) {
            return false;
        }
        final PsiElement[] elementsCopy;
        if (!elements[0].isPhysical()) {
            elementsCopy = elements;
        } else {
            final PsiFile copy = PsiFileFactory.getInstance(project).createFileFromText(file.getName(), file.getFileType(), file.getText(), file.getModificationStamp(), false);
            final TextRange range = new TextRange(elements[0].getTextRange().getStartOffset(), elements[elements.length - 1].getTextRange().getEndOffset());
            final PsiExpression exprInRange = CodeInsightUtil.findExpressionInRange(copy, range.getStartOffset(), range.getEndOffset());
            elementsCopy = exprInRange != null ? new PsiElement[] { exprInRange } : CodeInsightUtil.findStatementsInRange(copy, range.getStartOffset(), range.getEndOffset());
        }
        final PsiMethod containingMethodCopy = Util.getContainingMethod(elementsCopy[0]);
        LOG.assertTrue(containingMethodCopy != null);
        final List<PsiMethod> enclosingMethodsInCopy = getEnclosingMethods(containingMethodCopy);
        final MyExtractMethodProcessor processor = new MyExtractMethodProcessor(project, editor, elementsCopy, enclosingMethodsInCopy.get(enclosingMethodsInCopy.size() - 1));
        try {
            if (!processor.prepare())
                return false;
            processor.showDialog();
            //provide context for generated method to check exceptions compatibility
            final PsiMethod emptyMethod = JavaPsiFacade.getElementFactory(project).createMethodFromText(processor.generateEmptyMethod("name").getText(), elements[0]);
            final Collection<? extends PsiType> types = FunctionalInterfaceSuggester.suggestFunctionalInterfaces(emptyMethod);
            if (types.isEmpty()) {
                return false;
            }
            if (types.size() == 1 || ApplicationManager.getApplication().isUnitTestMode()) {
                final PsiType next = types.iterator().next();
                functionalInterfaceSelected(next, enclosingMethods, project, editor, processor, elements);
            } else {
                final Map<PsiClass, PsiType> classes = new LinkedHashMap<>();
                for (PsiType type : types) {
                    classes.put(PsiUtil.resolveClassInType(type), type);
                }
                final PsiClass[] psiClasses = classes.keySet().toArray(new PsiClass[classes.size()]);
                final String methodSignature = PsiFormatUtil.formatMethod(emptyMethod, PsiSubstitutor.EMPTY, PsiFormatUtilBase.SHOW_PARAMETERS, PsiFormatUtilBase.SHOW_TYPE);
                final PsiType returnType = emptyMethod.getReturnType();
                LOG.assertTrue(returnType != null);
                final String title = "Choose Applicable Functional Interface: " + methodSignature + " -> " + returnType.getPresentableText();
                NavigationUtil.getPsiElementPopup(psiClasses, new PsiClassListCellRenderer(), title, new PsiElementProcessor<PsiClass>() {

                    @Override
                    public boolean execute(@NotNull PsiClass psiClass) {
                        functionalInterfaceSelected(classes.get(psiClass), enclosingMethods, project, editor, processor, elements);
                        return true;
                    }
                }).showInBestPositionFor(editor);
                return true;
            }
            return true;
        } catch (IncorrectOperationException | PrepareFailedException ignore) {
        }
    }
    return false;
}
Also used : PrepareFailedException(com.intellij.refactoring.extractMethod.PrepareFailedException) AbstractInplaceIntroducer(com.intellij.refactoring.introduce.inplace.AbstractInplaceIntroducer) TextRange(com.intellij.openapi.util.TextRange) NotNull(org.jetbrains.annotations.NotNull) PsiElementProcessor(com.intellij.psi.search.PsiElementProcessor) PsiClassListCellRenderer(com.intellij.ide.util.PsiClassListCellRenderer) IncorrectOperationException(com.intellij.util.IncorrectOperationException) VisibleForTesting(com.google.common.annotations.VisibleForTesting)

Example 2 with PrepareFailedException

use of com.intellij.refactoring.extractMethod.PrepareFailedException in project intellij-community by JetBrains.

the class ExtractLightMethodObjectHandler method extractLightMethodObject.

@Nullable
public static ExtractedData extractLightMethodObject(final Project project, @Nullable PsiElement originalContext, @NotNull final PsiCodeFragment fragment, final String methodName) throws PrepareFailedException {
    final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
    PsiElement[] elements = completeToStatementArray(fragment, elementFactory);
    if (elements == null) {
        elements = CodeInsightUtil.findStatementsInRange(fragment, 0, fragment.getTextLength());
    }
    if (elements.length == 0) {
        return null;
    }
    if (originalContext == null) {
        return null;
    }
    PsiFile file = originalContext.getContainingFile();
    final PsiFile copy = PsiFileFactory.getInstance(project).createFileFromText(file.getName(), file.getFileType(), file.getText(), file.getModificationStamp(), false);
    if (originalContext instanceof PsiKeyword && PsiModifier.PRIVATE.equals(originalContext.getText())) {
        final PsiNameIdentifierOwner identifierOwner = PsiTreeUtil.getParentOfType(originalContext, PsiNameIdentifierOwner.class);
        if (identifierOwner != null) {
            final PsiElement identifier = identifierOwner.getNameIdentifier();
            if (identifier != null) {
                originalContext = identifier;
            }
        }
    }
    final TextRange range = originalContext.getTextRange();
    PsiElement originalAnchor = CodeInsightUtil.findElementInRange(copy, range.getStartOffset(), range.getEndOffset(), originalContext.getClass());
    if (originalAnchor == null) {
        final PsiElement elementAt = copy.findElementAt(range.getStartOffset());
        if (elementAt != null && elementAt.getClass() == originalContext.getClass()) {
            originalAnchor = PsiTreeUtil.skipSiblingsForward(elementAt, PsiWhiteSpace.class);
        }
    }
    final PsiClass containingClass = PsiTreeUtil.getParentOfType(originalAnchor, PsiClass.class, false);
    if (containingClass == null) {
        return null;
    }
    PsiElement anchor = RefactoringUtil.getParentStatement(originalAnchor, false);
    if (anchor == null) {
        if (PsiTreeUtil.getParentOfType(originalAnchor, PsiCodeBlock.class) != null) {
            anchor = originalAnchor;
        }
    }
    final PsiElement container;
    if (anchor == null) {
        container = ((PsiClassInitializer) containingClass.add(elementFactory.createClassInitializer())).getBody();
        anchor = container.getLastChild();
    } else {
        container = anchor.getParent();
    }
    final PsiElement firstElementCopy = container.addRangeBefore(elements[0], elements[elements.length - 1], anchor);
    final PsiElement[] elementsCopy = CodeInsightUtil.findStatementsInRange(copy, firstElementCopy.getTextRange().getStartOffset(), anchor.getTextRange().getStartOffset());
    if (elementsCopy.length == 0) {
        return null;
    }
    if (elementsCopy[elementsCopy.length - 1] instanceof PsiExpressionStatement) {
        final PsiExpression expr = ((PsiExpressionStatement) elementsCopy[elementsCopy.length - 1]).getExpression();
        if (!(expr instanceof PsiAssignmentExpression)) {
            PsiType expressionType = GenericsUtil.getVariableTypeByExpressionType(expr.getType());
            if (expressionType instanceof PsiDisjunctionType) {
                expressionType = ((PsiDisjunctionType) expressionType).getLeastUpperBound();
            }
            if (isValidVariableType(expressionType)) {
                final String uniqueResultName = JavaCodeStyleManager.getInstance(project).suggestUniqueVariableName("result", elementsCopy[0], true);
                final String statementText = expressionType.getCanonicalText() + " " + uniqueResultName + " = " + expr.getText() + ";";
                elementsCopy[elementsCopy.length - 1] = elementsCopy[elementsCopy.length - 1].replace(elementFactory.createStatementFromText(statementText, elementsCopy[elementsCopy.length - 1]));
            }
        }
    }
    LOG.assertTrue(elementsCopy[0].getParent() == container, "element: " + elementsCopy[0].getText() + "; container: " + container.getText());
    final int startOffsetInContainer = elementsCopy[0].getStartOffsetInParent();
    final ControlFlow controlFlow;
    try {
        controlFlow = ControlFlowFactory.getInstance(project).getControlFlow(container, LocalsOrMyInstanceFieldsControlFlowPolicy.getInstance(), false, false);
    } catch (AnalysisCanceledException e) {
        return null;
    }
    List<PsiVariable> variables = ControlFlowUtil.getUsedVariables(controlFlow, controlFlow.getStartOffset(elementsCopy[0]), controlFlow.getEndOffset(elementsCopy[elementsCopy.length - 1]));
    variables = ContainerUtil.filter(variables, variable -> {
        PsiElement variableScope = PsiUtil.getVariableCodeBlock(variable, null);
        return variableScope != null && PsiTreeUtil.isAncestor(variableScope, elementsCopy[elementsCopy.length - 1], true);
    });
    final String outputVariables = StringUtil.join(variables, variable -> "\"variable: \" + " + variable.getName(), " +");
    PsiStatement outStatement = elementFactory.createStatementFromText("System.out.println(" + outputVariables + ");", anchor);
    outStatement = (PsiStatement) container.addAfter(outStatement, elementsCopy[elementsCopy.length - 1]);
    copy.accept(new JavaRecursiveElementWalkingVisitor() {

        private void makePublic(PsiMember method) {
            if (method.hasModifierProperty(PsiModifier.PRIVATE)) {
                VisibilityUtil.setVisibility(method.getModifierList(), PsiModifier.PUBLIC);
            }
        }

        @Override
        public void visitMethod(PsiMethod method) {
            super.visitMethod(method);
            makePublic(method);
        }

        @Override
        public void visitField(PsiField field) {
            super.visitField(field);
            makePublic(field);
        }
    });
    final ExtractMethodObjectProcessor extractMethodObjectProcessor = new ExtractMethodObjectProcessor(project, null, elementsCopy, "") {

        @Override
        protected AbstractExtractDialog createExtractMethodObjectDialog(MyExtractMethodProcessor processor) {
            return new LightExtractMethodObjectDialog(this, methodName);
        }

        @Override
        protected boolean isFoldingApplicable() {
            return false;
        }
    };
    extractMethodObjectProcessor.getExtractProcessor().setShowErrorDialogs(false);
    final ExtractMethodObjectProcessor.MyExtractMethodProcessor extractProcessor = extractMethodObjectProcessor.getExtractProcessor();
    if (extractProcessor.prepare()) {
        if (extractProcessor.showDialog()) {
            try {
                extractProcessor.doExtract();
                final UsageInfo[] usages = extractMethodObjectProcessor.findUsages();
                extractMethodObjectProcessor.performRefactoring(usages);
                extractMethodObjectProcessor.runChangeSignature();
            } catch (IncorrectOperationException e) {
                LOG.error(e);
            }
            if (extractMethodObjectProcessor.isCreateInnerClass()) {
                extractMethodObjectProcessor.changeInstanceAccess(project);
            }
            final PsiElement method = extractMethodObjectProcessor.getMethod();
            LOG.assertTrue(method != null);
            method.delete();
        }
    } else {
        return null;
    }
    final int startOffset = startOffsetInContainer + container.getTextRange().getStartOffset();
    final String generatedCall = copy.getText().substring(startOffset, outStatement.getTextOffset());
    return new ExtractedData(generatedCall, (PsiClass) CodeStyleManager.getInstance(project).reformat(extractMethodObjectProcessor.getInnerClass()), originalAnchor);
}
Also used : IncorrectOperationException(com.intellij.util.IncorrectOperationException) StringUtil(com.intellij.openapi.util.text.StringUtil) VisibilityUtil(com.intellij.util.VisibilityUtil) UsageInfo(com.intellij.usageView.UsageInfo) TextRange(com.intellij.openapi.util.TextRange) InputVariables(com.intellij.refactoring.extractMethod.InputVariables) ContainerUtil(com.intellij.util.containers.ContainerUtil) CodeInsightUtil(com.intellij.codeInsight.CodeInsightUtil) JavaCodeStyleManager(com.intellij.psi.codeStyle.JavaCodeStyleManager) VariableData(com.intellij.refactoring.util.VariableData) Nullable(org.jetbrains.annotations.Nullable) CodeStyleManager(com.intellij.psi.codeStyle.CodeStyleManager) PsiTreeUtil(com.intellij.psi.util.PsiTreeUtil) List(java.util.List) RefactoringUtil(com.intellij.refactoring.util.RefactoringUtil) PrepareFailedException(com.intellij.refactoring.extractMethod.PrepareFailedException) Project(com.intellij.openapi.project.Project) PsiUtil(com.intellij.psi.util.PsiUtil) AbstractExtractDialog(com.intellij.refactoring.extractMethod.AbstractExtractDialog) com.intellij.psi(com.intellij.psi) Logger(com.intellij.openapi.diagnostic.Logger) NotNull(org.jetbrains.annotations.NotNull) com.intellij.psi.controlFlow(com.intellij.psi.controlFlow) UsageInfo(com.intellij.usageView.UsageInfo) TextRange(com.intellij.openapi.util.TextRange) IncorrectOperationException(com.intellij.util.IncorrectOperationException) Nullable(org.jetbrains.annotations.Nullable)

Example 3 with PrepareFailedException

use of com.intellij.refactoring.extractMethod.PrepareFailedException in project intellij-community by JetBrains.

the class TempWithQueryHandler method invokeOnVariable.

private static void invokeOnVariable(final PsiFile file, final Project project, final PsiLocalVariable local, final Editor editor) {
    if (!CommonRefactoringUtil.checkReadOnlyStatus(project, file))
        return;
    String localName = local.getName();
    final PsiExpression initializer = local.getInitializer();
    if (initializer == null) {
        String message = RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message("variable.has.no.initializer", localName));
        CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.REPLACE_TEMP_WITH_QUERY);
        return;
    }
    final PsiReference[] refs = ReferencesSearch.search(local, GlobalSearchScope.projectScope(project), false).toArray(PsiReference.EMPTY_ARRAY);
    if (refs.length == 0) {
        String message = RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message("variable.is.never.used", localName));
        CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.REPLACE_TEMP_WITH_QUERY);
        return;
    }
    final HighlightManager highlightManager = HighlightManager.getInstance(project);
    ArrayList<PsiReference> array = new ArrayList<>();
    EditorColorsManager manager = EditorColorsManager.getInstance();
    final TextAttributes attributes = manager.getGlobalScheme().getAttributes(EditorColors.SEARCH_RESULT_ATTRIBUTES);
    for (PsiReference ref : refs) {
        PsiElement refElement = ref.getElement();
        if (PsiUtil.isAccessedForWriting((PsiExpression) refElement)) {
            array.add(ref);
        }
        if (!array.isEmpty()) {
            PsiReference[] refsForWriting = array.toArray(new PsiReference[array.size()]);
            highlightManager.addOccurrenceHighlights(editor, refsForWriting, attributes, true, null);
            String message = RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message("variable.is.accessed.for.writing", localName));
            CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.REPLACE_TEMP_WITH_QUERY);
            WindowManager.getInstance().getStatusBar(project).setInfo(RefactoringBundle.message("press.escape.to.remove.the.highlighting"));
            return;
        }
    }
    final ExtractMethodProcessor processor = new ExtractMethodProcessor(project, editor, new PsiElement[] { initializer }, local.getType(), REFACTORING_NAME, localName, HelpID.REPLACE_TEMP_WITH_QUERY);
    try {
        if (!processor.prepare())
            return;
    } catch (PrepareFailedException e) {
        CommonRefactoringUtil.showErrorHint(project, editor, e.getMessage(), REFACTORING_NAME, HelpID.REPLACE_TEMP_WITH_QUERY);
        ExtractMethodHandler.highlightPrepareError(e, file, editor, project);
        return;
    }
    final PsiClass targetClass = processor.getTargetClass();
    if (targetClass != null && targetClass.isInterface()) {
        String message = RefactoringBundle.message("cannot.replace.temp.with.query.in.interface");
        CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.REPLACE_TEMP_WITH_QUERY);
        return;
    }
    if (processor.showDialog()) {
        CommandProcessor.getInstance().executeCommand(project, () -> {
            final Runnable action = () -> {
                try {
                    processor.doRefactoring();
                    local.normalizeDeclaration();
                    PsiExpression initializer1 = local.getInitializer();
                    PsiExpression[] exprs = new PsiExpression[refs.length];
                    for (int idx = 0; idx < refs.length; idx++) {
                        PsiElement ref = refs[idx].getElement();
                        exprs[idx] = (PsiExpression) ref.replace(initializer1);
                    }
                    PsiDeclarationStatement declaration = (PsiDeclarationStatement) local.getParent();
                    declaration.delete();
                    highlightManager.addOccurrenceHighlights(editor, exprs, attributes, true, null);
                } catch (IncorrectOperationException e) {
                    LOG.error(e);
                }
            };
            PostprocessReformattingAspect.getInstance(project).postponeFormattingInside(() -> {
                ApplicationManager.getApplication().runWriteAction(action);
                DuplicatesImpl.processDuplicates(processor, project, editor);
            });
        }, REFACTORING_NAME, null);
    }
    WindowManager.getInstance().getStatusBar(project).setInfo(RefactoringBundle.message("press.escape.to.remove.the.highlighting"));
}
Also used : PrepareFailedException(com.intellij.refactoring.extractMethod.PrepareFailedException) HighlightManager(com.intellij.codeInsight.highlighting.HighlightManager) ExtractMethodProcessor(com.intellij.refactoring.extractMethod.ExtractMethodProcessor) ArrayList(java.util.ArrayList) EditorColorsManager(com.intellij.openapi.editor.colors.EditorColorsManager) TextAttributes(com.intellij.openapi.editor.markup.TextAttributes) IncorrectOperationException(com.intellij.util.IncorrectOperationException)

Aggregations

PrepareFailedException (com.intellij.refactoring.extractMethod.PrepareFailedException)3 IncorrectOperationException (com.intellij.util.IncorrectOperationException)3 TextRange (com.intellij.openapi.util.TextRange)2 NotNull (org.jetbrains.annotations.NotNull)2 VisibleForTesting (com.google.common.annotations.VisibleForTesting)1 CodeInsightUtil (com.intellij.codeInsight.CodeInsightUtil)1 HighlightManager (com.intellij.codeInsight.highlighting.HighlightManager)1 PsiClassListCellRenderer (com.intellij.ide.util.PsiClassListCellRenderer)1 Logger (com.intellij.openapi.diagnostic.Logger)1 EditorColorsManager (com.intellij.openapi.editor.colors.EditorColorsManager)1 TextAttributes (com.intellij.openapi.editor.markup.TextAttributes)1 Project (com.intellij.openapi.project.Project)1 StringUtil (com.intellij.openapi.util.text.StringUtil)1 com.intellij.psi (com.intellij.psi)1 CodeStyleManager (com.intellij.psi.codeStyle.CodeStyleManager)1 JavaCodeStyleManager (com.intellij.psi.codeStyle.JavaCodeStyleManager)1 com.intellij.psi.controlFlow (com.intellij.psi.controlFlow)1 PsiElementProcessor (com.intellij.psi.search.PsiElementProcessor)1 PsiTreeUtil (com.intellij.psi.util.PsiTreeUtil)1 PsiUtil (com.intellij.psi.util.PsiUtil)1