Search in sources :

Example 6 with VariableInfo

use of org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.VariableInfo in project intellij-community by JetBrains.

the class ExtractUtil method mustAddVariableDeclaration.

/*
  To declare or not a variable to which method call result will be assigned.
   */
private static List<VariableInfo> mustAddVariableDeclaration(@NotNull GrStatement[] statements, @NotNull VariableInfo[] vars) {
    Map<String, VariableInfo> names = new HashMap<>();
    for (VariableInfo var : vars) {
        names.put(var.getName(), var);
    }
    List<VariableInfo> result = new ArrayList<>();
    for (GrStatement statement : statements) {
        if (statement instanceof GrVariableDeclaration) {
            GrVariableDeclaration declaration = (GrVariableDeclaration) statement;
            for (GrVariable variable : declaration.getVariables()) {
                final VariableInfo removed = names.remove(variable.getName());
                if (removed != null) {
                    result.add(removed);
                }
            }
        }
    }
    for (String varName : names.keySet()) {
        if (ResolveUtil.resolveProperty(statements[statements.length - 1], varName) == null) {
            result.add(names.get(varName));
        }
    }
    return result;
}
Also used : GrVariable(org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable) GrVariableDeclaration(org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration) HashMap(com.intellij.util.containers.HashMap) VariableInfo(org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.VariableInfo) GrStatement(org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement)

Example 7 with VariableInfo

use of org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.VariableInfo in project intellij-community by JetBrains.

the class ExtractUtil method generateBody.

public static void generateBody(ExtractInfoHelper helper, boolean isVoid, StringBuilder buffer, boolean forceReturn) {
    VariableInfo[] outputInfos = helper.getOutputVariableInfos();
    ParameterInfo[] infos = helper.getParameterInfos();
    Set<String> declaredVars = new HashSet<>();
    for (ParameterInfo info : infos) {
        declaredVars.add(info.getName());
    }
    for (VariableInfo info : mustAddVariableDeclaration(helper.getStatements(), outputInfos)) {
        declaredVars.add(info.getName());
    }
    List<VariableInfo> genDecl = new ArrayList<>();
    final Collection<GrVariable> outside = collectUsedLocalVarsOrParamsDeclaredOutside(helper);
    for (final GrVariable variable : outside) {
        if (!declaredVars.contains(variable.getName())) {
            genDecl.add(new VariableInfo() {

                @NotNull
                @Override
                public String getName() {
                    return variable.getName();
                }

                @Override
                public PsiType getType() {
                    return variable.getDeclaredType();
                }
            });
        }
    }
    final List<GrStatement> statements = generateVarDeclarations(genDecl, helper.getProject(), null);
    for (GrStatement statement : statements) {
        buffer.append(statement.getText()).append('\n');
    }
    final StringPartInfo stringPartInfo = helper.getStringPartInfo();
    if (!isSingleExpression(helper.getStatements()) && stringPartInfo == null) {
        for (PsiElement element : helper.getInnerElements()) {
            buffer.append(element.getText());
        }
        //append return statement
        if (!isVoid && outputInfos.length > 0) {
            buffer.append('\n');
            if (forceReturn) {
                buffer.append("return ");
            }
            if (outputInfos.length > 1)
                buffer.append('[');
            for (VariableInfo info : outputInfos) {
                buffer.append(info.getName()).append(", ");
            }
            buffer.delete(buffer.length() - 2, buffer.length());
            if (outputInfos.length > 1)
                buffer.append(']');
        }
    } else {
        GrExpression expr = stringPartInfo != null ? stringPartInfo.createLiteralFromSelected() : (GrExpression) PsiUtil.skipParentheses(helper.getStatements()[0], false);
        boolean addReturn = !isVoid && forceReturn && !PsiUtil.isVoidMethodCall(expr);
        if (addReturn) {
            buffer.append("return ");
            final GrExpression methodCall = ApplicationStatementUtil.convertToMethodCallExpression(expr);
            buffer.append(methodCall.getText());
        } else {
            buffer.append(expr != null ? expr.getText() : "");
        }
    }
}
Also used : VariableInfo(org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.VariableInfo) GrExpression(org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression) NotNull(org.jetbrains.annotations.NotNull) GrStatement(org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement) GrVariable(org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable) StringPartInfo(org.jetbrains.plugins.groovy.refactoring.introduce.StringPartInfo) PsiElement(com.intellij.psi.PsiElement) PsiType(com.intellij.psi.PsiType)

Example 8 with VariableInfo

use of org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.VariableInfo 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

VariableInfo (org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.VariableInfo)8 GrStatement (org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement)6 PsiType (com.intellij.psi.PsiType)4 NotNull (org.jetbrains.annotations.NotNull)3 GroovyPsiElementFactory (org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory)3 GrVariable (org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable)2 GrExpression (org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression)2 PsiElement (com.intellij.psi.PsiElement)1 HashMap (com.intellij.util.containers.HashMap)1 HashSet (com.intellij.util.containers.HashSet)1 ArrayList (java.util.ArrayList)1 GrControlFlowOwner (org.jetbrains.plugins.groovy.lang.psi.GrControlFlowOwner)1 GrVariableDeclaration (org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration)1 GrAssignmentExpression (org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrAssignmentExpression)1 GrMethodCallExpression (org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression)1 GrStatementOwner (org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner)1 Instruction (org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction)1 ControlFlowBuilder (org.jetbrains.plugins.groovy.lang.psi.controlFlow.impl.ControlFlowBuilder)1 FragmentVariableInfos (org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.FragmentVariableInfos)1 GrRefactoringError (org.jetbrains.plugins.groovy.refactoring.GrRefactoringError)1