Search in sources :

Example 1 with ControlFlowBuilder

use of org.jetbrains.plugins.groovy.lang.psi.controlFlow.impl.ControlFlowBuilder in project intellij-community by JetBrains.

the class GroovyInlineLocalProcessor method collectRefs.

private static void collectRefs(final GrVariable variable, Instruction[] flow, final List<BitSet> writes, final int writeInstructionNumber, final ArrayList<UsageInfo> toInline) {
    for (Instruction instruction : flow) {
        final PsiElement element = instruction.getElement();
        if (instruction instanceof ReadWriteVariableInstruction) {
            if (((ReadWriteVariableInstruction) instruction).isWrite())
                continue;
            if (element instanceof GrVariable && element != variable)
                continue;
            if (!(element instanceof GrReferenceExpression))
                continue;
            final GrReferenceExpression ref = (GrReferenceExpression) element;
            if (ref.isQualified() || ref.resolve() != variable)
                continue;
            final BitSet prev = writes.get(instruction.num());
            if (writeInstructionNumber >= 0 && prev.cardinality() == 1 && prev.get(writeInstructionNumber)) {
                toInline.add(new UsageInfo(ref));
            } else if (writeInstructionNumber == -1 && prev.cardinality() == 0) {
                toInline.add(new ClosureUsage(ref));
            }
        } else if (element instanceof GrClosableBlock) {
            final BitSet prev = writes.get(instruction.num());
            if (writeInstructionNumber >= 0 && prev.cardinality() == 1 && prev.get(writeInstructionNumber) || writeInstructionNumber == -1 && prev.cardinality() == 0) {
                final Instruction[] closureFlow = ((GrClosableBlock) element).getControlFlow();
                collectRefs(variable, closureFlow, ControlFlowUtils.inferWriteAccessMap(closureFlow, variable), -1, toInline);
            }
        } else if (element instanceof GrAnonymousClassDefinition) {
            final BitSet prev = writes.get(instruction.num());
            if (writeInstructionNumber >= 0 && prev.cardinality() == 1 && prev.get(writeInstructionNumber) || writeInstructionNumber == -1 && prev.cardinality() == 0) {
                ((GrAnonymousClassDefinition) element).acceptChildren(new GroovyRecursiveElementVisitor() {

                    @Override
                    public void visitField(@NotNull GrField field) {
                        GrExpression initializer = field.getInitializerGroovy();
                        if (initializer != null) {
                            Instruction[] flow = new ControlFlowBuilder(field.getProject()).buildControlFlow(initializer);
                            collectRefs(variable, flow, ControlFlowUtils.inferWriteAccessMap(flow, variable), -1, toInline);
                        }
                    }

                    @Override
                    public void visitMethod(@NotNull GrMethod method) {
                        GrOpenBlock block = method.getBlock();
                        if (block != null) {
                            Instruction[] flow = block.getControlFlow();
                            collectRefs(variable, flow, ControlFlowUtils.inferWriteAccessMap(flow, variable), -1, toInline);
                        }
                    }

                    @Override
                    public void visitClassInitializer(@NotNull GrClassInitializer initializer) {
                        GrOpenBlock block = initializer.getBlock();
                        Instruction[] flow = block.getControlFlow();
                        collectRefs(variable, flow, ControlFlowUtils.inferWriteAccessMap(flow, variable), -1, toInline);
                    }
                });
            }
        }
    }
}
Also used : GrField(org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField) ReadWriteVariableInstruction(org.jetbrains.plugins.groovy.lang.psi.controlFlow.ReadWriteVariableInstruction) GrAnonymousClassDefinition(org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnonymousClassDefinition) BitSet(java.util.BitSet) GrMethod(org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod) GrClosableBlock(org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock) GroovyRecursiveElementVisitor(org.jetbrains.plugins.groovy.lang.psi.GroovyRecursiveElementVisitor) GrExpression(org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression) Instruction(org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction) ReadWriteVariableInstruction(org.jetbrains.plugins.groovy.lang.psi.controlFlow.ReadWriteVariableInstruction) GrReferenceExpression(org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression) GrVariable(org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable) GrClassInitializer(org.jetbrains.plugins.groovy.lang.psi.api.statements.GrClassInitializer) GrOpenBlock(org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock) ControlFlowBuilder(org.jetbrains.plugins.groovy.lang.psi.controlFlow.impl.ControlFlowBuilder) PsiElement(com.intellij.psi.PsiElement) UsageInfo(com.intellij.usageView.UsageInfo)

Example 2 with ControlFlowBuilder

use of org.jetbrains.plugins.groovy.lang.psi.controlFlow.impl.ControlFlowBuilder 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)

Aggregations

GrExpression (org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression)2 Instruction (org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction)2 ControlFlowBuilder (org.jetbrains.plugins.groovy.lang.psi.controlFlow.impl.ControlFlowBuilder)2 PsiElement (com.intellij.psi.PsiElement)1 UsageInfo (com.intellij.usageView.UsageInfo)1 HashSet (com.intellij.util.containers.HashSet)1 ArrayList (java.util.ArrayList)1 BitSet (java.util.BitSet)1 NotNull (org.jetbrains.annotations.NotNull)1 GrControlFlowOwner (org.jetbrains.plugins.groovy.lang.psi.GrControlFlowOwner)1 GroovyRecursiveElementVisitor (org.jetbrains.plugins.groovy.lang.psi.GroovyRecursiveElementVisitor)1 GrClassInitializer (org.jetbrains.plugins.groovy.lang.psi.api.statements.GrClassInitializer)1 GrField (org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField)1 GrStatement (org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement)1 GrVariable (org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable)1 GrClosableBlock (org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock)1 GrOpenBlock (org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock)1 GrAssignmentExpression (org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrAssignmentExpression)1 GrReferenceExpression (org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression)1 GrAnonymousClassDefinition (org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnonymousClassDefinition)1