Search in sources :

Example 11 with Instruction

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;
}
Also used : ReadWriteInstruction(com.jetbrains.python.codeInsight.controlflow.ReadWriteInstruction) ReadWriteInstruction(com.jetbrains.python.codeInsight.controlflow.ReadWriteInstruction) Instruction(com.intellij.codeInsight.controlflow.Instruction) ControlFlow(com.intellij.codeInsight.controlflow.ControlFlow) PsiElement(com.intellij.psi.PsiElement) NotNull(org.jetbrains.annotations.NotNull)

Example 12 with Instruction

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()]);
}
Also used : ReadWriteInstruction(com.jetbrains.python.codeInsight.controlflow.ReadWriteInstruction) Instruction(com.intellij.codeInsight.controlflow.Instruction) ControlFlow(com.intellij.codeInsight.controlflow.ControlFlow) NotNull(org.jetbrains.annotations.NotNull)

Example 13 with Instruction

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);
}
Also used : ReadWriteInstruction(com.jetbrains.python.codeInsight.controlflow.ReadWriteInstruction) Instruction(com.intellij.codeInsight.controlflow.Instruction) ControlFlow(com.intellij.codeInsight.controlflow.ControlFlow) NotNull(org.jetbrains.annotations.NotNull)

Example 14 with Instruction

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();
}
Also used : Instruction(com.intellij.codeInsight.controlflow.Instruction) TypeEvalContext(com.jetbrains.python.psi.types.TypeEvalContext) ScopeOwner(com.jetbrains.python.codeInsight.controlflow.ScopeOwner) Scope(com.jetbrains.python.codeInsight.dataflow.scope.Scope)

Example 15 with Instruction

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;
}
Also used : Instruction(com.intellij.codeInsight.controlflow.Instruction)

Aggregations

Instruction (com.intellij.codeInsight.controlflow.Instruction)33 ReadWriteInstruction (com.jetbrains.python.codeInsight.controlflow.ReadWriteInstruction)15 NotNull (org.jetbrains.annotations.NotNull)12 PsiElement (com.intellij.psi.PsiElement)10 ControlFlow (com.intellij.codeInsight.controlflow.ControlFlow)7 ArrayList (java.util.ArrayList)5 ScopeOwner (com.jetbrains.python.codeInsight.controlflow.ScopeOwner)4 Pair (com.intellij.openapi.util.Pair)3 Scope (com.jetbrains.python.codeInsight.dataflow.scope.Scope)3 Project (com.intellij.openapi.project.Project)2 TextRange (com.intellij.openapi.util.TextRange)2 PyDefUseUtil (com.jetbrains.python.refactoring.PyDefUseUtil)2 TargetElementUtil (com.intellij.codeInsight.TargetElementUtil)1 CannotCreateCodeFragmentException (com.intellij.codeInsight.codeFragment.CannotCreateCodeFragmentException)1 HighlightManager (com.intellij.codeInsight.highlighting.HighlightManager)1 Language (com.intellij.lang.Language)1 InlineActionHandler (com.intellij.lang.refactoring.InlineActionHandler)1 ApplicationManager (com.intellij.openapi.application.ApplicationManager)1 CommandProcessor (com.intellij.openapi.command.CommandProcessor)1 Logger (com.intellij.openapi.diagnostic.Logger)1