diff --git a/python/src/com/jetbrains/python/psi/impl/PyBuiltinCache.java b/python/src/com/jetbrains/python/psi/impl/PyBuiltinCache.java index f2eb8f6a1605..37676b041853 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyBuiltinCache.java +++ b/python/src/com/jetbrains/python/psi/impl/PyBuiltinCache.java @@ -28,7 +28,10 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; -import java.util.*; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; /** * Provides access to Python builtins via skeletons. diff --git a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java index bb5bd4c4e10c..6ecd7815459c 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java @@ -207,31 +207,26 @@ public class PyClassImpl extends PyPresentableElementImpl implement return Collections.emptyList(); } - List stubSuperClasses = resolveSuperClassesFromStub(); - if (stubSuperClasses != null) { - return stubSuperClasses; - } - - PsiElement[] superClassElements = getSuperClassElements(); - if (superClassElements.length > 0) { - List result = new ArrayList(); - // maybe a bare old-style class? - // TODO: depend on language version: py3k does not do old style classes - PsiElement paren = PsiTreeUtil.getChildOfType(this, PyArgumentList.class).getFirstChild(); // no NPE, we always have the par expr - if (paren != null && "(".equals(paren.getText())) { // "()" after class name, it's new style - for (PsiElement element : superClassElements) { - if (element instanceof PyClass) { - result.add((PyClass)element); - } + List superClasses = resolveSuperClassesFromStub(); + if (superClasses == null) { + superClasses = new ArrayList(); + PsiElement[] superClassElements = getSuperClassElements(); + for (PsiElement element : superClassElements) { + if (element instanceof PyClass) { + superClasses.add((PyClass)element); } } - else if (!PyBuiltinCache.BUILTIN_FILE.equals(getContainingFile().getName())) { // old-style *and* not builtin object() - PyClass oldstyler = PyBuiltinCache.getInstance(this).getClass(PyNames.FAKE_OLD_BASE); - if (oldstyler != null) result.add(oldstyler); - } - return result; } - return Collections.emptyList(); + + if (superClasses.size() == 0 && !PyBuiltinCache.getInstance(this).hasInBuiltins(this)) { + String implicitSuperclassName = LanguageLevel.forElement(this).isPy3K() ? PyNames.OBJECT : PyNames.FAKE_OLD_BASE; + PyClass implicitSuperclass = PyBuiltinCache.getInstance(this).getClass(implicitSuperclassName); + if (implicitSuperclass != null) { + superClasses.add(implicitSuperclass); + } + } + + return superClasses; } @Nullable diff --git a/python/testData/resolve/ObjectMethods.py b/python/testData/resolve/ObjectMethods.py new file mode 100644 index 000000000000..42f002e1d41d --- /dev/null +++ b/python/testData/resolve/ObjectMethods.py @@ -0,0 +1,9 @@ +class A: + x = 1 + y = 1 + +class B(A): + def foo(self): + self.__repr__() +# + \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/Py3ResolveTest.java b/python/testSrc/com/jetbrains/python/Py3ResolveTest.java new file mode 100644 index 000000000000..c9d268b80603 --- /dev/null +++ b/python/testSrc/com/jetbrains/python/Py3ResolveTest.java @@ -0,0 +1,43 @@ +package com.jetbrains.python; + +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiReference; +import com.intellij.testFramework.LightProjectDescriptor; +import com.jetbrains.python.fixtures.PyResolveTestCase; +import com.jetbrains.python.psi.LanguageLevel; +import com.jetbrains.python.psi.PyFunction; +import com.jetbrains.python.psi.impl.PythonLanguageLevelPusher; + +/** + * @author yole + */ +public class Py3ResolveTest extends PyResolveTestCase { + @Override + protected LightProjectDescriptor getProjectDescriptor() { + return ourPy3Descriptor; + } + + @Override + protected PsiElement doResolve() { + myFixture.configureByFile("resolve/" + getTestName(false) + ".py"); + int offset = findMarkerOffset(myFixture.getFile()); + final PsiReference ref = myFixture.getFile().findReferenceAt(offset); + return ref.resolve(); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + PythonLanguageLevelPusher.setForcedLanguageLevel(myFixture.getProject(), LanguageLevel.PYTHON31); + } + + @Override + protected void tearDown() throws Exception { + PythonLanguageLevelPusher.setForcedLanguageLevel(myFixture.getProject(), null); + super.tearDown(); + } + + public void testObjectMethods() { // PY-1494 + assertResolvesTo(PyFunction.class, "__repr__"); + } +} diff --git a/python/testSrc/com/jetbrains/python/PyPropertyTestSuite.java b/python/testSrc/com/jetbrains/python/PyPropertyTestSuite.java index ec5dda652158..5babec54f0bd 100644 --- a/python/testSrc/com/jetbrains/python/PyPropertyTestSuite.java +++ b/python/testSrc/com/jetbrains/python/PyPropertyTestSuite.java @@ -35,7 +35,6 @@ public class PyPropertyTestSuite { super.setUp(); PsiReference ref = myFixture.getReferenceAtCaretPosition("property/"+ getFileName()); final Project project = ref.getElement().getContainingFile().getProject(); - project.putUserData(PyBuiltinCache.TEST_SDK, PythonMockSdk.findOrCreate()); PythonLanguageLevelPusher.setForcedLanguageLevel(project, myLanguageLevel); PsiElement elt = ref.resolve(); assertInstanceOf(elt, PyExpression.class); diff --git a/python/testSrc/com/jetbrains/python/PyResolveTest.java b/python/testSrc/com/jetbrains/python/PyResolveTest.java index c409bb4e265a..8fecc86a1d51 100644 --- a/python/testSrc/com/jetbrains/python/PyResolveTest.java +++ b/python/testSrc/com/jetbrains/python/PyResolveTest.java @@ -1,6 +1,5 @@ package com.jetbrains.python; -import com.intellij.openapi.project.Project; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiPolyVariantReference; import com.intellij.psi.PsiReference; @@ -8,7 +7,6 @@ import com.intellij.psi.ResolveResult; import com.intellij.psi.util.PsiTreeUtil; import com.jetbrains.python.fixtures.PyResolveTestCase; import com.jetbrains.python.psi.*; -import com.jetbrains.python.psi.impl.PyBuiltinCache; import com.jetbrains.python.psi.impl.PythonLanguageLevelPusher; import com.jetbrains.python.psi.resolve.ImportedResolveResult; @@ -16,8 +14,6 @@ public class PyResolveTest extends PyResolveTestCase { @Override protected PsiElement doResolve() { myFixture.configureByFile("resolve/" + getTestName(false) + ".py"); - final Project project = myFixture.getProject(); - project.putUserData(PyBuiltinCache.TEST_SDK, PythonMockSdk.findOrCreate()); int offset = findMarkerOffset(myFixture.getFile()); final PsiReference ref = myFixture.getFile().findReferenceAt(offset); return ref.resolve(); @@ -25,8 +21,6 @@ public class PyResolveTest extends PyResolveTestCase { protected PsiElement resolve() { PsiReference ref = configureByFile("resolve/" + getTestName(false) + ".py"); - final Project project = ref.getElement().getContainingFile().getProject(); - project.putUserData(PyBuiltinCache.TEST_SDK, PythonMockSdk.findOrCreate()); // if need be: PythonLanguageLevelPusher.setForcedLanguageLevel(project, LanguageLevel.PYTHON26); return ref.resolve(); } diff --git a/python/testSrc/com/jetbrains/python/PyStubsTest.java b/python/testSrc/com/jetbrains/python/PyStubsTest.java index 2ab7f2ddf878..971109add551 100644 --- a/python/testSrc/com/jetbrains/python/PyStubsTest.java +++ b/python/testSrc/com/jetbrains/python/PyStubsTest.java @@ -15,7 +15,6 @@ import com.intellij.testFramework.TestDataPath; import com.intellij.util.indexing.FileBasedIndex; import com.jetbrains.python.fixtures.PyLightFixtureTestCase; import com.jetbrains.python.psi.*; -import com.jetbrains.python.psi.impl.PyBuiltinCache; import com.jetbrains.python.psi.impl.PyFileImpl; import com.jetbrains.python.psi.impl.PyQualifiedName; import com.jetbrains.python.psi.impl.PythonLanguageLevelPusher; @@ -42,7 +41,6 @@ public class PyStubsTest extends PyLightFixtureTestCase { final PyFile file = getTestFile(); // vfile is problematic, but we need an SDK to check builtins final Project project = file.getProject(); - project.putUserData(PyBuiltinCache.TEST_SDK, PythonMockSdk.findOrCreate()); try { PythonLanguageLevelPusher.setForcedLanguageLevel(project, LanguageLevel.PYTHON26); // we need 2.6+ for @foo.setter diff --git a/python/testSrc/com/jetbrains/python/PythonAllTestsSuite.java b/python/testSrc/com/jetbrains/python/PythonAllTestsSuite.java index 444414a50ac0..e05623eb7580 100644 --- a/python/testSrc/com/jetbrains/python/PythonAllTestsSuite.java +++ b/python/testSrc/com/jetbrains/python/PythonAllTestsSuite.java @@ -24,6 +24,7 @@ public class PythonAllTestsSuite { PythonHighlightingTest.class, PyStubsTest.class, PyResolveTest.class, + Py3ResolveTest.class, PyMultiFileResolveTest.class, PyResolveCalleeTest.class, PyAssignmentMappingTest.class, diff --git a/python/testSrc/com/jetbrains/python/PythonMockSdk.java b/python/testSrc/com/jetbrains/python/PythonMockSdk.java index 83fafe41f2e3..792c85209273 100644 --- a/python/testSrc/com/jetbrains/python/PythonMockSdk.java +++ b/python/testSrc/com/jetbrains/python/PythonMockSdk.java @@ -1,6 +1,5 @@ package com.jetbrains.python; -import com.intellij.openapi.application.PathManager; import com.intellij.openapi.projectRoots.ProjectJdkTable; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.projectRoots.SdkModificator; @@ -19,25 +18,24 @@ import java.util.List; public class PythonMockSdk { @NonNls private static final String MOCK_SDK_NAME = "Mock Python SDK"; - public static Sdk findOrCreate() { + public static Sdk findOrCreate(String version) { final List sdkList = ProjectJdkTable.getInstance().getSdksOfType(PythonSdkType.getInstance()); for (Sdk sdk : sdkList) { - if (sdk.getName().equals(MOCK_SDK_NAME)) { + if (sdk.getName().equals(MOCK_SDK_NAME + " " + version)) { return sdk; } } - return create(); + return create(version); } - public static Sdk create() { - final String version = "2.5"; // TODO: implement language level here + public static Sdk create(final String version) { final String mock_path = PythonTestUtil.getTestDataPath() + "/MockSdk" + version + "/"; String sdkHome = new File(mock_path, "bin/python"+version).getPath(); SdkType sdkType = PythonSdkType.getInstance(); - final Sdk sdk = new ProjectJdkImpl(MOCK_SDK_NAME, sdkType) { + final Sdk sdk = new ProjectJdkImpl(MOCK_SDK_NAME + " " + version, sdkType) { @Override public String getVersionString() { return "Python " + version + " Mock SDK"; diff --git a/python/testSrc/com/jetbrains/python/fixtures/PyLightFixtureTestCase.java b/python/testSrc/com/jetbrains/python/fixtures/PyLightFixtureTestCase.java index a23c9f2da831..68f30aa2a937 100644 --- a/python/testSrc/com/jetbrains/python/fixtures/PyLightFixtureTestCase.java +++ b/python/testSrc/com/jetbrains/python/fixtures/PyLightFixtureTestCase.java @@ -25,7 +25,8 @@ import org.jetbrains.annotations.Nullable; */ @TestDataPath("$CONTENT_ROOT/../testData/") public abstract class PyLightFixtureTestCase extends UsefulTestCase { - private static final PyLightProjectDescriptor ourPyDescriptor = new PyLightProjectDescriptor(); + private static final PyLightProjectDescriptor ourPyDescriptor = new PyLightProjectDescriptor("2.5"); + protected static final PyLightProjectDescriptor ourPy3Descriptor = new PyLightProjectDescriptor("3.1"); protected CodeInsightTestFixture myFixture; private static boolean ourPlatformPrefixInitialized; @@ -74,12 +75,18 @@ public abstract class PyLightFixtureTestCase extends UsefulTestCase { } protected static class PyLightProjectDescriptor implements LightProjectDescriptor { + private final String myPythonVersion; + + public PyLightProjectDescriptor(String pythonVersion) { + myPythonVersion = pythonVersion; + } + public ModuleType getModuleType() { return EmptyModuleType.getInstance(); } public Sdk getSdk() { - return PythonMockSdk.findOrCreate(); + return PythonMockSdk.findOrCreate(myPythonVersion); } public void configureModule(Module module, ModifiableRootModel model, ContentEntry contentEntry) {