use of com.intellij.codeInsight.controlflow.Instruction in project intellij-community by JetBrains.
the class PyBaseMakeFunctionTopLevelProcessor method analyseScope.
@NotNull
protected AnalysisResult analyseScope(@NotNull ScopeOwner owner) {
final ControlFlow controlFlow = ControlFlowCache.getControlFlow(owner);
final AnalysisResult result = new AnalysisResult();
for (Instruction instruction : controlFlow.getInstructions()) {
if (instruction instanceof ReadWriteInstruction) {
final ReadWriteInstruction readWriteInstruction = (ReadWriteInstruction) instruction;
final PsiElement element = readWriteInstruction.getElement();
if (element == null) {
continue;
}
if (readWriteInstruction.getAccess().isReadAccess()) {
for (PsiElement resolved : PyUtil.multiResolveTopPriority(element, myResolveContext)) {
if (resolved != null) {
if (isInitOrNewMethod(resolved)) {
resolved = ((PyFunction) resolved).getContainingClass();
}
if (isFromEnclosingScope(resolved)) {
result.readsFromEnclosingScope.add(element);
} else if (!belongsToFunction(resolved)) {
myExternalReads.add(resolved);
}
if (resolved instanceof PyParameter && ((PyParameter) resolved).isSelf()) {
if (PsiTreeUtil.getParentOfType(resolved, PyFunction.class) == myFunction) {
result.readsOfSelfParameter.add(element);
} else if (!PsiTreeUtil.isAncestor(myFunction, resolved, true)) {
result.readsOfSelfParametersFromEnclosingScope.add(element);
}
}
}
}
}
if (readWriteInstruction.getAccess().isWriteAccess() && element instanceof PyTargetExpression) {
for (PsiElement resolved : PyUtil.multiResolveTopPriority(element, myResolveContext)) {
if (resolved != null) {
if (element.getParent() instanceof PyNonlocalStatement && isFromEnclosingScope(resolved)) {
result.nonlocalWritesToEnclosingScope.add((PyTargetExpression) element);
}
if (resolved instanceof PyParameter && ((PyParameter) resolved).isSelf() && PsiTreeUtil.getParentOfType(resolved, PyFunction.class) == myFunction) {
result.writesToSelfParameter.add((PyTargetExpression) element);
}
}
}
}
}
}
return result;
}
use of com.intellij.codeInsight.controlflow.Instruction in project intellij-community by JetBrains.
the class PyDefUseUtil method getPostRefs.
@NotNull
public static PsiElement[] getPostRefs(ScopeOwner block, PyTargetExpression var, PyExpression anchor) {
final ControlFlow controlFlow = ControlFlowCache.getControlFlow(block);
final Instruction[] instructions = controlFlow.getInstructions();
final int instr = ControlFlowUtil.findInstructionNumberByElement(instructions, anchor);
if (instr < 0) {
return PyElement.EMPTY_ARRAY;
}
final boolean[] visited = new boolean[instructions.length];
final Collection<PyElement> result = Sets.newHashSet();
for (Instruction instruction : instructions[instr].allSucc()) {
getPostRefs(var, instructions, instruction.num(), visited, result);
}
return result.toArray(new PyElement[result.size()]);
}
use of com.intellij.codeInsight.controlflow.Instruction in project intellij-community by JetBrains.
the class PyDefUseUtil method getLatestDefs.
@NotNull
public static List<Instruction> getLatestDefs(ScopeOwner block, String varName, PsiElement anchor, boolean acceptTypeAssertions, boolean acceptImplicitImports) {
final ControlFlow controlFlow = ControlFlowCache.getControlFlow(block);
final Instruction[] instructions = controlFlow.getInstructions();
final PyAugAssignmentStatement augAssignment = PyAugAssignmentStatementNavigator.getStatementByTarget(anchor);
if (augAssignment != null) {
anchor = augAssignment;
}
int instr = ControlFlowUtil.findInstructionNumberByElement(instructions, anchor);
if (instr < 0) {
return Collections.emptyList();
}
if (anchor instanceof PyTargetExpression) {
Collection<Instruction> pred = instructions[instr].allPred();
if (!pred.isEmpty()) {
instr = pred.iterator().next().num();
}
}
final Collection<Instruction> result = getLatestDefs(varName, instructions, instr, acceptTypeAssertions, acceptImplicitImports);
return new ArrayList<>(result);
}
use of com.intellij.codeInsight.controlflow.Instruction in project intellij-community by JetBrains.
the class PyReferenceImpl method getResultsFromProcessor.
protected List<RatedResolveResult> getResultsFromProcessor(@NotNull String referencedName, @NotNull PyResolveProcessor processor, @Nullable PsiElement realContext, @Nullable PsiElement resolveRoof) {
boolean unreachableLocalDeclaration = false;
boolean resolveInParentScope = false;
final ResolveResultList resultList = new ResolveResultList();
final ScopeOwner referenceOwner = ScopeUtil.getScopeOwner(realContext);
final TypeEvalContext typeEvalContext = myContext.getTypeEvalContext();
ScopeOwner resolvedOwner = processor.getOwner();
if (resolvedOwner != null && !processor.getResults().isEmpty()) {
final Collection<PsiElement> resolvedElements = processor.getElements();
final Scope resolvedScope = ControlFlowCache.getScope(resolvedOwner);
if (!resolvedScope.isGlobal(referencedName)) {
if (resolvedOwner == referenceOwner) {
final List<Instruction> instructions = PyDefUseUtil.getLatestDefs(resolvedOwner, referencedName, realContext, false, true);
// TODO: Use the results from the processor as a cache for resolving to latest defs
final ResolveResultList latestDefs = resolveToLatestDefs(instructions, realContext, referencedName, typeEvalContext);
if (!latestDefs.isEmpty()) {
return latestDefs;
} else if (resolvedOwner instanceof PyClass || instructions.isEmpty() && allInOwnScopeComprehensions(resolvedElements)) {
resolveInParentScope = true;
} else if (PyiUtil.isInsideStubAnnotation(myElement)) {
for (PsiElement element : resolvedElements) {
resultList.poke(element, getRate(element, typeEvalContext));
}
return resultList;
} else {
unreachableLocalDeclaration = true;
}
} else if (referenceOwner != null) {
final Scope referenceScope = ControlFlowCache.getScope(referenceOwner);
if (referenceScope.containsDeclaration(referencedName)) {
unreachableLocalDeclaration = true;
}
}
}
}
if (!unreachableLocalDeclaration) {
if (resolveInParentScope) {
processor = new PyResolveProcessor(referencedName);
resolvedOwner = ScopeUtil.getScopeOwner(resolvedOwner);
if (resolvedOwner != null) {
PyResolveUtil.scopeCrawlUp(processor, resolvedOwner, referencedName, resolveRoof);
}
}
for (Map.Entry<PsiElement, PyImportedNameDefiner> entry : processor.getResults().entrySet()) {
final PsiElement resolved = entry.getKey();
final PyImportedNameDefiner definer = entry.getValue();
if (resolved != null) {
if (typeEvalContext.maySwitchToAST(resolved) && isInnerComprehension(realContext, resolved)) {
continue;
}
if (skipClassForwardReferences(referenceOwner, resolved)) {
continue;
}
if (definer == null) {
resultList.poke(resolved, getRate(resolved, typeEvalContext));
} else {
resultList.poke(definer, getRate(definer, typeEvalContext));
resultList.add(new ImportedResolveResult(resolved, getRate(resolved, typeEvalContext), definer));
}
} else if (definer != null) {
resultList.add(new ImportedResolveResult(null, RatedResolveResult.RATE_LOW, definer));
}
}
if (!resultList.isEmpty()) {
return resultList;
}
}
return resolveByReferenceResolveProviders();
}
use of com.intellij.codeInsight.controlflow.Instruction in project intellij-community by JetBrains.
the class DFAEngine method performDFA.
public List<E> performDFA(final List<E> info) throws DFALimitExceededException {
if (LOG.isDebugEnabled()) {
LOG.debug("Performing DFA\n" + "Instance: " + myDfa + " Semilattice: " + mySemilattice + "\nCon");
}
// initializing dfa
final E initial = myDfa.initial();
for (int i = 0; i < myFlow.length; i++) {
info.add(i, initial);
}
final boolean[] visited = new boolean[myFlow.length];
final int[] order = ControlFlowUtil.postOrder(myFlow);
// Count limit for number of iterations per worklist
final int limit = getIterationLimit();
int dfaCount = 0;
final long startTime = System.nanoTime();
for (int i = 0; i < myFlow.length; i++) {
// Check if canceled
ProgressManager.checkCanceled();
if (System.nanoTime() - startTime > TIME_LIMIT) {
if (LOG.isDebugEnabled()) {
LOG.debug("Time limit exceeded");
}
throw new DFALimitExceededException("Time limit exceeded");
}
// Iteration count per one worklist
int count = 0;
final Instruction instruction = myFlow[order[i]];
final int number = instruction.num();
if (!visited[number]) {
final Queue<Instruction> worklist = new LinkedList<>();
worklist.add(instruction);
visited[number] = true;
while (true) {
// Check if canceled
ProgressManager.checkCanceled();
// It is essential to apply this check!!!
// This gives us more chances that resulting info will be closer to expected result
// Also it is used as indicator that "equals" method is implemented correctly in E
count++;
if (count > limit) {
if (LOG.isDebugEnabled()) {
LOG.debug("Iteration count exceeded on worklist");
}
throw new DFALimitExceededException("Iteration count exceeded on worklist");
}
final Instruction currentInstruction = worklist.poll();
if (currentInstruction == null) {
break;
}
final int currentNumber = currentInstruction.num();
final E oldE = info.get(currentNumber);
final E joinedE = join(currentInstruction, info);
final E newE = myDfa.fun(joinedE, currentInstruction);
if (!mySemilattice.eq(newE, oldE)) {
if (LOG.isDebugEnabled()) {
LOG.debug("Number: " + currentNumber + " old: " + oldE.toString() + " new: " + newE.toString());
}
info.set(currentNumber, newE);
for (Instruction next : getNext(currentInstruction)) {
worklist.add(next);
visited[next.num()] = true;
}
}
}
}
// Move to another worklist
dfaCount += count;
}
if (LOG.isDebugEnabled()) {
LOG.debug("Done in: " + (System.nanoTime() - startTime) / 10e6 + "ms. Ratio: " + dfaCount / myFlow.length);
}
return info;
}
Aggregations