diff --git a/python/python-ast/src/com/jetbrains/python/codeInsight/dataflow/scope/ScopeUtilCore.java b/python/python-ast/src/com/jetbrains/python/codeInsight/dataflow/scope/ScopeUtilCore.java index e4459f12c903..1902daa908ed 100644 --- a/python/python-ast/src/com/jetbrains/python/codeInsight/dataflow/scope/ScopeUtilCore.java +++ b/python/python-ast/src/com/jetbrains/python/codeInsight/dataflow/scope/ScopeUtilCore.java @@ -1,12 +1,13 @@ package com.jetbrains.python.codeInsight.dataflow.scope; +import com.intellij.extapi.psi.StubBasedPsiElementBase; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; import com.intellij.psi.StubBasedPsiElement; import com.intellij.psi.stubs.StubElement; import com.intellij.psi.util.CachedValueProvider; import com.intellij.psi.util.CachedValuesManager; import com.intellij.psi.util.PsiModificationTracker; -import com.intellij.psi.util.PsiTreeUtil; import com.jetbrains.python.ast.*; import com.jetbrains.python.ast.controlFlow.AstScopeOwner; import org.jetbrains.annotations.ApiStatus; @@ -33,18 +34,23 @@ public final class ScopeUtilCore { final PsiElement context = element.getContext(); return context instanceof AstScopeOwner ? (AstScopeOwner)context : getScopeOwner(context); } - if (element instanceof StubBasedPsiElement) { - final StubElement stub = ((StubBasedPsiElement)element).getStub(); + if (element instanceof StubBasedPsiElement stubBasedElement) { + final StubElement stub = stubBasedElement.getStub(); if (stub != null) { - StubElement parentStub = stub.getParentStub(); - while (parentStub != null) { - final PsiElement parent = parentStub.getPsi(); - if (parent instanceof AstScopeOwner) { - return (AstScopeOwner)parent; - } - parentStub = parentStub.getParentStub(); + AstScopeOwner firstOwner = stub.getParentStubOfType(AstScopeOwner.class); + AstScopeOwner nextOwner; + if (firstOwner != null && !(firstOwner instanceof PsiFile)) { + StubElement firstOwnerStub = ((StubBasedPsiElementBase)firstOwner).getStub(); + assert firstOwnerStub != null; + nextOwner = firstOwnerStub.getParentStubOfType(AstScopeOwner.class); } - return null; + else { + nextOwner = null; + } + if (stub.getParentStubOfType(PyAstDecoratorList.class) != null) { + return nextOwner; + } + return firstOwner; } } return CachedValuesManager.getCachedValue(element, () -> CachedValueProvider.Result @@ -59,7 +65,7 @@ public final class ScopeUtilCore { } final AstScopeOwner nextOwner = getParentOfType(firstOwner, AstScopeOwner.class); // References in decorator expressions are resolved outside of the function (if the lambda is not inside the decorator) - final PyAstElement decoratorAncestor = getParentOfType(element, PyAstDecorator.class); + final PyAstElement decoratorAncestor = getParentOfType(element, PyAstDecorator.class, false); if (decoratorAncestor != null && !isAncestor(decoratorAncestor, firstOwner, true)) { return nextOwner; } @@ -67,7 +73,7 @@ public final class ScopeUtilCore { * References in default values are resolved outside of the function (if the lambda is not inside the default value). * Annotations of parameters are resolved outside of the function if the function doesn't have type parameters list */ - final PyAstNamedParameter parameterAncestor = getParentOfType(element, PyAstNamedParameter.class); + final PyAstNamedParameter parameterAncestor = getParentOfType(element, PyAstNamedParameter.class, false); if (parameterAncestor != null && !isAncestor(parameterAncestor, firstOwner, true)) { final PyAstExpression defaultValue = parameterAncestor.getDefaultValue(); final PyAstAnnotation annotation = parameterAncestor.getAnnotation();