Reduce unstubbing while processing instance level declarations (PY-27863)

Stub->AST switch happened when passed location was inside unstubbed file.
This commit is contained in:
Semyon Proshev
2018-02-07 21:15:42 +03:00
parent 1b1899cf28
commit 57e8c38989
4 changed files with 29 additions and 6 deletions
@@ -1269,8 +1269,8 @@ public class PyClassImpl extends PyBaseElementImpl<PyClassStub> implements PyCla
@Override
public boolean processInstanceLevelDeclarations(@NotNull PsiScopeProcessor processor, @Nullable PsiElement location) {
Map<String, PyTargetExpression> declarationsInMethod = new HashMap<>();
PyFunction instanceMethod = PsiTreeUtil.getParentOfType(location, PyFunction.class);
final Map<String, PyTargetExpression> declarationsInMethod = new HashMap<>();
final PyFunction instanceMethod = PsiTreeUtil.getStubOrPsiParentOfType(location, PyFunction.class);
final PyClass containingClass = instanceMethod != null ? instanceMethod.getContainingClass() : null;
if (instanceMethod != null && containingClass != null && CompletionUtil.getOriginalElement(containingClass) == this) {
collectInstanceAttributes(instanceMethod, declarationsInMethod);
@@ -0,0 +1,3 @@
import b
b.B().some_attr
# <ref>
@@ -0,0 +1,3 @@
class B(object):
def __init__(self) -> None:
self.some_attr = unresolved
@@ -1,10 +1,7 @@
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.jetbrains.python;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiPolyVariantReference;
import com.intellij.psi.PsiReference;
import com.intellij.psi.ResolveResult;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.testFramework.UsefulTestCase;
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
@@ -14,6 +11,8 @@ import com.jetbrains.python.fixtures.PyResolveTestCase;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.PyPsiUtils;
import com.jetbrains.python.psi.resolve.ImportedResolveResult;
import com.jetbrains.python.psi.resolve.PyResolveContext;
import com.jetbrains.python.psi.types.PyClassTypeImpl;
import com.jetbrains.python.psi.types.TypeEvalContext;
public class PyResolveTest extends PyResolveTestCase {
@@ -1247,4 +1246,22 @@ public class PyResolveTest extends PyResolveTestCase {
myFixture.copyDirectoryToProject("resolve/" + getTestName(false), "");
assertResolvesTo(PyFunction.class, "append");
}
// PY-27863
public void testAttributeClassLevelAnnotation() {
myFixture.copyDirectoryToProject("resolve/" + getTestName(false), "");
final PyTargetExpression target = assertResolvesTo(PyTargetExpression.class, "some_attr");
final PsiFile file = myFixture.getFile();
final TypeEvalContext context = TypeEvalContext.codeAnalysis(myFixture.getProject(), file);
final PyResolveContext resolveContext = PyResolveContext.noImplicits().withTypeEvalContext(context);
// It's like an attempt to find type annotation for attribute on the class level.
final PyClassTypeImpl classType = new PyClassTypeImpl(target.getContainingClass(), true);
assertEmpty(classType.resolveMember(target.getReferencedName(), target, AccessDirection.READ, resolveContext, true));
assertProjectFilesNotParsed(file);
assertSdkRootsNotParsed(file);
}
}