Search in sources :

Example 16 with Instruction

use of org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction 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 17 with Instruction

use of org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction 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 18 with Instruction

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

the class GrFinalVariableAccessInspection method appendFieldsInitializedInClassInitializer.

private static void appendFieldsInitializedInClassInitializer(@NotNull GrClassInitializer[] initializers, @Nullable GrClassInitializer initializerToStop, boolean isStatic, @NotNull List<GrField> fields, @NotNull Set<GrVariable> initializedFields) {
    for (GrClassInitializer curInit : initializers) {
        if (curInit.isStatic() != isStatic)
            continue;
        if (curInit == initializerToStop)
            break;
        final GrOpenBlock block = curInit.getBlock();
        final Instruction[] flow = buildFlowForField(block);
        for (GrField field : fields) {
            if (field.hasModifierProperty(PsiModifier.STATIC) == isStatic && !initializedFields.contains(field) && VariableInitializationChecker.isVariableDefinitelyInitializedCached(field, block, flow)) {
                initializedFields.add(field);
            }
        }
    }
}
Also used : GrOpenBlock(org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock) Instruction(org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction) ReadWriteVariableInstruction(org.jetbrains.plugins.groovy.lang.psi.controlFlow.ReadWriteVariableInstruction)

Example 19 with Instruction

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

the class GrFinalVariableAccessInspection method appendInitializationFromChainedConstructors.

private static void appendInitializationFromChainedConstructors(@NotNull GrMethod constructor, @NotNull List<GrField> fields, @NotNull Set<GrVariable> initializedFields) {
    final List<GrMethod> chained = getChainedConstructors(constructor);
    chained.remove(0);
    for (GrMethod method : chained) {
        final GrOpenBlock block = method.getBlock();
        if (block == null)
            continue;
        final Instruction[] flow = buildFlowForField(block);
        for (GrField field : fields) {
            if (!field.hasModifierProperty(PsiModifier.STATIC) && !initializedFields.contains(field) && VariableInitializationChecker.isVariableDefinitelyInitializedCached(field, block, flow)) {
                initializedFields.add(field);
            }
        }
    }
}
Also used : GrMethod(org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod) GrOpenBlock(org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock) Instruction(org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction) ReadWriteVariableInstruction(org.jetbrains.plugins.groovy.lang.psi.controlFlow.ReadWriteVariableInstruction)

Example 20 with Instruction

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

the class GrFinalVariableAccessInspection method isFieldInitialized.

private static boolean isFieldInitialized(@NotNull GrField field) {
    if (field instanceof GrEnumConstant)
        return true;
    if (field.getInitializerGroovy() != null)
        return true;
    if (isImmutableField(field))
        return true;
    final boolean isStatic = field.hasModifierProperty(PsiModifier.STATIC);
    final GrTypeDefinition aClass = ((GrTypeDefinition) field.getContainingClass());
    if (aClass == null)
        return true;
    GrClassInitializer[] initializers = aClass.getInitializers();
    for (GrClassInitializer initializer : initializers) {
        if (initializer.isStatic() != isStatic)
            continue;
        final GrOpenBlock block = initializer.getBlock();
        final Instruction[] initializerFlow = buildFlowForField(block);
        if (VariableInitializationChecker.isVariableDefinitelyInitializedCached(field, block, initializerFlow)) {
            return true;
        }
    }
    if (isStatic)
        return false;
    final GrMethod[] constructors = aClass.getCodeConstructors();
    if (constructors.length == 0)
        return false;
    Set<GrMethod> initializedConstructors = ContainerUtil.newHashSet();
    Set<GrMethod> notInitializedConstructors = ContainerUtil.newHashSet();
    NEXT_CONSTR: for (GrMethod constructor : constructors) {
        if (constructor.getBlock() == null)
            return false;
        final List<GrMethod> chained = getChainedConstructors(constructor);
        NEXT_CHAINED: for (GrMethod method : chained) {
            if (initializedConstructors.contains(method)) {
                continue NEXT_CONSTR;
            } else if (notInitializedConstructors.contains(method)) {
                continue NEXT_CHAINED;
            }
            final GrOpenBlock block = method.getBlock();
            assert block != null;
            final boolean initialized = VariableInitializationChecker.isVariableDefinitelyInitializedCached(field, block, buildFlowForField(block));
            if (initialized) {
                initializedConstructors.add(method);
                continue NEXT_CONSTR;
            } else {
                notInitializedConstructors.add(method);
            }
        }
        return false;
    }
    return true;
}
Also used : GrTypeDefinition(org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition) GrEnumConstant(org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstant) GrMethod(org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod) GrModifierList(org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList) GrOpenBlock(org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock) Instruction(org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction) ReadWriteVariableInstruction(org.jetbrains.plugins.groovy.lang.psi.controlFlow.ReadWriteVariableInstruction)

Aggregations

Instruction (org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction)27 ReadWriteVariableInstruction (org.jetbrains.plugins.groovy.lang.psi.controlFlow.ReadWriteVariableInstruction)18 PsiElement (com.intellij.psi.PsiElement)10 Nullable (org.jetbrains.annotations.Nullable)8 GrControlFlowOwner (org.jetbrains.plugins.groovy.lang.psi.GrControlFlowOwner)7 GrExpression (org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression)7 IfEndInstruction (org.jetbrains.plugins.groovy.lang.psi.controlFlow.impl.IfEndInstruction)7 NotNull (org.jetbrains.annotations.NotNull)6 GroovyPsiElement (org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement)6 GrMethod (org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod)6 GrVariable (org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable)5 GrOpenBlock (org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock)5 AfterCallInstruction (org.jetbrains.plugins.groovy.lang.psi.controlFlow.AfterCallInstruction)5 MaybeReturnInstruction (org.jetbrains.plugins.groovy.lang.psi.controlFlow.impl.MaybeReturnInstruction)5 GrClosableBlock (org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock)4 GrReferenceExpression (org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression)4 ThrowingInstruction (org.jetbrains.plugins.groovy.lang.psi.controlFlow.impl.ThrowingInstruction)4 BitSet (java.util.BitSet)3 ControlFlowUtils (org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils)3 GrStatement (org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement)3