From da0aadddc176e1c8ad9ee77685db9bc153f77c25 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 17 Aug 2010 20:17:31 +0400 Subject: [PATCH] propagate type eval context via resolve context (PY-1565) --- .../python/psi/impl/PyCallExpressionImpl.java | 3 +- .../psi/impl/PyQualifiedReferenceImpl.java | 2 +- .../python/psi/resolve/PyResolveContext.java | 17 ++++ .../testData/completion/chainedCall.after.py | 8 ++ python/testData/completion/chainedCall.py | 8 ++ .../python/PythonCompletionTest.java | 77 ++++++++++--------- 6 files changed, 77 insertions(+), 38 deletions(-) create mode 100644 python/testData/completion/chainedCall.after.py create mode 100644 python/testData/completion/chainedCall.py diff --git a/python/src/com/jetbrains/python/psi/impl/PyCallExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyCallExpressionImpl.java index 52161d1c19da..a89e98679826 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyCallExpressionImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyCallExpressionImpl.java @@ -79,7 +79,8 @@ public class PyCallExpressionImpl extends PyElementImpl implements PyCallExpress } } // normal cases - ResolveResult[] targets = ((PyReferenceExpression)callee).getReference(PyResolveContext.noImplicits()).multiResolve(false); + final PyResolveContext resolveContext = PyResolveContext.noImplicits().withTypeEvalContext(context); + ResolveResult[] targets = ((PyReferenceExpression)callee).getReference(resolveContext).multiResolve(false); if (targets.length > 0) { PsiElement target = targets[0].getElement(); if (target == null) { diff --git a/python/src/com/jetbrains/python/psi/impl/PyQualifiedReferenceImpl.java b/python/src/com/jetbrains/python/psi/impl/PyQualifiedReferenceImpl.java index 4dd88ec6011c..501543ad7664 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyQualifiedReferenceImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyQualifiedReferenceImpl.java @@ -39,7 +39,7 @@ public class PyQualifiedReferenceImpl extends PyReferenceImpl { assert qualifier != null; // regular attributes - PyType qualifierType = qualifier.getType(TypeEvalContext.fast()); + PyType qualifierType = qualifier.getType(myContext.getTypeEvalContext()); // is it a class-private name qualified by a different class? if (PyUtil.isClassPrivateName(referencedName) && qualifierType instanceof PyClassType) { final List match = SyntaxMatchers.DEEP_IN_METHOD.search(qualifier); diff --git a/python/src/com/jetbrains/python/psi/resolve/PyResolveContext.java b/python/src/com/jetbrains/python/psi/resolve/PyResolveContext.java index 01968c9d2d9e..dea2f1225360 100644 --- a/python/src/com/jetbrains/python/psi/resolve/PyResolveContext.java +++ b/python/src/com/jetbrains/python/psi/resolve/PyResolveContext.java @@ -1,13 +1,22 @@ package com.jetbrains.python.psi.resolve; +import com.jetbrains.python.psi.types.TypeEvalContext; + /** * @author yole */ public class PyResolveContext { private final boolean myAllowImplicits; + private final TypeEvalContext myTypeEvalContext; private PyResolveContext(boolean allowImplicits) { myAllowImplicits = allowImplicits; + myTypeEvalContext = null; + } + + private PyResolveContext(boolean allowImplicits, TypeEvalContext typeEvalContext) { + myAllowImplicits = allowImplicits; + myTypeEvalContext = typeEvalContext; } public boolean allowImplicits() { @@ -25,6 +34,14 @@ public class PyResolveContext { return ourNoImplicitsContext; } + public PyResolveContext withTypeEvalContext(TypeEvalContext context) { + return new PyResolveContext(myAllowImplicits, context); + } + + public TypeEvalContext getTypeEvalContext() { + return myTypeEvalContext != null ? myTypeEvalContext : TypeEvalContext.fast(); + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/python/testData/completion/chainedCall.after.py b/python/testData/completion/chainedCall.after.py new file mode 100644 index 000000000000..b501018e8eeb --- /dev/null +++ b/python/testData/completion/chainedCall.after.py @@ -0,0 +1,8 @@ +class X(object): + def testChain(self): + return X() + +def g(): + return X() + +g().testChain().testChain() \ No newline at end of file diff --git a/python/testData/completion/chainedCall.py b/python/testData/completion/chainedCall.py new file mode 100644 index 000000000000..0ae00b3bde5b --- /dev/null +++ b/python/testData/completion/chainedCall.py @@ -0,0 +1,8 @@ +class X(object): + def testChain(self): + return X() + +def g(): + return X() + +g().testChain(). \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/PythonCompletionTest.java b/python/testSrc/com/jetbrains/python/PythonCompletionTest.java index 640906da6a6a..1e63891d4e48 100644 --- a/python/testSrc/com/jetbrains/python/PythonCompletionTest.java +++ b/python/testSrc/com/jetbrains/python/PythonCompletionTest.java @@ -11,122 +11,122 @@ import java.util.Arrays; public class PythonCompletionTest extends PyLightFixtureTestCase { - private void doTest() throws Exception { + private void doTest() { final String testName = "completion/" + getTestName(true); myFixture.configureByFile(testName + ".py"); myFixture.completeBasic(); myFixture.checkResultByFile(testName + ".after.py"); } - public void testLocalVar() throws Exception { + public void testLocalVar() { doTest(); } - public void testSelfMethod() throws Exception { + public void testSelfMethod() { doTest(); } - public void testSelfField() throws Exception { + public void testSelfField() { doTest(); } - public void testFuncParams() throws Exception { + public void testFuncParams() { doTest(); } - public void testFuncParamsStar() throws Exception { + public void testFuncParamsStar() { doTest(); } - public void testInitParams() throws Exception { + public void testInitParams() { doTest(); } - public void testSuperInitParams() throws Exception { // PY-505 + public void testSuperInitParams() { // PY-505 doTest(); } - public void testSuperInitKwParams() throws Exception { // PY-778 + public void testSuperInitKwParams() { // PY-778 doTest(); } - public void testPredefinedMethodName() throws Exception { + public void testPredefinedMethodName() { doTest(); } - public void testPredefinedMethodNot() throws Exception { + public void testPredefinedMethodNot() { doTest(); } - public void testKeywordAfterComment() throws Exception { // PY-697 + public void testKeywordAfterComment() { // PY-697 doTest(); } - public void testClassPrivate() throws Exception { + public void testClassPrivate() { doTest(); } - public void testClassPrivateNotInherited() throws Exception { + public void testClassPrivateNotInherited() { doTest(); } - public void testClassPrivateNotPublic() throws Exception { + public void testClassPrivateNotPublic() { doTest(); } - public void testTwoUnderscores() throws Exception { + public void testTwoUnderscores() { doTest(); } - public void testOneUnderscore() throws Exception { + public void testOneUnderscore() { doTest(); } - public void testTwoUnderscoresNotOne() throws Exception { + public void testTwoUnderscoresNotOne() { doTest(); } - public void testKwParamsInCodeUsage() throws Exception { //PY-1002 + public void testKwParamsInCodeUsage() { //PY-1002 doTest(); } - public void testKwParamsInCodeGetUsage() throws Exception { //PY-1002 + public void testKwParamsInCodeGetUsage() { //PY-1002 doTest(); } - public void testSuperInitKwParamsNotOnlySelfAndKwArgs() throws Exception { //PY-1050 + public void testSuperInitKwParamsNotOnlySelfAndKwArgs() { //PY-1050 doTest(); } - public void testSuperInitKwParamsNoCompletion() throws Exception { + public void testSuperInitKwParamsNoCompletion() { doTest(); } - public void testIsInstance() throws Exception { + public void testIsInstance() { doTest(); } - public void testIsInstanceAssert() throws Exception { + public void testIsInstanceAssert() { doTest(); } - public void testIsInstanceTuple() throws Exception { + public void testIsInstanceTuple() { doTest(); } - public void testPropertyParens() throws Exception { // PY-1037 + public void testPropertyParens() { // PY-1037 doTest(); } - public void testClassNameFromVarName() throws Exception { + public void testClassNameFromVarName() { doTest(); } - public void testPropertyType() throws Exception { + public void testPropertyType() { doTest(); } - public void testSeenMembers() throws Exception { // PY-1181 + public void testSeenMembers() { // PY-1181 final String testName = "completion/" + getTestName(true); myFixture.configureByFile(testName + ".py"); final LookupElement[] elements = myFixture.completeBasic(); @@ -134,14 +134,14 @@ public class PythonCompletionTest extends PyLightFixtureTestCase { assertEquals("children", elements [0].getLookupString()); } - public void testImportModule() throws Exception { + public void testImportModule() { final String testName = "completion/" + getTestName(true); myFixture.configureByFiles(testName + ".py", "completion/someModule.py"); myFixture.completeBasic(); myFixture.checkResultByFile(testName + ".after.py"); } - public void testPy255() throws Exception { + public void testPy255() { final String dirname = "completion/"; final String testName = dirname + "moduleClass"; myFixture.configureByFiles(testName + ".py", dirname + "__init__.py"); @@ -150,7 +150,7 @@ public class PythonCompletionTest extends PyLightFixtureTestCase { myFixture.checkResultByFile(testName + ".after.py"); } - public void testPy874() throws Exception { + public void testPy874() { final String dirname = "completion/"; final String testName = dirname + "py874"; myFixture.configureByFile(testName + ".py"); @@ -159,21 +159,26 @@ public class PythonCompletionTest extends PyLightFixtureTestCase { myFixture.checkResultByFile(testName + ".after.py"); } - public void testClassMethod() throws Exception { // PY-833 + public void testClassMethod() { // PY-833 doTest(); } - public void testStarImport() throws Exception { + public void testStarImport() { myFixture.configureByFiles("completion/starImport/starImport.py", "completion/starImport/importSource.py"); myFixture.completeBasic(); assertSameElements(myFixture.getLookupElementStrings(), Arrays.asList("my_foo", "my_bar")); } - public void testSlots() throws Exception { // PY-1211 + public void testSlots() { // PY-1211 doTest(); } - public void testReturnType() throws Exception { + public void testReturnType() { doTest(); } + + public void testChainedCall() { // PY-1565 + doTest(); + } + } \ No newline at end of file