Search in sources :

Example 26 with ScopeOwner

use of com.jetbrains.python.codeInsight.controlflow.ScopeOwner 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 27 with ScopeOwner

use of com.jetbrains.python.codeInsight.controlflow.ScopeOwner in project intellij-community by JetBrains.

the class PyNamedParameterImpl method collectUsedAttributes.

@NotNull
private Set<String> collectUsedAttributes(@NotNull final TypeEvalContext context) {
    final Set<String> result = new LinkedHashSet<>();
    final ScopeOwner owner = ScopeUtil.getScopeOwner(this);
    final String name = getName();
    if (owner != null && name != null) {
        owner.accept(new PyRecursiveElementVisitor() {

            @Override
            public void visitPyElement(PyElement node) {
                if (node instanceof ScopeOwner && node != owner) {
                    return;
                }
                if (node instanceof PyQualifiedExpression) {
                    final PyQualifiedExpression expr = (PyQualifiedExpression) node;
                    final PyExpression qualifier = expr.getQualifier();
                    if (qualifier != null) {
                        final String attributeName = expr.getReferencedName();
                        final PyExpression referencedExpr = node instanceof PyBinaryExpression && PyNames.isRightOperatorName(attributeName) ? ((PyBinaryExpression) node).getRightExpression() : qualifier;
                        if (referencedExpr != null) {
                            final PsiReference ref = referencedExpr.getReference();
                            if (ref != null && ref.isReferenceTo(PyNamedParameterImpl.this)) {
                                if (attributeName != null && !result.contains(attributeName)) {
                                    result.add(attributeName);
                                }
                            }
                        }
                    } else {
                        final PsiReference ref = expr.getReference();
                        if (ref != null && ref.isReferenceTo(PyNamedParameterImpl.this)) {
                            StreamEx.of(getParametersByCallArgument(expr, context)).nonNull().map(context::getType).select(PyStructuralType.class).forEach(type -> result.addAll(type.getAttributeNames()));
                        }
                    }
                }
                super.visitPyElement(node);
            }

            @Override
            public void visitPyIfStatement(PyIfStatement node) {
                final PyExpression ifCondition = node.getIfPart().getCondition();
                if (ifCondition != null) {
                    ifCondition.accept(this);
                }
                for (PyIfPart part : node.getElifParts()) {
                    final PyExpression elseIfCondition = part.getCondition();
                    if (elseIfCondition != null) {
                        elseIfCondition.accept(this);
                    }
                }
            }

            @Override
            public void visitPyCallExpression(PyCallExpression node) {
                Optional.ofNullable(node.getCallee()).filter(callee -> "len".equals(callee.getName())).map(PyExpression::getReference).map(PsiReference::resolve).filter(element -> PyBuiltinCache.getInstance(element).isBuiltin(element)).ifPresent(callable -> {
                    final PyReferenceExpression argument = node.getArgument(0, PyReferenceExpression.class);
                    if (argument != null && argument.getReference().isReferenceTo(PyNamedParameterImpl.this)) {
                        result.add(PyNames.LEN);
                    }
                });
                super.visitPyCallExpression(node);
            }

            @Override
            public void visitPyForStatement(PyForStatement node) {
                Optional.of(node.getForPart()).map(PyForPart::getSource).map(PyExpression::getReference).filter(reference -> reference.isReferenceTo(PyNamedParameterImpl.this)).ifPresent(reference -> result.add(PyNames.ITER));
                super.visitPyForStatement(node);
            }
        });
    }
    return result;
}
Also used : PyNames(com.jetbrains.python.PyNames) java.util(java.util) PythonDocumentationProvider(com.jetbrains.python.documentation.PythonDocumentationProvider) ScopeUtil(com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil) SearchScope(com.intellij.psi.search.SearchScope) ContainerUtil(com.intellij.util.containers.ContainerUtil) PyElementTypes(com.jetbrains.python.PyElementTypes) PythonDialectsTokenSetProvider(com.jetbrains.python.PythonDialectsTokenSetProvider) PyNamedParameterStub(com.jetbrains.python.psi.stubs.PyNamedParameterStub) LocalSearchScope(com.intellij.psi.search.LocalSearchScope) ItemPresentation(com.intellij.navigation.ItemPresentation) PsiTreeUtil(com.intellij.psi.util.PsiTreeUtil) com.jetbrains.python.psi(com.jetbrains.python.psi) com.jetbrains.python.psi.types(com.jetbrains.python.psi.types) PyTypingTypeProvider(com.jetbrains.python.codeInsight.typing.PyTypingTypeProvider) PlatformIcons(com.intellij.util.PlatformIcons) Extensions(com.intellij.openapi.extensions.Extensions) IncorrectOperationException(com.intellij.util.IncorrectOperationException) IStubElementType(com.intellij.psi.stubs.IStubElementType) PyTokenTypes(com.jetbrains.python.PyTokenTypes) PyResolveContext(com.jetbrains.python.psi.resolve.PyResolveContext) Collectors(java.util.stream.Collectors) ASTNode(com.intellij.lang.ASTNode) Nullable(org.jetbrains.annotations.Nullable) StreamEx(one.util.streamex.StreamEx) Processor(com.intellij.util.Processor) Pair(com.intellij.openapi.util.Pair) ScopeOwner(com.jetbrains.python.codeInsight.controlflow.ScopeOwner) com.intellij.psi(com.intellij.psi) NotNull(org.jetbrains.annotations.NotNull) Ref(com.intellij.openapi.util.Ref) javax.swing(javax.swing) ScopeOwner(com.jetbrains.python.codeInsight.controlflow.ScopeOwner) NotNull(org.jetbrains.annotations.NotNull)

Example 28 with ScopeOwner

use of com.jetbrains.python.codeInsight.controlflow.ScopeOwner in project intellij-community by JetBrains.

the class AbstractPythonLegacyTestRunConfiguration method getRefactoringElementListener.

@Override
public RefactoringElementListener getRefactoringElementListener(PsiElement element) {
    if (element instanceof PsiDirectory) {
        VirtualFile vFile = ((PsiDirectory) element).getVirtualFile();
        if ((myTestType == TestType.TEST_FOLDER && pathsEqual(vFile, myFolderName)) || pathsEqual(vFile, getWorkingDirectory())) {
            return new RefactoringElementAdapter() {

                @Override
                protected void elementRenamedOrMoved(@NotNull PsiElement newElement) {
                    String newPath = FileUtil.toSystemDependentName(((PsiDirectory) newElement).getVirtualFile().getPath());
                    setWorkingDirectory(newPath);
                    if (myTestType == TestType.TEST_FOLDER) {
                        myFolderName = newPath;
                    }
                }

                @Override
                public void undoElementMovedOrRenamed(@NotNull PsiElement newElement, @NotNull String oldQualifiedName) {
                    final String systemDependant = FileUtil.toSystemDependentName(oldQualifiedName);
                    setWorkingDirectory(systemDependant);
                    if (myTestType == TestType.TEST_FOLDER) {
                        myFolderName = systemDependant;
                    }
                }
            };
        }
        return null;
    }
    if (myTestType == TestType.TEST_FOLDER) {
        return null;
    }
    File scriptFile = new File(myScriptName);
    if (!scriptFile.isAbsolute()) {
        scriptFile = new File(getWorkingDirectory(), myScriptName);
    }
    PsiFile containingFile = element.getContainingFile();
    VirtualFile vFile = containingFile == null ? null : containingFile.getVirtualFile();
    if (vFile != null && Comparing.equal(new File(vFile.getPath()).getAbsolutePath(), scriptFile.getAbsolutePath())) {
        if (element instanceof PsiFile) {
            return new RefactoringElementAdapter() {

                @Override
                protected void elementRenamedOrMoved(@NotNull PsiElement newElement) {
                    VirtualFile virtualFile = ((PsiFile) newElement).getVirtualFile();
                    if (virtualFile != null) {
                        myScriptName = FileUtil.toSystemDependentName(virtualFile.getPath());
                    }
                }

                @Override
                public void undoElementMovedOrRenamed(@NotNull PsiElement newElement, @NotNull String oldQualifiedName) {
                    myScriptName = FileUtil.toSystemDependentName(oldQualifiedName);
                }
            };
        }
        if (element instanceof PyClass && (myTestType == TestType.TEST_CLASS || myTestType == TestType.TEST_METHOD) && Comparing.equal(((PyClass) element).getName(), myClassName)) {
            return new RefactoringElementAdapter() {

                @Override
                protected void elementRenamedOrMoved(@NotNull PsiElement newElement) {
                    myClassName = ((PyClass) newElement).getName();
                }

                @Override
                public void undoElementMovedOrRenamed(@NotNull PsiElement newElement, @NotNull String oldQualifiedName) {
                    myClassName = oldQualifiedName;
                }
            };
        }
        if (element instanceof PyFunction && Comparing.equal(((PyFunction) element).getName(), myMethodName)) {
            ScopeOwner scopeOwner = PsiTreeUtil.getParentOfType(element, ScopeOwner.class);
            if ((myTestType == TestType.TEST_FUNCTION && scopeOwner instanceof PyFile) || (myTestType == TestType.TEST_METHOD && scopeOwner instanceof PyClass && Comparing.equal(scopeOwner.getName(), myClassName))) {
                return new RefactoringElementAdapter() {

                    @Override
                    protected void elementRenamedOrMoved(@NotNull PsiElement newElement) {
                        myMethodName = ((PyFunction) newElement).getName();
                    }

                    @Override
                    public void undoElementMovedOrRenamed(@NotNull PsiElement newElement, @NotNull String oldQualifiedName) {
                        final int methodIdx = oldQualifiedName.indexOf("#") + 1;
                        if (methodIdx > 0 && methodIdx < oldQualifiedName.length()) {
                            myMethodName = oldQualifiedName.substring(methodIdx);
                        }
                    }
                };
            }
        }
    }
    return null;
}
Also used : VirtualFile(com.intellij.openapi.vfs.VirtualFile) PyClass(com.jetbrains.python.psi.PyClass) PyFile(com.jetbrains.python.psi.PyFile) NotNull(org.jetbrains.annotations.NotNull) ScopeOwner(com.jetbrains.python.codeInsight.controlflow.ScopeOwner) PyFunction(com.jetbrains.python.psi.PyFunction) PsiDirectory(com.intellij.psi.PsiDirectory) PsiFile(com.intellij.psi.PsiFile) PyFile(com.jetbrains.python.psi.PyFile) VirtualFile(com.intellij.openapi.vfs.VirtualFile) PsiFile(com.intellij.psi.PsiFile) File(java.io.File) PsiElement(com.intellij.psi.PsiElement) RefactoringElementAdapter(com.intellij.refactoring.listeners.RefactoringElementAdapter)

Example 29 with ScopeOwner

use of com.jetbrains.python.codeInsight.controlflow.ScopeOwner in project intellij-community by JetBrains.

the class PyUnreachableCodeInspection method hasAnyInterruptedControlFlowPaths.

public static boolean hasAnyInterruptedControlFlowPaths(@NotNull PsiElement element) {
    final ScopeOwner owner = ScopeUtil.getScopeOwner(element);
    if (owner != null) {
        final ControlFlow flow = ControlFlowCache.getControlFlow(owner);
        final Instruction[] instructions = flow.getInstructions();
        final int start = ControlFlowUtil.findInstructionNumberByElement(instructions, element);
        if (start >= 0) {
            final Ref<Boolean> resultRef = Ref.create(false);
            ControlFlowUtil.iteratePrev(start, instructions, instruction -> {
                if (instruction.allPred().isEmpty() && !isFirstInstruction(instruction)) {
                    resultRef.set(true);
                    return ControlFlowUtil.Operation.BREAK;
                }
                return ControlFlowUtil.Operation.NEXT;
            });
            return resultRef.get();
        }
    }
    return false;
}
Also used : ScopeOwner(com.jetbrains.python.codeInsight.controlflow.ScopeOwner) Instruction(com.intellij.codeInsight.controlflow.Instruction) ControlFlow(com.intellij.codeInsight.controlflow.ControlFlow)

Example 30 with ScopeOwner

use of com.jetbrains.python.codeInsight.controlflow.ScopeOwner in project intellij-community by JetBrains.

the class AddGlobalQuickFix method applyFix.

public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) {
    PsiElement problemElt = descriptor.getPsiElement();
    if (problemElt instanceof PyReferenceExpression) {
        final PyReferenceExpression expression = (PyReferenceExpression) problemElt;
        final String name = expression.getReferencedName();
        final ScopeOwner owner = PsiTreeUtil.getParentOfType(problemElt, ScopeOwner.class);
        assert owner instanceof PyClass || owner instanceof PyFunction : "Add global quickfix is available only inside class or function, but applied for " + owner;
        final Ref<Boolean> added = new Ref<>(false);
        owner.accept(new PyRecursiveElementVisitor() {

            @Override
            public void visitElement(PsiElement element) {
                if (!added.get()) {
                    super.visitElement(element);
                }
            }

            @Override
            public void visitPyGlobalStatement(final PyGlobalStatement node) {
                if (!added.get()) {
                    node.addGlobal(name);
                    added.set(true);
                }
            }
        });
        if (added.get()) {
            return;
        }
        final PyGlobalStatement globalStatement = PyElementGenerator.getInstance(project).createFromText(LanguageLevel.getDefault(), PyGlobalStatement.class, "global " + name);
        final PyStatementList statementList;
        boolean hasDocString = false;
        if (owner instanceof PyClass) {
            statementList = ((PyClass) owner).getStatementList();
            if (((PyClass) owner).getDocStringExpression() != null)
                hasDocString = true;
        } else {
            statementList = ((PyFunction) owner).getStatementList();
            if (((PyFunction) owner).getDocStringExpression() != null)
                hasDocString = true;
        }
        PyStatement first = statementList.getStatements()[0];
        if (hasDocString)
            first = statementList.getStatements()[1];
        statementList.addBefore(globalStatement, first);
    }
}
Also used : ScopeOwner(com.jetbrains.python.codeInsight.controlflow.ScopeOwner) Ref(com.intellij.openapi.util.Ref) PsiElement(com.intellij.psi.PsiElement)

Aggregations

ScopeOwner (com.jetbrains.python.codeInsight.controlflow.ScopeOwner)51 PsiElement (com.intellij.psi.PsiElement)25 Nullable (org.jetbrains.annotations.Nullable)18 NotNull (org.jetbrains.annotations.NotNull)14 Pair (com.intellij.openapi.util.Pair)6 QualifiedName (com.intellij.psi.util.QualifiedName)6 ArrayList (java.util.ArrayList)6 Instruction (com.intellij.codeInsight.controlflow.Instruction)4 TextRange (com.intellij.openapi.util.TextRange)4 PsiFile (com.intellij.psi.PsiFile)4 Scope (com.jetbrains.python.codeInsight.dataflow.scope.Scope)4 List (java.util.List)4 LookupElement (com.intellij.codeInsight.lookup.LookupElement)3 Project (com.intellij.openapi.project.Project)3 Ref (com.intellij.openapi.util.Ref)3 PsiLanguageInjectionHost (com.intellij.psi.PsiLanguageInjectionHost)3 GlobalSearchScope (com.intellij.psi.search.GlobalSearchScope)3 TypeEvalContext (com.jetbrains.python.psi.types.TypeEvalContext)3 CannotCreateCodeFragmentException (com.intellij.codeInsight.codeFragment.CannotCreateCodeFragmentException)2 ASTNode (com.intellij.lang.ASTNode)2