Search in sources :

Example 31 with GrStatementOwner

use of org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner in project intellij-community by JetBrains.

the class GroovyMethodInliner method inlineReferenceImpl.

@Nullable
static RangeMarker inlineReferenceImpl(@NotNull GrCallExpression call, @NotNull GrMethod method, boolean resultOfCallExplicitlyUsed, boolean isTailMethodCall, @Nullable Editor editor) {
    try {
        GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(call.getProject());
        final Project project = call.getProject();
        // Variable declaration for qualifier expression
        GrVariableDeclaration qualifierDeclaration = null;
        GrReferenceExpression innerQualifier = null;
        GrExpression qualifier = null;
        if (call instanceof GrMethodCallExpression && ((GrMethodCallExpression) call).getInvokedExpression() != null) {
            GrExpression invoked = ((GrMethodCallExpression) call).getInvokedExpression();
            if (invoked instanceof GrReferenceExpression && ((GrReferenceExpression) invoked).getQualifierExpression() != null) {
                qualifier = ((GrReferenceExpression) invoked).getQualifierExpression();
                if (PsiUtil.isSuperReference(qualifier)) {
                    qualifier = null;
                } else if (!GroovyInlineMethodUtil.isSimpleReference(qualifier)) {
                    String qualName = generateQualifierName(call, method, project, qualifier);
                    qualifier = (GrExpression) PsiUtil.skipParentheses(qualifier, false);
                    qualifierDeclaration = factory.createVariableDeclaration(ArrayUtil.EMPTY_STRING_ARRAY, qualifier, null, qualName);
                    innerQualifier = (GrReferenceExpression) factory.createExpressionFromText(qualName);
                } else {
                    innerQualifier = (GrReferenceExpression) qualifier;
                }
            }
        }
        GrMethod _method = prepareNewMethod(call, method, qualifier);
        GrExpression result = getAloneResultExpression(_method);
        if (result != null) {
            GrExpression expression = call.replaceWithExpression(result, false);
            TextRange range = expression.getTextRange();
            return editor != null ? editor.getDocument().createRangeMarker(range.getStartOffset(), range.getEndOffset(), true) : null;
        }
        GrMethod newMethod = prepareNewMethod(call, method, innerQualifier);
        String resultName = InlineMethodConflictSolver.suggestNewName("result", newMethod, call);
        // Add variable for method result
        Collection<GrStatement> returnStatements = ControlFlowUtils.collectReturns(newMethod.getBlock());
        final int returnCount = returnStatements.size();
        PsiType methodType = method.getInferredReturnType();
        GrOpenBlock body = newMethod.getBlock();
        assert body != null;
        GrExpression replaced;
        if (resultOfCallExplicitlyUsed && !isTailMethodCall) {
            GrExpression resultExpr = null;
            if (PsiType.VOID.equals(methodType)) {
                resultExpr = factory.createExpressionFromText("null");
            } else if (returnCount == 1) {
                final GrExpression returnExpression = ControlFlowUtils.extractReturnExpression(returnStatements.iterator().next());
                if (returnExpression != null) {
                    resultExpr = factory.createExpressionFromText(returnExpression.getText());
                }
            } else if (returnCount > 1) {
                resultExpr = factory.createExpressionFromText(resultName);
            }
            if (resultExpr == null) {
                resultExpr = factory.createExpressionFromText("null");
            }
            replaced = call.replaceWithExpression(resultExpr, false);
        } else {
            replaced = call;
        }
        // Calculate anchor to insert before
        GrExpression enclosingExpr = GroovyRefactoringUtil.addBlockIntoParent(replaced);
        GrVariableDeclarationOwner owner = PsiTreeUtil.getParentOfType(enclosingExpr, GrVariableDeclarationOwner.class);
        assert owner != null;
        PsiElement element = enclosingExpr;
        while (element != null && element.getParent() != owner) {
            element = element.getParent();
        }
        assert element != null && element instanceof GrStatement;
        GrStatement anchor = (GrStatement) element;
        if (!resultOfCallExplicitlyUsed) {
            assert anchor == enclosingExpr;
        }
        // add qualifier reference declaration
        if (qualifierDeclaration != null) {
            owner.addVariableDeclarationBefore(qualifierDeclaration, anchor);
        }
        // Process method return statements
        if (returnCount > 1 && !PsiType.VOID.equals(methodType) && !isTailMethodCall) {
            PsiType type = methodType != null && methodType.equalsToText(CommonClassNames.JAVA_LANG_OBJECT) ? null : methodType;
            GrVariableDeclaration resultDecl = factory.createVariableDeclaration(ArrayUtil.EMPTY_STRING_ARRAY, "", type, resultName);
            GrStatement statement = ((GrStatementOwner) owner).addStatementBefore(resultDecl, anchor);
            JavaCodeStyleManager.getInstance(statement.getProject()).shortenClassReferences(statement);
            // Replace all return statements with assignments to 'result' variable
            for (GrStatement returnStatement : returnStatements) {
                GrExpression value = ControlFlowUtils.extractReturnExpression(returnStatement);
                if (value != null) {
                    GrExpression assignment = factory.createExpressionFromText(resultName + " = " + value.getText());
                    returnStatement.replaceWithStatement(assignment);
                } else {
                    returnStatement.replaceWithStatement(factory.createExpressionFromText(resultName + " = null"));
                }
            }
        }
        if (!isTailMethodCall && resultOfCallExplicitlyUsed && returnCount == 1) {
            returnStatements.iterator().next().removeStatement();
        } else if (!isTailMethodCall && (PsiType.VOID.equals(methodType) || returnCount == 1)) {
            for (GrStatement returnStatement : returnStatements) {
                if (returnStatement instanceof GrReturnStatement) {
                    final GrExpression returnValue = ((GrReturnStatement) returnStatement).getReturnValue();
                    if (returnValue != null && GroovyRefactoringUtil.hasSideEffect(returnValue)) {
                        returnStatement.replaceWithStatement(returnValue);
                        continue;
                    }
                } else if (GroovyRefactoringUtil.hasSideEffect(returnStatement)) {
                    continue;
                }
                returnStatement.removeStatement();
            }
        }
        // Add all method statements
        GrStatement[] statements = body.getStatements();
        for (GrStatement statement : statements) {
            ((GrStatementOwner) owner).addStatementBefore(statement, anchor);
        }
        if (resultOfCallExplicitlyUsed && !isTailMethodCall) {
            TextRange range = replaced.getTextRange();
            RangeMarker marker = editor != null ? editor.getDocument().createRangeMarker(range.getStartOffset(), range.getEndOffset(), true) : null;
            reformatOwner(owner);
            return marker;
        } else {
            GrStatement stmt;
            if (isTailMethodCall && enclosingExpr.getParent() instanceof GrReturnStatement) {
                stmt = (GrReturnStatement) enclosingExpr.getParent();
            } else {
                stmt = enclosingExpr;
            }
            stmt.removeStatement();
            reformatOwner(owner);
            return null;
        }
    } catch (IncorrectOperationException e) {
        LOG.error(e);
    }
    return null;
}
Also used : GrMethod(org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod) GrStatementOwner(org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner) GrExpression(org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression) TextRange(com.intellij.openapi.util.TextRange) RangeMarker(com.intellij.openapi.editor.RangeMarker) GrReturnStatement(org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrReturnStatement) GrVariableDeclarationOwner(org.jetbrains.plugins.groovy.lang.psi.api.util.GrVariableDeclarationOwner) GrReferenceExpression(org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression) GrStatement(org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement) GroovyPsiElementFactory(org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory) Project(com.intellij.openapi.project.Project) GrVariableDeclaration(org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration) GrMethodCallExpression(org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression) IncorrectOperationException(com.intellij.util.IncorrectOperationException) GrOpenBlock(org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock) Nullable(org.jetbrains.annotations.Nullable)

Example 32 with GrStatementOwner

use of org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner in project intellij-community by JetBrains.

the class GrIntroduceFieldProcessor method generateAssignment.

private void generateAssignment(@NotNull GrVariable field, @Nullable GrStatement anchor, @Nullable GrStatementOwner defaultContainer, @Nullable PsiElement occurrenceToDelete) {
    if (myInitializer == null || defaultContainer == null)
        return;
    GrAssignmentExpression init = (GrAssignmentExpression) GroovyPsiElementFactory.getInstance(myContext.getProject()).createExpressionFromText(mySettings.getName() + " = " + myInitializer.getText());
    GrStatementOwner block;
    if (anchor != null) {
        anchor = GroovyRefactoringUtil.addBlockIntoParent(anchor);
        LOG.assertTrue(anchor.getParent() instanceof GrStatementOwner);
        block = (GrStatementOwner) anchor.getParent();
    } else {
        block = defaultContainer;
    }
    init = (GrAssignmentExpression) block.addStatementBefore(init, anchor);
    replaceOccurrence(field, init.getLValue(), (PsiClass) myContext.getScope());
    if (occurrenceToDelete != null) {
        occurrenceToDelete.delete();
    }
}
Also used : GrAssignmentExpression(org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrAssignmentExpression) GrStatementOwner(org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner)

Example 33 with GrStatementOwner

use of org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner in project intellij-community by JetBrains.

the class GroovyExtractChooser method buildInfo.

@NotNull
private static InitialInfo buildInfo(@NotNull Project project, @NotNull PsiFile file, int start, int end, boolean forceStatements, @NotNull SelectionModel selectionModel, @Nullable GrVariable variable) throws GrRefactoringError {
    PsiElement[] elements = getElementsInOffset(file, start, end, forceStatements);
    //if (elements.length == 1 && elements[0] instanceof GrExpression) {
    //  selectionModel.setSelection(start, elements[0].getTextRange().getEndOffset());
    //}
    GrStatement[] statements = getStatementsByElements(elements);
    if (statements.length == 0) {
        throw new GrRefactoringError(GroovyRefactoringBundle.message("selected.block.should.represent.a.statement.set"));
    }
    for (GrStatement statement : statements) {
        if (GroovyRefactoringUtil.isSuperOrThisCall(statement, true, true)) {
            throw new GrRefactoringError(GroovyRefactoringBundle.message("selected.block.contains.invocation.of.another.class.constructor"));
        }
    }
    GrStatement statement0 = statements[0];
    PsiClass owner = PsiUtil.getContextClass(statement0);
    GrStatementOwner declarationOwner = GroovyRefactoringUtil.getDeclarationOwner(statement0);
    if (owner == null || declarationOwner == null && !ExtractUtil.isSingleExpression(statements)) {
        throw new GrRefactoringError(GroovyRefactoringBundle.message("refactoring.is.not.supported.in.the.current.context"));
    }
    if (declarationOwner == null && ExtractUtil.isSingleExpression(statements) && statement0 instanceof GrExpression && PsiType.VOID.equals(((GrExpression) statement0).getType())) {
        throw new GrRefactoringError(GroovyRefactoringBundle.message("selected.expression.has.void.type"));
    }
    if (ExtractUtil.isSingleExpression(statements) && GrIntroduceHandlerBase.expressionIsIncorrect((GrExpression) statement0, true)) {
        throw new GrRefactoringError(GroovyRefactoringBundle.message("selected.block.should.represent.an.expression"));
    }
    if (ExtractUtil.isSingleExpression(statements) && statement0.getParent() instanceof GrAssignmentExpression && ((GrAssignmentExpression) statement0.getParent()).getLValue() == statement0) {
        throw new GrRefactoringError(GroovyRefactoringBundle.message("selected.expression.should.not.be.lvalue"));
    }
    // collect information about return statements in selected statement set
    Set<GrStatement> allReturnStatements = new HashSet<>();
    GrControlFlowOwner controlFlowOwner = ControlFlowUtils.findControlFlowOwner(statement0);
    LOG.assertTrue(controlFlowOwner != null);
    final Instruction[] flow = new ControlFlowBuilder(project, GrAllVarsInitializedPolicy.getInstance()).buildControlFlow(controlFlowOwner);
    allReturnStatements.addAll(ControlFlowUtils.collectReturns(flow, true));
    ArrayList<GrStatement> returnStatements = new ArrayList<>();
    for (GrStatement returnStatement : allReturnStatements) {
        for (GrStatement statement : statements) {
            if (PsiTreeUtil.isAncestor(statement, returnStatement, false)) {
                returnStatements.add(returnStatement);
                break;
            }
        }
    }
    // collect information about variables in selected block
    FragmentVariableInfos fragmentVariableInfos = ReachingDefinitionsCollector.obtainVariableFlowInformation(statement0, statements[statements.length - 1], controlFlowOwner, flow);
    VariableInfo[] inputInfos = fragmentVariableInfos.getInputVariableNames();
    VariableInfo[] outputInfos = fragmentVariableInfos.getOutputVariableNames();
    if (outputInfos.length == 1 && !returnStatements.isEmpty()) {
        throw new GrRefactoringError(GroovyRefactoringBundle.message("multiple.output.values"));
    }
    boolean hasInterruptingStatements = false;
    for (GrStatement statement : statements) {
        hasInterruptingStatements = GroovyRefactoringUtil.hasWrongBreakStatements(statement) || GroovyRefactoringUtil.hasWrongContinueStatements(statement);
        if (hasInterruptingStatements)
            break;
    }
    // must be replaced by return statement
    boolean hasReturns = !returnStatements.isEmpty();
    List<GrStatement> returnStatementsCopy = new ArrayList<>(returnStatements.size());
    returnStatementsCopy.addAll(returnStatements);
    boolean isReturnStatement = isReturnStatement(statements[statements.length - 1], returnStatementsCopy);
    boolean isLastStatementOfMethod = isLastStatementOfMethodOrClosure(statements);
    if (hasReturns && !isLastStatementOfMethod && !isReturnStatement || hasInterruptingStatements) {
        throw new GrRefactoringError(GroovyRefactoringBundle.message("refactoring.is.not.supported.when.return.statement.interrupts.the.execution.flow"));
    }
    return new InitialInfo(inputInfos, outputInfos, elements, statements, returnStatements, null, project, variable);
}
Also used : VariableInfo(org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.VariableInfo) GrRefactoringError(org.jetbrains.plugins.groovy.refactoring.GrRefactoringError) ArrayList(java.util.ArrayList) GrStatementOwner(org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner) GrExpression(org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression) Instruction(org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction) GrStatement(org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement) GrControlFlowOwner(org.jetbrains.plugins.groovy.lang.psi.GrControlFlowOwner) FragmentVariableInfos(org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.FragmentVariableInfos) GrAssignmentExpression(org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrAssignmentExpression) ControlFlowBuilder(org.jetbrains.plugins.groovy.lang.psi.controlFlow.impl.ControlFlowBuilder) HashSet(com.intellij.util.containers.HashSet) NotNull(org.jetbrains.annotations.NotNull)

Example 34 with GrStatementOwner

use of org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner in project intellij-community by JetBrains.

the class GroovyExtractChooser method isLastStatementOfMethodOrClosure.

private static boolean isLastStatementOfMethodOrClosure(GrStatement[] statements) {
    final GrStatement statement0 = statements[0];
    PsiElement returnFrom = PsiTreeUtil.getParentOfType(statement0, GrMethod.class, GrClosableBlock.class, GroovyFile.class);
    if (returnFrom instanceof GrMethod) {
        returnFrom = ((GrMethod) returnFrom).getBlock();
    }
    LOG.assertTrue(returnFrom instanceof GrStatementOwner);
    final GrStatement[] blockStatements = ((GrStatementOwner) returnFrom).getStatements();
    final GrStatement lastFromBlock = ArrayUtil.getLastElement(blockStatements);
    final GrStatement lastStatement = ArrayUtil.getLastElement(statements);
    return statement0.getManager().areElementsEquivalent(lastFromBlock, lastStatement);
}
Also used : GrMethod(org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod) GrStatementOwner(org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner) GrStatement(org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement)

Example 35 with GrStatementOwner

use of org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner in project intellij-community by JetBrains.

the class GroovyAnnotator method visitTypeDefinitionBody.

@Override
public void visitTypeDefinitionBody(@NotNull GrTypeDefinitionBody typeDefinitionBody) {
    final PsiElement parent = typeDefinitionBody.getParent();
    if (!(parent instanceof GrAnonymousClassDefinition))
        return;
    final PsiElement prev = typeDefinitionBody.getPrevSibling();
    if (!PsiUtil.isLineFeed(prev))
        return;
    final PsiElement newExpression = parent.getParent();
    if (!(newExpression instanceof GrNewExpression))
        return;
    final GrStatementOwner statementOwner = PsiTreeUtil.getParentOfType(newExpression, GrStatementOwner.class);
    final GrParenthesizedExpression parenthesizedExpression = PsiTreeUtil.getParentOfType(newExpression, GrParenthesizedExpression.class);
    if (parenthesizedExpression != null && PsiTreeUtil.isAncestor(statementOwner, parenthesizedExpression, true))
        return;
    final GrArgumentList argumentList = PsiTreeUtil.getParentOfType(newExpression, GrArgumentList.class);
    if (argumentList != null && !(argumentList instanceof GrCommandArgumentList)) {
        if (PsiTreeUtil.isAncestor(statementOwner, argumentList, true))
            return;
    }
    myHolder.createErrorAnnotation(typeDefinitionBody, GroovyBundle.message("ambiguous.code.block"));
}
Also used : GrArgumentList(org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList) GrStatementOwner(org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner)

Aggregations

GrStatementOwner (org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner)38 GrStatement (org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement)11 PsiElement (com.intellij.psi.PsiElement)7 VirtualFile (com.intellij.openapi.vfs.VirtualFile)4 File (java.io.File)4 List (java.util.List)4 GrOpenBlock (org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock)4 GrMethod (org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod)4 ImmutableList (com.google.common.collect.ImmutableList)3 GrControlStatement (org.jetbrains.plugins.groovy.lang.psi.api.formatter.GrControlStatement)3 GrBlockStatement (org.jetbrains.plugins.groovy.lang.psi.api.statements.GrBlockStatement)3 BuildFileKey (com.android.tools.idea.gradle.parser.BuildFileKey)2 NamedObject (com.android.tools.idea.gradle.parser.NamedObject)2 ValueFactory (com.android.tools.idea.gradle.parser.ValueFactory)2 ASTNode (com.intellij.lang.ASTNode)2 Project (com.intellij.openapi.project.Project)2 TextRange (com.intellij.openapi.util.TextRange)2 IElementType (com.intellij.psi.tree.IElementType)2 IncorrectOperationException (com.intellij.util.IncorrectOperationException)2 NotNull (org.jetbrains.annotations.NotNull)2