Search in sources :

Example 1 with AbstractExtractDialog

use of com.intellij.refactoring.extractMethod.AbstractExtractDialog 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)

Aggregations

CodeInsightUtil (com.intellij.codeInsight.CodeInsightUtil)1 Logger (com.intellij.openapi.diagnostic.Logger)1 Project (com.intellij.openapi.project.Project)1 TextRange (com.intellij.openapi.util.TextRange)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 PsiTreeUtil (com.intellij.psi.util.PsiTreeUtil)1 PsiUtil (com.intellij.psi.util.PsiUtil)1 AbstractExtractDialog (com.intellij.refactoring.extractMethod.AbstractExtractDialog)1 InputVariables (com.intellij.refactoring.extractMethod.InputVariables)1 PrepareFailedException (com.intellij.refactoring.extractMethod.PrepareFailedException)1 RefactoringUtil (com.intellij.refactoring.util.RefactoringUtil)1 VariableData (com.intellij.refactoring.util.VariableData)1 UsageInfo (com.intellij.usageView.UsageInfo)1 IncorrectOperationException (com.intellij.util.IncorrectOperationException)1 VisibilityUtil (com.intellij.util.VisibilityUtil)1 ContainerUtil (com.intellij.util.containers.ContainerUtil)1