mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Don't resolve forward outgoing references in class except cython and pyi (PY-26368)
This commit is contained in:
+5
-15
@@ -1,18 +1,4 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
// 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.psi.resolve;
|
||||
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
@@ -34,4 +20,8 @@ public interface PyReferenceResolveProvider {
|
||||
*/
|
||||
@NotNull
|
||||
List<RatedResolveResult> resolveName(@NotNull PyQualifiedExpression element, @NotNull TypeEvalContext context);
|
||||
|
||||
default boolean allowsForwardOutgoingReferencesInClass(@NotNull PyQualifiedExpression element) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -712,6 +712,7 @@
|
||||
<typeProvider implementation="com.jetbrains.python.pyi.PyiTypeProvider"/>
|
||||
<pyModuleMembersProvider implementation="com.jetbrains.python.pyi.PyiModuleMembersProvider"/>
|
||||
<pyClassMembersProvider implementation="com.jetbrains.python.pyi.PyiClassMembersProvider"/>
|
||||
<pyReferenceResolveProvider implementation="com.jetbrains.python.pyi.PyiReferenceResolveProvider"/>
|
||||
<visitorFilter language="PythonStub" implementationClass="com.jetbrains.python.pyi.PyiVisitorFilter"/>
|
||||
<inspectionExtension implementation="com.jetbrains.python.pyi.PyiInspectionExtension"/>
|
||||
<inspectionExtension implementation="com.jetbrains.python.codeInsight.typing.PyTypingInspectionExtension"/>
|
||||
|
||||
@@ -1,18 +1,4 @@
|
||||
/*
|
||||
* Copyright 2000-2017 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
// 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.psi.impl.references;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
@@ -297,6 +283,17 @@ public class PyReferenceImpl implements PsiReferenceEx, PsiPolyVariantReference
|
||||
}
|
||||
}
|
||||
else if (referenceOwner != null) {
|
||||
if (!allowsForwardOutgoingReferencesInClass(myElement)) {
|
||||
final PyClass outermostNestedClass = outermostNestedClass(referenceOwner, resolvedOwner);
|
||||
|
||||
if (outermostNestedClass != null) {
|
||||
final List<Instruction> instructions =
|
||||
PyDefUseUtil.getLatestDefs(resolvedOwner, referencedName, outermostNestedClass, false, true);
|
||||
|
||||
return resolveToLatestDefs(instructions, outermostNestedClass, referencedName, typeEvalContext);
|
||||
}
|
||||
}
|
||||
|
||||
final Scope referenceScope = ControlFlowCache.getScope(referenceOwner);
|
||||
if (referenceScope.containsDeclaration(referencedName)) {
|
||||
unreachableLocalDeclaration = true;
|
||||
@@ -360,6 +357,25 @@ public class PyReferenceImpl implements PsiReferenceEx, PsiPolyVariantReference
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean allowsForwardOutgoingReferencesInClass(@NotNull PyQualifiedExpression element) {
|
||||
return ContainerUtil.exists(Extensions.getExtensions(PyReferenceResolveProvider.EP_NAME),
|
||||
provider -> provider.allowsForwardOutgoingReferencesInClass(element));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PyClass outermostNestedClass(@NotNull ScopeOwner referenceOwner, @NotNull ScopeOwner resolvedOwner) {
|
||||
PyClass current = PyUtil.as(referenceOwner, PyClass.class);
|
||||
ScopeOwner outer = ScopeUtil.getScopeOwner(current);
|
||||
|
||||
while (outer != resolvedOwner) {
|
||||
current = PyUtil.as(outer, PyClass.class);
|
||||
if (current == null) return null;
|
||||
outer = ScopeUtil.getScopeOwner(outer);
|
||||
}
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private ResolveResultList resolveByOverridingReferenceResolveProviders() {
|
||||
final ResolveResultList results = new ResolveResultList();
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
// 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.pyi
|
||||
|
||||
import com.jetbrains.python.psi.PyQualifiedExpression
|
||||
import com.jetbrains.python.psi.resolve.PyReferenceResolveProvider
|
||||
import com.jetbrains.python.psi.resolve.RatedResolveResult
|
||||
import com.jetbrains.python.psi.types.TypeEvalContext
|
||||
|
||||
class PyiReferenceResolveProvider: PyReferenceResolveProvider {
|
||||
|
||||
override fun resolveName(element: PyQualifiedExpression, context: TypeEvalContext): List<RatedResolveResult> = emptyList()
|
||||
|
||||
override fun allowsForwardOutgoingReferencesInClass(element: PyQualifiedExpression): Boolean {
|
||||
return PyiUtil.isInsideStubAnnotation(element)
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
class A1:
|
||||
foo = <error descr="Unresolved reference 'B1'">B1</error>()
|
||||
|
||||
class B1:
|
||||
pass
|
||||
|
||||
|
||||
class A21:
|
||||
class A22:
|
||||
bar = <error descr="Unresolved reference 'B2'">B2</error>()
|
||||
|
||||
class B2:
|
||||
pass
|
||||
|
||||
|
||||
class A31:
|
||||
def baz(self):
|
||||
class A32:
|
||||
egg = B3()
|
||||
|
||||
class B3:
|
||||
pass
|
||||
+5
@@ -643,6 +643,11 @@ public class PyUnresolvedReferencesInspectionTest extends PyInspectionTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
// PY-26368
|
||||
public void testForwardReferencesInClassBody() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Class<? extends PyInspection> getInspectionClass() {
|
||||
|
||||
Reference in New Issue
Block a user