From 229e65fd121e043f778c8bcf41c06f1ca15362c3 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Thu, 26 Aug 2010 18:46:58 +0400 Subject: [PATCH] to avoid unnecessary tree loading in Django code, when the value assigned to a target expression is a call, store the callee qualified name in stubs --- .../python/psi/PyFileElementType.java | 2 +- .../python/psi/PyTargetExpression.java | 9 ++++ .../src/com/jetbrains/python/psi/PyUtil.java | 6 +-- .../python/psi/impl/PyQualifiedName.java | 4 ++ .../psi/impl/PyTargetExpressionImpl.java | 22 ++++++++- .../stubs/PyTargetExpressionElementType.java | 45 ++++++++++--------- .../stubs/PyTargetExpressionStubImpl.java | 11 ++++- .../psi/stubs/PyTargetExpressionStub.java | 28 ++++++++++++ python/testData/stubs/StubStructure.py | 1 + .../com/jetbrains/python/PyStubsTest.java | 2 +- 10 files changed, 101 insertions(+), 29 deletions(-) diff --git a/python/src/com/jetbrains/python/psi/PyFileElementType.java b/python/src/com/jetbrains/python/psi/PyFileElementType.java index 8d21f7b90d74..51e59d3b032d 100644 --- a/python/src/com/jetbrains/python/psi/PyFileElementType.java +++ b/python/src/com/jetbrains/python/psi/PyFileElementType.java @@ -41,7 +41,7 @@ public class PyFileElementType extends IStubFileElementType { @Override public int getStubVersion() { - return 27; + return 28; } @Override diff --git a/python/src/com/jetbrains/python/psi/PyTargetExpression.java b/python/src/com/jetbrains/python/psi/PyTargetExpression.java index 222c4d0b4d86..7e1fc6e8c308 100644 --- a/python/src/com/jetbrains/python/psi/PyTargetExpression.java +++ b/python/src/com/jetbrains/python/psi/PyTargetExpression.java @@ -27,6 +27,15 @@ public interface PyTargetExpression extends PyQualifiedExpression, PsiNamedEleme @Nullable PyQualifiedName getAssignedQName(); + /** + * If the value assigned to the target expression is a call, returns the (unqualified and unresolved) name of the + * callee. Otherwise, returns null. + * + * @return the name of the callee or null if the assigned value is not a call. + */ + @Nullable + PyQualifiedName getCalleeName(); + @NotNull PsiReference getReference(); } diff --git a/python/src/com/jetbrains/python/psi/PyUtil.java b/python/src/com/jetbrains/python/psi/PyUtil.java index af98cef66bd6..ca2ca23cabbb 100644 --- a/python/src/com/jetbrains/python/psi/PyUtil.java +++ b/python/src/com/jetbrains/python/psi/PyUtil.java @@ -669,10 +669,10 @@ public class PyUtil { } @Nullable - public static PyExpression getKeywordArgument(PyCallExpressionImpl expr, String keyword) { + public static PyExpression getKeywordArgument(PyCallExpression expr, String keyword) { for (PyExpression arg : expr.getArguments()) { - if (arg instanceof PyKeywordArgumentImpl) { - PyKeywordArgumentImpl kwarg = (PyKeywordArgumentImpl)arg; + if (arg instanceof PyKeywordArgument) { + PyKeywordArgument kwarg = (PyKeywordArgument)arg; if (keyword.equals(kwarg.getKeyword())) { return kwarg.getValueExpression(); } diff --git a/python/src/com/jetbrains/python/psi/impl/PyQualifiedName.java b/python/src/com/jetbrains/python/psi/impl/PyQualifiedName.java index b9843ddacca3..a5ca920c63cf 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyQualifiedName.java +++ b/python/src/com/jetbrains/python/psi/impl/PyQualifiedName.java @@ -85,6 +85,10 @@ public class PyQualifiedName { return true; } + public boolean endsWith(@NotNull String suffix) { + return suffix.equals(getLastComponent()); + } + public static void serialize(@Nullable PyQualifiedName qName, StubOutputStream dataStream) throws IOException { if (qName == null) { dataStream.writeVarInt(0); diff --git a/python/src/com/jetbrains/python/psi/impl/PyTargetExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyTargetExpressionImpl.java index e8f7e9ae9a1d..58c0dee54e02 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyTargetExpressionImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyTargetExpressionImpl.java @@ -214,12 +214,32 @@ public class PyTargetExpressionImpl extends PyPresentableElementImpl implements PyTargetExpressionStub { private final String myName; + private final InitializerType myInitializerType; private final PyQualifiedName myInitializer; private final PropertyStubStorage myPropertyPack; @@ -21,13 +22,17 @@ public class PyTargetExpressionStubImpl extends StubBase imp public PyTargetExpressionStubImpl(String name, PropertyStubStorage propertyPack, StubElement parent) { super(parent, PyElementTypes.TARGET_EXPRESSION); myName = name; + myInitializerType = InitializerType.Property; myInitializer = null; myPropertyPack = propertyPack; } - public PyTargetExpressionStubImpl(final String name, final PyQualifiedName initializer, final StubElement parentStub) { + public PyTargetExpressionStubImpl(final String name, final InitializerType initializerType, + final PyQualifiedName initializer, final StubElement parentStub) { super(parentStub, PyElementTypes.TARGET_EXPRESSION); myName = name; + assert initializerType != InitializerType.Property; + myInitializerType = initializerType; myInitializer = initializer; myPropertyPack = null; } @@ -36,6 +41,10 @@ public class PyTargetExpressionStubImpl extends StubBase imp return myName; } + public InitializerType getInitializerType() { + return myInitializerType; + } + public PyQualifiedName getInitializer() { return myInitializer; } diff --git a/python/src/com/jetbrains/python/psi/stubs/PyTargetExpressionStub.java b/python/src/com/jetbrains/python/psi/stubs/PyTargetExpressionStub.java index f1c7d25288c5..3745f0d951b1 100644 --- a/python/src/com/jetbrains/python/psi/stubs/PyTargetExpressionStub.java +++ b/python/src/com/jetbrains/python/psi/stubs/PyTargetExpressionStub.java @@ -9,6 +9,34 @@ import org.jetbrains.annotations.Nullable; * @author yole */ public interface PyTargetExpressionStub extends NamedStub { + enum InitializerType { + ReferenceExpression(1), + CallExpression(2), + Property(3), + Other(0); + + private int myIndex; + + InitializerType(int index) { + myIndex = index; + } + + public int getIndex() { + return myIndex; + } + + public static InitializerType fromIndex(int index) { + switch (index) { + case 1: return ReferenceExpression; + case 2: return CallExpression; + case 3: return Property; + default: return Other; + } + } + } + + InitializerType getInitializerType(); + @Nullable PyQualifiedName getInitializer(); diff --git a/python/testData/stubs/StubStructure.py b/python/testData/stubs/StubStructure.py index 4c1e5728bc00..5db705ce8bfe 100644 --- a/python/testData/stubs/StubStructure.py +++ b/python/testData/stubs/StubStructure.py @@ -3,6 +3,7 @@ def deco(fun): class FooClass: staticField = deco + globs = globals() def __init__(self): self.instanceField = 2 diff --git a/python/testSrc/com/jetbrains/python/PyStubsTest.java b/python/testSrc/com/jetbrains/python/PyStubsTest.java index 5bcf1ab28ba5..23fd7a866f95 100644 --- a/python/testSrc/com/jetbrains/python/PyStubsTest.java +++ b/python/testSrc/com/jetbrains/python/PyStubsTest.java @@ -50,7 +50,7 @@ public class PyStubsTest extends PyLightFixtureTestCase { assertEquals("StubStructure.FooClass", pyClass.getQualifiedName()); final List attrs = pyClass.getClassAttributes(); - assertEquals(1, attrs.size()); + assertEquals(2, attrs.size()); assertEquals("staticField", attrs.get(0).getName()); assertTrue(attrs.get(0).getAssignedQName().matches("deco"));