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