Fixed non-deterministic detection of unresolved attribute of named tuple defined in other file

This commit is contained in:
Andrey Vlasovskikh
2013-01-14 21:23:22 +04:00
parent 154d1b1daa
commit f233414cfc
2 changed files with 57 additions and 5 deletions
@@ -11,6 +11,7 @@ import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.PyBuiltinCache;
import com.jetbrains.python.psi.impl.PyQualifiedName;
import com.jetbrains.python.psi.impl.PyTypeProvider;
import com.jetbrains.python.psi.resolve.PyResolveContext;
import com.jetbrains.python.psi.resolve.QualifiedNameFinder;
import com.jetbrains.python.psi.types.*;
import org.jetbrains.annotations.NotNull;
@@ -41,11 +42,23 @@ public class PyStdlibTypeProvider extends PyTypeProviderBase {
@Override
public PyType getReferenceType(@NotNull PsiElement referenceTarget, @NotNull TypeEvalContext context, @Nullable PsiElement anchor) {
if (referenceTarget instanceof PyFunction &&
PyNames.NAMEDTUPLE.equals(((PyFunction) referenceTarget).getName()) &&
PyNames.COLLECTIONS_PY.equals(referenceTarget.getContainingFile().getName()) &&
anchor instanceof PyCallExpression) {
return PyNamedTupleType.fromCall((PyCallExpression)anchor);
if (referenceTarget instanceof PyTargetExpression) {
final PyTargetExpression target = (PyTargetExpression)referenceTarget;
final PyQualifiedName calleeName = target.getCalleeName();
if (calleeName != null && PyNames.NAMEDTUPLE.equals(calleeName.toString())) {
// TODO: Create stubs for namedtuple for preventing switch from stub to AST
final PyExpression value = target.findAssignedValue();
if (value instanceof PyCallExpression) {
final PyCallExpression call = (PyCallExpression)value;
final PyCallExpression.PyMarkedCallee callee = call.resolveCallee(PyResolveContext.noImplicits());
if (callee != null) {
final Callable callable = callee.getCallable();
if (PyNames.COLLECTIONS_PY.equals(callable.getContainingFile().getName())) {
return PyNamedTupleType.fromCall(call);
}
}
}
}
}
return null;
}
@@ -0,0 +1,39 @@
package com.jetbrains.python.inspections;
import com.intellij.testFramework.LightProjectDescriptor;
import com.jetbrains.python.fixtures.PyTestCase;
import com.jetbrains.python.psi.LanguageLevel;
import org.jetbrains.annotations.NotNull;
/**
* @author vlan
*/
public class Py3UnresolvedReferencesInspectionTest extends PyTestCase {
private static final String TEST_DIRECTORY = "inspections/PyUnresolvedReferencesInspection3K/";
@Override
protected LightProjectDescriptor getProjectDescriptor() {
return ourPy3Descriptor;
}
private void doMultiFileTest(@NotNull final String filename, @NotNull LanguageLevel level) {
runWithLanguageLevel(level, new Runnable() {
@Override
public void run() {
final String testName = getTestName(false);
myFixture.copyDirectoryToProject(TEST_DIRECTORY + testName, "");
myFixture.configureFromTempProjectFile(filename);
myFixture.enableInspections(PyUnresolvedReferencesInspection.class);
myFixture.checkHighlighting(true, false, false);
}
});
}
private void doMultiFileTest(@NotNull String filename) {
doMultiFileTest(filename, LanguageLevel.PYTHON33);
}
public void testNamedTupleStub() {
doMultiFileTest("a.py");
}
}