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);
}
});
}
}
}
}
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);
}
Aggregations