use of org.jetbrains.plugins.groovy.lang.psi.controlFlow.ReadWriteVariableInstruction in project intellij-community by JetBrains.
the class GrIntroduceClosureParameterProcessor method findUsagesForLocal.
private static Collection<PsiReference> findUsagesForLocal(GrClosableBlock initializer, final GrVariable var) {
final Instruction[] flow = ControlFlowUtils.findControlFlowOwner(initializer).getControlFlow();
final List<BitSet> writes = ControlFlowUtils.inferWriteAccessMap(flow, var);
Instruction writeInstr = null;
final PsiElement parent = initializer.getParent();
if (parent instanceof GrVariable) {
writeInstr = ContainerUtil.find(flow, instruction -> instruction.getElement() == var);
} else if (parent instanceof GrAssignmentExpression) {
final GrReferenceExpression refExpr = (GrReferenceExpression) ((GrAssignmentExpression) parent).getLValue();
final Instruction instruction = ContainerUtil.find(flow, instruction1 -> instruction1.getElement() == refExpr);
LOG.assertTrue(instruction != null);
final BitSet prev = writes.get(instruction.num());
if (prev.cardinality() == 1) {
writeInstr = flow[prev.nextSetBit(0)];
}
}
LOG.assertTrue(writeInstr != null);
Collection<PsiReference> result = new ArrayList<>();
for (Instruction instruction : flow) {
if (!(instruction instanceof ReadWriteVariableInstruction))
continue;
if (((ReadWriteVariableInstruction) instruction).isWrite())
continue;
final PsiElement element = instruction.getElement();
if (element instanceof GrVariable && element != var)
continue;
if (!(element instanceof GrReferenceExpression))
continue;
final GrReferenceExpression ref = (GrReferenceExpression) element;
if (ref.isQualified() || ref.resolve() != var)
continue;
final BitSet prev = writes.get(instruction.num());
if (prev.cardinality() == 1 && prev.get(writeInstr.num())) {
result.add(ref);
}
}
return result;
}
use of org.jetbrains.plugins.groovy.lang.psi.controlFlow.ReadWriteVariableInstruction in project intellij-community by JetBrains.
the class UnassignedVariableAccessInspection method check.
@Override
protected void check(@NotNull GrControlFlowOwner owner, @NotNull ProblemsHolder problemsHolder) {
Instruction[] flow = owner.getControlFlow();
ReadWriteVariableInstruction[] reads = ControlFlowBuilderUtil.getReadsWithoutPriorWrites(flow, true);
for (ReadWriteVariableInstruction read : reads) {
PsiElement element = read.getElement();
if (element instanceof GroovyPsiElement && !(element instanceof GrClosableBlock)) {
String name = read.getVariableName();
GroovyPsiElement property = ResolveUtil.resolveProperty((GroovyPsiElement) element, name);
if (property != null && !(property instanceof PsiParameter) && !(property instanceof PsiField) && PsiTreeUtil.isAncestor(owner, property, false) && !(myIgnoreBooleanExpressions && isBooleanCheck(element))) {
problemsHolder.registerProblem(element, GroovyInspectionBundle.message("unassigned.access.tooltip", name));
}
}
}
}
use of org.jetbrains.plugins.groovy.lang.psi.controlFlow.ReadWriteVariableInstruction in project intellij-community by JetBrains.
the class ControlFlowUtils method findAccess.
/**
* searches for next or previous write access to local variable
* @param local variable to analyze
* @param place place to start searching
* @param ahead if true search for next write. if false searches for previous write
* @return all write instructions leading to (or preceding) the place
*/
public static List<ReadWriteVariableInstruction> findAccess(GrVariable local, final PsiElement place, boolean ahead, boolean writeAccessOnly) {
LOG.assertTrue(!(local instanceof GrField), local.getClass());
final GrControlFlowOwner owner = findControlFlowOwner(place);
assert owner != null;
final Instruction cur = findInstruction(place, owner.getControlFlow());
if (cur == null) {
throw new IllegalArgumentException("place is not in the flow");
}
return findAccess(local, ahead, writeAccessOnly, cur);
}
use of org.jetbrains.plugins.groovy.lang.psi.controlFlow.ReadWriteVariableInstruction in project intellij-community by JetBrains.
the class ControlFlowUtils method inferWriteAccessMap.
@NotNull
public static List<BitSet> inferWriteAccessMap(final Instruction[] flow, final GrVariable var) {
final Semilattice<BitSet> sem = new Semilattice<BitSet>() {
@NotNull
@Override
public BitSet join(@NotNull List<BitSet> ins) {
BitSet result = new BitSet(flow.length);
for (BitSet set : ins) {
result.or(set);
}
return result;
}
@Override
public boolean eq(@NotNull BitSet e1, @NotNull BitSet e2) {
return e1.equals(e2);
}
};
DfaInstance<BitSet> dfa = new DfaInstance<BitSet>() {
@Override
public void fun(@NotNull BitSet bitSet, @NotNull Instruction instruction) {
if (!(instruction instanceof ReadWriteVariableInstruction))
return;
if (!((ReadWriteVariableInstruction) instruction).isWrite())
return;
final PsiElement element = instruction.getElement();
if (element instanceof GrVariable && element != var)
return;
if (element instanceof GrReferenceExpression) {
final GrReferenceExpression ref = (GrReferenceExpression) element;
if (ref.isQualified() || ref.resolve() != var) {
return;
}
}
if (!((ReadWriteVariableInstruction) instruction).getVariableName().equals(var.getName())) {
return;
}
bitSet.clear();
bitSet.set(instruction.num());
}
@NotNull
@Override
public BitSet initial() {
return new BitSet(flow.length);
}
};
return new DFAEngine<>(flow, dfa, sem).performForceDFA();
}
use of org.jetbrains.plugins.groovy.lang.psi.controlFlow.ReadWriteVariableInstruction in project intellij-community by JetBrains.
the class ReachingDefinitionsCollector method obtainVariableFlowInformation.
@NotNull
public static FragmentVariableInfos obtainVariableFlowInformation(@NotNull final GrStatement first, @NotNull final GrStatement last, @NotNull final GrControlFlowOwner flowOwner, @NotNull final Instruction[] flow) {
final DefinitionMap dfaResult = inferDfaResult(flow);
final LinkedHashSet<Integer> fragmentInstructions = getFragmentInstructions(first, last, flow);
final int[] postorder = reversedPostOrder(flow);
LinkedHashSet<Integer> reachableFromFragmentReads = getReachable(fragmentInstructions, flow, dfaResult, postorder);
LinkedHashSet<Integer> fragmentReads = filterReads(fragmentInstructions, flow);
final Map<String, VariableInfo> imap = new LinkedHashMap<>();
final Map<String, VariableInfo> omap = new LinkedHashMap<>();
final PsiManager manager = first.getManager();
for (final Integer ref : fragmentReads) {
ReadWriteVariableInstruction rwInstruction = (ReadWriteVariableInstruction) flow[ref];
String name = rwInstruction.getVariableName();
final int[] defs = dfaResult.getDefinitions(ref);
if (!allDefsInFragment(defs, fragmentInstructions)) {
addVariable(name, imap, manager, getType(rwInstruction.getElement()));
}
}
for (final Integer ref : reachableFromFragmentReads) {
ReadWriteVariableInstruction rwInstruction = (ReadWriteVariableInstruction) flow[ref];
String name = rwInstruction.getVariableName();
final int[] defs = dfaResult.getDefinitions(ref);
if (anyDefInFragment(defs, fragmentInstructions)) {
for (int def : defs) {
if (fragmentInstructions.contains(def)) {
PsiType outputType = getType(flow[def].getElement());
addVariable(name, omap, manager, outputType);
}
}
if (!allProperDefsInFragment(defs, ref, fragmentInstructions, postorder)) {
PsiType inputType = getType(rwInstruction.getElement());
addVariable(name, imap, manager, inputType);
}
}
}
addClosureUsages(imap, omap, first, last, flowOwner);
final VariableInfo[] iarr = filterNonlocals(imap, last);
final VariableInfo[] oarr = filterNonlocals(omap, last);
return new FragmentVariableInfos() {
@Override
public VariableInfo[] getInputVariableNames() {
return iarr;
}
@Override
public VariableInfo[] getOutputVariableNames() {
return oarr;
}
};
}
Aggregations