mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-21088 Understand __all__.append() and __all__.extend()
PyCharm used to fail to statically evaluate __all__.append() calls in typing.py and concluded that since __all__ was too dynamic to analyse it was better to assume that __all__ isn't present. It affected resolving to internal module attributes not mentioned in __all__ and even led to false positives in unused locals when these internal names were imported from another module right next to star-import from the module with __all__.
This commit is contained in:
@@ -23,7 +23,6 @@ import com.intellij.lang.Language;
|
||||
import com.intellij.navigation.ItemPresentation;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.roots.ProjectFileIndex;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.RecursionManager;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
@@ -575,7 +574,24 @@ public class PyFileImpl extends PsiFileBase implements PyFile, PyExpression {
|
||||
if (callee instanceof PyQualifiedExpression) {
|
||||
final PyExpression qualifier = ((PyQualifiedExpression)callee).getQualifier();
|
||||
if (qualifier != null && PyNames.ALL.equals(qualifier.getText())) {
|
||||
// TODO handle append and extend with constant arguments here
|
||||
final String calleeName = callee.getName();
|
||||
if ("append".equals(calleeName)) {
|
||||
final PyStringLiteralExpression argument = node.getArgument(0, PyStringLiteralExpression.class);
|
||||
if (argument != null) {
|
||||
myResult.add(argument.getStringValue());
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if ("extend".equals(calleeName)) {
|
||||
final PyExpression argument = node.getArgument(0, PyExpression.class);
|
||||
if (argument != null) {
|
||||
final List<String> results = PyUtil.strListValue(argument);
|
||||
if (results != null) {
|
||||
myResult.addAll(results);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
myDynamic = true;
|
||||
}
|
||||
}
|
||||
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
from m1 import *
|
||||
|
||||
|
||||
print(internal_name)
|
||||
# <ref>
|
||||
@@ -0,0 +1,13 @@
|
||||
__all__ = [
|
||||
'foo',
|
||||
'bar'
|
||||
]
|
||||
|
||||
foo = 0
|
||||
bar = 1
|
||||
|
||||
__all__.append('quux')
|
||||
|
||||
quux = 3
|
||||
internal_name = 4
|
||||
|
||||
@@ -473,6 +473,11 @@ public class PyMultiFileResolveTest extends PyMultiFileResolveTestCase {
|
||||
assertSameElements(doMultiResolveAndGetFileUrls("pkg/__init__.py"), "pkg/mod.py");
|
||||
}
|
||||
|
||||
// PY-21088
|
||||
public void testDontResolveToMissingNameInDynamicDunderAll() {
|
||||
assertNull(doResolve());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private List<String> doMultiResolveAndGetFileUrls(@NotNull String currentFilePath) {
|
||||
myFixture.configureByFile(currentFilePath);
|
||||
|
||||
Reference in New Issue
Block a user