mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-15 11:53:49 +07:00
PY-39682 Handle union types of qualifiers when deducing FQN for unresolved attributes
The underlying problem is that we started to infer a confusing union type of __init__.py modules found both in site-packages and python_stubs for such imported packages, but I want it to be addressed separately in PY-39911. GitOrigin-RevId: 053a4a092ce7fcc71d192dbaa6b1623b82472a17
This commit is contained in:
committed by
intellij-monorepo-bot
parent
d5073a50b2
commit
c955ffbcc7
@@ -661,44 +661,43 @@ abstract class PyUnresolvedReferencesVisitor extends PyInspectionVisitor {
|
||||
final String exprName = expr.getName();
|
||||
if (exprName != null) {
|
||||
if (qualifier != null) {
|
||||
final PyType type = context.getType(qualifier);
|
||||
if (type instanceof PyClassType) {
|
||||
ContainerUtil.addIfNotNull(result, extractAttributeQNameFromClassType(exprName, (PyClassType)type));
|
||||
}
|
||||
else if (type instanceof PyModuleType) {
|
||||
final PyFile file = ((PyModuleType)type).getModule();
|
||||
final QualifiedName name = QualifiedNameFinder.findCanonicalImportPath(file, element);
|
||||
if (name != null) {
|
||||
ContainerUtil.addIfNotNull(result, name.append(exprName));
|
||||
}
|
||||
}
|
||||
else if (type instanceof PyImportedModuleType) {
|
||||
final PyImportedModule module = ((PyImportedModuleType)type).getImportedModule();
|
||||
final PsiElement resolved = module.resolve();
|
||||
if (resolved != null) {
|
||||
final QualifiedName path = QualifiedNameFinder.findCanonicalImportPath(resolved, element);
|
||||
if (path != null) {
|
||||
ContainerUtil.addIfNotNull(result, path.append(exprName));
|
||||
final PyType qualifierType = context.getType(qualifier);
|
||||
PyTypeUtil.toStream(qualifierType)
|
||||
.map(type -> {
|
||||
if (type instanceof PyClassType) {
|
||||
return extractAttributeQNameFromClassType(exprName, (PyClassType)type);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (type instanceof PyFunctionType) {
|
||||
final PyCallable callable = ((PyFunctionType)type).getCallable();
|
||||
final String callableName = callable.getName();
|
||||
if (callableName != null) {
|
||||
final QualifiedName path = QualifiedNameFinder.findCanonicalImportPath(callable, element);
|
||||
if (path != null) {
|
||||
result.add(path.append(QualifiedName.fromComponents(callableName, exprName)));
|
||||
else if (type instanceof PyModuleType) {
|
||||
final PyFile file = ((PyModuleType)type).getModule();
|
||||
final QualifiedName name = QualifiedNameFinder.findCanonicalImportPath(file, element);
|
||||
if (name != null) {
|
||||
return name.append(exprName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (type instanceof PyUnionType) {
|
||||
for (PyType memberType : ((PyUnionType)type).getMembers()) {
|
||||
if (memberType instanceof PyClassType) {
|
||||
ContainerUtil.addIfNotNull(result, extractAttributeQNameFromClassType(exprName, (PyClassType)memberType));
|
||||
else if (type instanceof PyImportedModuleType) {
|
||||
final PyImportedModule module = ((PyImportedModuleType)type).getImportedModule();
|
||||
final PsiElement resolved = module.resolve();
|
||||
if (resolved != null) {
|
||||
final QualifiedName path = QualifiedNameFinder.findCanonicalImportPath(resolved, element);
|
||||
if (path != null) {
|
||||
return path.append(exprName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (type instanceof PyFunctionType) {
|
||||
final PyCallable callable = ((PyFunctionType)type).getCallable();
|
||||
final String callableName = callable.getName();
|
||||
if (callableName != null) {
|
||||
final QualifiedName path = QualifiedNameFinder.findCanonicalImportPath(callable, element);
|
||||
if (path != null) {
|
||||
return path.append(QualifiedName.fromComponents(callableName, exprName));
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
})
|
||||
.nonNull()
|
||||
.into(result);
|
||||
}
|
||||
else {
|
||||
final PsiElement parent = element.getParent();
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
import pkg
|
||||
|
||||
pkg.unresolved
|
||||
@@ -0,0 +1 @@
|
||||
from .mod import *
|
||||
@@ -828,6 +828,25 @@ public class PyUnresolvedReferencesInspectionTest extends PyInspectionTestCase {
|
||||
"a.<warning descr=\"Cannot find reference 'append' in 'None'\">append</warning>(10)");
|
||||
}
|
||||
|
||||
// PY-39682
|
||||
public void testWildcardIgnorePatternReferenceForNestedBinaryModule() {
|
||||
// TODO simplify runWithAdditionalClassEntryInSdkRoots to accept a relative path directly
|
||||
final String testDataDir = getTestDataPath() + "/" + getTestDirectoryPath();
|
||||
final VirtualFile sitePackagesDir = StandardFileSystems.local().findFileByPath(testDataDir + "/site-packages");
|
||||
final VirtualFile skeletonsDir = StandardFileSystems.local().findFileByPath(testDataDir + "/python_stubs");
|
||||
runWithAdditionalClassEntryInSdkRoots(sitePackagesDir, () -> {
|
||||
runWithAdditionalClassEntryInSdkRoots(skeletonsDir, () -> {
|
||||
myFixture.configureByFile(getTestDirectoryPath() + "/a.py");
|
||||
final PyUnresolvedReferencesInspection inspection = new PyUnresolvedReferencesInspection();
|
||||
inspection.ignoredIdentifiers.add("pkg.*");
|
||||
myFixture.enableInspections(inspection);
|
||||
myFixture.checkHighlighting(isWarning(), isInfo(), isWeakWarning());
|
||||
assertSdkRootsNotParsed(myFixture.getFile());
|
||||
assertProjectFilesNotParsed(myFixture.getFile());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Class<? extends PyInspection> getInspectionClass() {
|
||||
|
||||
Reference in New Issue
Block a user