mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Resolve __class__ to the corresponding PyClass PSI element
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -371,6 +371,11 @@ public class PyBuiltinCache {
|
||||
return getObjectType("staticmethod");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PyClassType getTypeType() {
|
||||
return getObjectType("type");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param target an element to check.
|
||||
* @return true iff target is inside the __builtins__.py
|
||||
|
||||
@@ -246,19 +246,17 @@ public class PyReferenceImpl implements PsiReferenceEx, PsiPolyVariantReference
|
||||
LanguageLevel.forElement(myElement).isAtLeast(LanguageLevel.PYTHON30)) {
|
||||
final PyFunction containingFunction = PsiTreeUtil.getParentOfType(myElement, PyFunction.class);
|
||||
|
||||
if (containingFunction != null && containingFunction.getContainingClass() != null) {
|
||||
final PyResolveProcessor processor = new PyResolveProcessor(referencedName);
|
||||
PyResolveUtil.scopeCrawlUp(processor, myElement, referencedName, containingFunction);
|
||||
if (containingFunction != null) {
|
||||
final PyClass containingClass = containingFunction.getContainingClass();
|
||||
|
||||
if (processor.getElements().isEmpty()) {
|
||||
ret.addAll(
|
||||
Optional
|
||||
.ofNullable(PyBuiltinCache.getInstance(myElement).getObjectType())
|
||||
.map(type -> type.resolveMember(PyNames.__CLASS__, myElement, AccessDirection.of(myElement), myContext))
|
||||
.orElse(Collections.emptyList())
|
||||
);
|
||||
if (containingClass != null) {
|
||||
final PyResolveProcessor processor = new PyResolveProcessor(referencedName);
|
||||
PyResolveUtil.scopeCrawlUp(processor, myElement, referencedName, containingFunction);
|
||||
|
||||
return ret;
|
||||
if (processor.getElements().isEmpty()) {
|
||||
ret.add(new RatedResolveResult(RatedResolveResult.RATE_NORMAL, containingClass));
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,24 +196,8 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
|
||||
|
||||
classMember = resolveClassMember(myClass, myIsDefinition, name, location);
|
||||
|
||||
if (PyNames.__CLASS__.equals(name) && !isBuiltin()) {
|
||||
final LanguageLevel languageLevel = LanguageLevel.forElement(myClass);
|
||||
final boolean py2K = languageLevel.isOlderThan(LanguageLevel.PYTHON30);
|
||||
final boolean newStyleClass = myClass.isNewStyleClass(resolveContext.getTypeEvalContext());
|
||||
|
||||
final boolean py2KNewStyleClass = py2K && newStyleClass;
|
||||
final boolean py2KOldStyleClass = py2K && !newStyleClass;
|
||||
|
||||
if (myIsDefinition && py2KOldStyleClass && classMember == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
if (myIsDefinition && (py2KNewStyleClass || !py2K) || !myIsDefinition && py2KOldStyleClass) {
|
||||
return Optional
|
||||
.ofNullable(PyBuiltinCache.getInstance(myClass).getObjectType())
|
||||
.map(type -> type.resolveMember(name, location, direction, resolveContext))
|
||||
.orElse(Collections.emptyList());
|
||||
}
|
||||
if (PyNames.__CLASS__.equals(name)) {
|
||||
return resolveDunderClass(context, classMember);
|
||||
}
|
||||
|
||||
if (classMember != null) {
|
||||
@@ -321,6 +305,36 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
|
||||
return resultRef;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private List<? extends RatedResolveResult> resolveDunderClass(@NotNull TypeEvalContext context, @Nullable PsiElement classMember) {
|
||||
final boolean newStyleClass = myClass.isNewStyleClass(context);
|
||||
|
||||
if (!myIsDefinition) {
|
||||
if (newStyleClass && classMember != null) {
|
||||
return ResolveResultList.to(classMember);
|
||||
}
|
||||
|
||||
return ResolveResultList.to(
|
||||
myClass.getAncestorClasses(context)
|
||||
.stream()
|
||||
.filter(cls -> !PyUtil.isObjectClass(cls))
|
||||
.<PsiElement>map(cls -> cls.findClassAttribute(PyNames.__CLASS__, true, context))
|
||||
.filter(target -> target != null)
|
||||
.findFirst()
|
||||
.orElse(myClass)
|
||||
);
|
||||
}
|
||||
|
||||
if (LanguageLevel.forElement(myClass).isOlderThan(LanguageLevel.PYTHON30) && !newStyleClass) {
|
||||
return ResolveResultList.to(classMember);
|
||||
}
|
||||
|
||||
return Optional
|
||||
.ofNullable(PyBuiltinCache.getInstance(myClass).getTypeType())
|
||||
.map(typeType -> ResolveResultList.to(typeType.getPyClass()))
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PyClassLikeType getMetaClassType(@NotNull final TypeEvalContext context, boolean inherited) {
|
||||
|
||||
@@ -67,8 +67,7 @@ public class Py3ResolveTest extends PyResolveTestCase {
|
||||
|
||||
// PY-13734
|
||||
public void testImplicitDunderClass() {
|
||||
final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.__CLASS__);
|
||||
assertEquals(PyBuiltinCache.BUILTIN_FILE_3K, expression.getContainingFile().getName());
|
||||
assertResolvesTo(PyClass.class, "A");
|
||||
}
|
||||
|
||||
public void testImplicitDunderDoc() {
|
||||
@@ -86,8 +85,7 @@ public class Py3ResolveTest extends PyResolveTestCase {
|
||||
|
||||
// PY-13734
|
||||
public void testImplicitDunderClassWithClassAttr() {
|
||||
final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.__CLASS__);
|
||||
assertEquals(PyBuiltinCache.BUILTIN_FILE_3K, expression.getContainingFile().getName());
|
||||
assertResolvesTo(PyClass.class, "A");
|
||||
}
|
||||
|
||||
public void testImplicitDunderDocWithClassAttr() {
|
||||
@@ -105,8 +103,7 @@ public class Py3ResolveTest extends PyResolveTestCase {
|
||||
|
||||
// PY-13734
|
||||
public void testImplicitDunderClassWithInheritedClassAttr() {
|
||||
final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.__CLASS__);
|
||||
assertEquals(PyBuiltinCache.BUILTIN_FILE_3K, expression.getContainingFile().getName());
|
||||
assertResolvesTo(PyClass.class, "B");
|
||||
}
|
||||
|
||||
public void testImplicitDunderDocWithInheritedClassAttr() {
|
||||
@@ -124,8 +121,7 @@ public class Py3ResolveTest extends PyResolveTestCase {
|
||||
|
||||
// PY-13734
|
||||
public void testInstanceDunderClass() {
|
||||
final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.__CLASS__);
|
||||
assertEquals(PyBuiltinCache.BUILTIN_FILE_3K, expression.getContainingFile().getName());
|
||||
assertResolvesTo(PyClass.class, "A");
|
||||
}
|
||||
|
||||
public void testInstanceDunderDoc() {
|
||||
@@ -216,8 +212,7 @@ public class Py3ResolveTest extends PyResolveTestCase {
|
||||
|
||||
// PY-13734
|
||||
public void testTypeDunderClass() {
|
||||
final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.__CLASS__);
|
||||
assertEquals(PyBuiltinCache.BUILTIN_FILE_3K, expression.getContainingFile().getName());
|
||||
assertResolvesTo(PyClass.class, "type");
|
||||
}
|
||||
|
||||
public void testTypeDunderDoc() {
|
||||
@@ -236,8 +231,7 @@ public class Py3ResolveTest extends PyResolveTestCase {
|
||||
|
||||
// PY-13734
|
||||
public void testTypeDunderClassWithClassAttr() {
|
||||
final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.__CLASS__);
|
||||
assertEquals(PyBuiltinCache.BUILTIN_FILE_3K, expression.getContainingFile().getName());
|
||||
assertResolvesTo(PyClass.class, "type");
|
||||
}
|
||||
|
||||
public void testTypeDunderDocWithClassAttr() {
|
||||
@@ -266,8 +260,7 @@ public class Py3ResolveTest extends PyResolveTestCase {
|
||||
|
||||
// PY-13734
|
||||
public void testTypeDunderClassWithInheritedClassAttr() {
|
||||
final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.__CLASS__);
|
||||
assertEquals(PyBuiltinCache.BUILTIN_FILE_3K, expression.getContainingFile().getName());
|
||||
assertResolvesTo(PyClass.class, "type");
|
||||
}
|
||||
|
||||
public void testTypeDunderDocWithInheritedClassAttr() {
|
||||
|
||||
@@ -833,8 +833,7 @@ public class PyResolveTest extends PyResolveTestCase {
|
||||
|
||||
// PY-13734
|
||||
public void testInstanceDunderClass() {
|
||||
final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.__CLASS__);
|
||||
assertEquals(PyBuiltinCache.BUILTIN_FILE, expression.getContainingFile().getName());
|
||||
assertResolvesTo(PyClass.class, "A");
|
||||
}
|
||||
|
||||
public void testInstanceDunderDoc() {
|
||||
@@ -852,8 +851,7 @@ public class PyResolveTest extends PyResolveTestCase {
|
||||
|
||||
// PY-13734
|
||||
public void testInstanceDunderClassNewStyleClass() {
|
||||
final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.__CLASS__);
|
||||
assertEquals(PyBuiltinCache.BUILTIN_FILE, expression.getContainingFile().getName());
|
||||
assertResolvesTo(PyClass.class, "A");
|
||||
}
|
||||
|
||||
public void testInstanceDunderDocNewStyleClass() {
|
||||
@@ -872,8 +870,7 @@ public class PyResolveTest extends PyResolveTestCase {
|
||||
|
||||
// PY-13734
|
||||
public void testInstanceDunderClassWithClassAttr() {
|
||||
final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.__CLASS__);
|
||||
assertEquals(PyBuiltinCache.BUILTIN_FILE, expression.getContainingFile().getName());
|
||||
assertResolvesTo(PyClass.class, "A");
|
||||
}
|
||||
|
||||
public void testInstanceDunderDocWithClassAttr() {
|
||||
@@ -992,8 +989,7 @@ public class PyResolveTest extends PyResolveTestCase {
|
||||
|
||||
// PY-13734
|
||||
public void testTypeDunderClassNewStyleClass() {
|
||||
final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.__CLASS__);
|
||||
assertEquals(PyBuiltinCache.BUILTIN_FILE, expression.getContainingFile().getName());
|
||||
assertResolvesTo(PyClass.class, "type");
|
||||
}
|
||||
|
||||
public void testTypeDunderDocNewStyleClass() {
|
||||
@@ -1045,8 +1041,7 @@ public class PyResolveTest extends PyResolveTestCase {
|
||||
|
||||
// PY-13734
|
||||
public void testTypeDunderClassWithClassAttrNewStyleClass() {
|
||||
final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.__CLASS__);
|
||||
assertEquals(PyBuiltinCache.BUILTIN_FILE, expression.getContainingFile().getName());
|
||||
assertResolvesTo(PyClass.class, "type");
|
||||
}
|
||||
|
||||
public void testTypeDunderDocWithClassAttrNewStyleClass() {
|
||||
@@ -1075,8 +1070,7 @@ public class PyResolveTest extends PyResolveTestCase {
|
||||
|
||||
// PY-13734
|
||||
public void testTypeDunderClassWithInheritedClassAttr() {
|
||||
final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.__CLASS__);
|
||||
assertEquals(PyBuiltinCache.BUILTIN_FILE, expression.getContainingFile().getName());
|
||||
assertResolvesTo(PyClass.class, "type");
|
||||
}
|
||||
|
||||
public void testTypeDunderDocWithInheritedClassAttr() {
|
||||
|
||||
Reference in New Issue
Block a user