Search in sources :

Example 41 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)

Example 42 with ScopeOwner

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

the class PyRenameUnresolvedRefQuickFix method applyFix.

@Override
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
    final PsiElement element = descriptor.getPsiElement();
    if (!(element instanceof PyReferenceExpression)) {
        return;
    }
    final PyReferenceExpression referenceExpression = (PyReferenceExpression) element;
    ScopeOwner parentScope = ScopeUtil.getScopeOwner(referenceExpression);
    if (parentScope == null)
        return;
    List<PyReferenceExpression> refs = collectExpressionsToRename(referenceExpression, parentScope);
    LookupElement[] items = collectLookupItems(parentScope);
    final String name = referenceExpression.getReferencedName();
    ReferenceNameExpression refExpr = new ReferenceNameExpression(items, name);
    TemplateBuilderImpl builder = (TemplateBuilderImpl) TemplateBuilderFactory.getInstance().createTemplateBuilder(parentScope);
    for (PyReferenceExpression expr : refs) {
        if (!expr.equals(referenceExpression)) {
            builder.replaceElement(expr, name, name, false);
        } else {
            builder.replaceElement(expr, name, refExpr, true);
        }
    }
    Editor editor = getEditor(project, element.getContainingFile(), parentScope.getTextRange().getStartOffset());
    if (editor != null) {
        Template template = builder.buildInlineTemplate();
        TemplateManager.getInstance(project).startTemplate(editor, template);
    }
}
Also used : ScopeOwner(com.jetbrains.python.codeInsight.controlflow.ScopeOwner) LookupElement(com.intellij.codeInsight.lookup.LookupElement) Editor(com.intellij.openapi.editor.Editor) PsiElement(com.intellij.psi.PsiElement) PyReferenceExpression(com.jetbrains.python.psi.PyReferenceExpression)

Example 43 with ScopeOwner

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

the class PyReferenceImpl method resolvesToSameLocal.

private boolean resolvesToSameLocal(PsiElement element, String elementName, ScopeOwner ourScopeOwner, ScopeOwner theirScopeOwner) {
    final PsiElement ourContainer = findContainer(getElement());
    final PsiElement theirContainer = findContainer(element);
    if (ourContainer != null) {
        if (ourContainer == theirContainer) {
            return true;
        }
        if (PsiTreeUtil.isAncestor(theirContainer, ourContainer, true)) {
            if (ourContainer instanceof PyComprehensionElement && containsDeclaration((PyComprehensionElement) ourContainer, elementName)) {
                return false;
            }
            ScopeOwner owner = ourScopeOwner;
            while (owner != theirScopeOwner && owner != null) {
                if (ControlFlowCache.getScope(owner).containsDeclaration(elementName)) {
                    return false;
                }
                owner = ScopeUtil.getScopeOwner(owner);
            }
            return true;
        }
    }
    return false;
}
Also used : ScopeOwner(com.jetbrains.python.codeInsight.controlflow.ScopeOwner)

Example 44 with ScopeOwner

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

the class PyReferenceImpl method findResolveRoof.

private PsiElement findResolveRoof(String referencedName, PsiElement realContext) {
    if (PyUtil.isClassPrivateName(referencedName)) {
        // a class-private name; limited by either class or this file
        PsiElement one = myElement;
        do {
            one = ScopeUtil.getScopeOwner(one);
        } while (one instanceof PyFunction);
        if (one instanceof PyClass) {
            PyArgumentList superClassExpressionList = ((PyClass) one).getSuperClassExpressionList();
            if (superClassExpressionList == null || !PsiTreeUtil.isAncestor(superClassExpressionList, myElement, false)) {
                return one;
            }
        }
    }
    if (myElement instanceof PyTargetExpression) {
        final ScopeOwner scopeOwner = PsiTreeUtil.getParentOfType(myElement, ScopeOwner.class);
        final Scope scope;
        if (scopeOwner != null) {
            scope = ControlFlowCache.getScope(scopeOwner);
            final String name = myElement.getName();
            if (scope.isNonlocal(name)) {
                final ScopeOwner nonlocalOwner = ScopeUtil.getDeclarationScopeOwner(myElement, referencedName);
                if (nonlocalOwner != null && !(nonlocalOwner instanceof PyFile)) {
                    return nonlocalOwner;
                }
            }
            if (!scope.isGlobal(name)) {
                return scopeOwner;
            }
        }
    }
    return realContext.getContainingFile();
}
Also used : ScopeOwner(com.jetbrains.python.codeInsight.controlflow.ScopeOwner) Scope(com.jetbrains.python.codeInsight.dataflow.scope.Scope)

Example 45 with ScopeOwner

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

the class PyReferenceImpl method isReferenceTo.

@Override
public boolean isReferenceTo(PsiElement element) {
    if (element instanceof PsiFileSystemItem) {
        // may be import via alias, so don't check if names match, do simple resolve check instead
        PsiElement resolveResult = resolve();
        if (resolveResult instanceof PyImportedModule) {
            resolveResult = resolveResult.getNavigationElement();
        }
        if (element instanceof PsiDirectory) {
            if (resolveResult instanceof PyFile) {
                final PyFile file = (PyFile) resolveResult;
                if (PyUtil.isPackage(file) && file.getContainingDirectory() == element) {
                    return true;
                }
            } else if (resolveResult instanceof PsiDirectory) {
                final PsiDirectory directory = (PsiDirectory) resolveResult;
                if (PyUtil.isPackage(directory, null) && directory == element) {
                    return true;
                }
            }
        }
        return resolveResult == element;
    }
    if (element instanceof PsiNamedElement) {
        final String elementName = ((PsiNamedElement) element).getName();
        if ((Comparing.equal(myElement.getReferencedName(), elementName) || PyNames.INIT.equals(elementName))) {
            if (!haveQualifiers(element)) {
                final ScopeOwner ourScopeOwner = ScopeUtil.getScopeOwner(getElement());
                final ScopeOwner theirScopeOwner = ScopeUtil.getScopeOwner(element);
                if (element instanceof PyParameter || element instanceof PyTargetExpression) {
                    // Check if the reference is in the same or inner scope of the element scope, not shadowed by an intermediate declaration
                    if (resolvesToSameLocal(element, elementName, ourScopeOwner, theirScopeOwner)) {
                        return true;
                    }
                }
                final PsiElement resolveResult = resolve();
                if (resolveResult == element) {
                    return true;
                }
                // we shadow their name or they shadow ours (PY-6241)
                if (resolveResult instanceof PsiNamedElement && resolveResult instanceof ScopeOwner && element instanceof ScopeOwner && theirScopeOwner == ScopeUtil.getScopeOwner(resolveResult)) {
                    return true;
                }
                if (!haveQualifiers(element) && ourScopeOwner != null && theirScopeOwner != null) {
                    if (resolvesToSameGlobal(element, elementName, ourScopeOwner, theirScopeOwner, resolveResult))
                        return true;
                }
                if (resolvesToWrapper(element, resolveResult)) {
                    return true;
                }
            }
            if (element instanceof PyExpression) {
                final PyExpression expr = (PyExpression) element;
                if (PyUtil.isClassAttribute(myElement) && (PyUtil.isClassAttribute(expr) || PyUtil.isInstanceAttribute(expr))) {
                    final PyClass c1 = PsiTreeUtil.getParentOfType(element, PyClass.class);
                    final PyClass c2 = PsiTreeUtil.getParentOfType(myElement, PyClass.class);
                    final TypeEvalContext context = myContext.getTypeEvalContext();
                    if (c1 != null && c2 != null && (c1.isSubclass(c2, context) || c2.isSubclass(c1, context))) {
                        return true;
                    }
                }
            }
        }
    }
    return false;
}
Also used : TypeEvalContext(com.jetbrains.python.psi.types.TypeEvalContext) ScopeOwner(com.jetbrains.python.codeInsight.controlflow.ScopeOwner)

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