diff --git a/python/src/META-INF/python-plugin-common.xml b/python/src/META-INF/python-plugin-common.xml
index 904c36f72c2e..5397623c773e 100644
--- a/python/src/META-INF/python-plugin-common.xml
+++ b/python/src/META-INF/python-plugin-common.xml
@@ -42,6 +42,7 @@
+
diff --git a/python/src/com/jetbrains/python/psi/impl/PyQualifiedReferenceImpl.java b/python/src/com/jetbrains/python/psi/impl/PyQualifiedReferenceImpl.java
index d2b005619951..198c761ea77b 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyQualifiedReferenceImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyQualifiedReferenceImpl.java
@@ -8,9 +8,9 @@ import com.intellij.util.ProcessingContext;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.patterns.SyntaxMatchers;
import com.jetbrains.python.psi.resolve.*;
+import com.jetbrains.python.psi.stubs.PyClassNameIndexInsensitive;
import com.jetbrains.python.psi.stubs.PyFunctionNameIndex;
import com.jetbrains.python.psi.types.*;
-import com.jetbrains.python.toolbox.Maybe;
import org.jetbrains.annotations.NotNull;
import java.util.*;
@@ -156,6 +156,21 @@ public class PyQualifiedReferenceImpl extends PyReferenceImpl {
return qualifierType.getCompletionVariants(myElement, ctx);
}
}
+ return getUntypedVariants();
+ }
+
+ private Object[] getUntypedVariants() {
+ final PyExpression qualifierElement = myElement.getQualifier();
+ if (qualifierElement instanceof PyReferenceExpression) {
+ PyReferenceExpression qualifier = (PyReferenceExpression)qualifierElement;
+ if (qualifier.getQualifier() == null) {
+ final String className = qualifier.getText();
+ final Collection classes = PyClassNameIndexInsensitive.find(className, getElement().getProject());
+ if (classes.size() == 1) {
+ return new PyClassType(classes.iterator().next(), false).getCompletionVariants(myElement, new ProcessingContext());
+ }
+ }
+ }
return ArrayUtil.EMPTY_OBJECT_ARRAY;
}
diff --git a/python/src/com/jetbrains/python/psi/impl/stubs/PyClassElementType.java b/python/src/com/jetbrains/python/psi/impl/stubs/PyClassElementType.java
index e7fb6c76d1f1..d13613bd7104 100644
--- a/python/src/com/jetbrains/python/psi/impl/stubs/PyClassElementType.java
+++ b/python/src/com/jetbrains/python/psi/impl/stubs/PyClassElementType.java
@@ -14,6 +14,7 @@ import com.jetbrains.python.psi.PyStubElementType;
import com.jetbrains.python.psi.impl.PyClassImpl;
import com.jetbrains.python.psi.impl.PyQualifiedName;
import com.jetbrains.python.psi.stubs.PyClassNameIndex;
+import com.jetbrains.python.psi.stubs.PyClassNameIndexInsensitive;
import com.jetbrains.python.psi.stubs.PyClassStub;
import com.jetbrains.python.psi.stubs.PySuperClassIndex;
@@ -74,6 +75,7 @@ public class PyClassElementType extends PyStubElementType
final String name = stub.getName();
if (name != null) {
sink.occurrence(PyClassNameIndex.KEY, name);
+ sink.occurrence(PyClassNameIndexInsensitive.KEY, name.toLowerCase());
}
for(PyQualifiedName s: stub.getSuperClasses()) {
if (s != null) {
diff --git a/python/src/com/jetbrains/python/psi/stubs/PyClassNameIndexInsensitive.java b/python/src/com/jetbrains/python/psi/stubs/PyClassNameIndexInsensitive.java
new file mode 100644
index 000000000000..d5972dea8cac
--- /dev/null
+++ b/python/src/com/jetbrains/python/psi/stubs/PyClassNameIndexInsensitive.java
@@ -0,0 +1,27 @@
+package com.jetbrains.python.psi.stubs;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.search.ProjectScope;
+import com.intellij.psi.stubs.StringStubIndexExtension;
+import com.intellij.psi.stubs.StubIndex;
+import com.intellij.psi.stubs.StubIndexKey;
+import com.intellij.util.io.KeyDescriptor;
+import com.jetbrains.python.psi.PyClass;
+
+import java.util.Collection;
+
+/**
+ * @author yole
+ */
+public class PyClassNameIndexInsensitive extends StringStubIndexExtension {
+ public static final StubIndexKey KEY = StubIndexKey.createIndexKey("Py.class.shortNameInsensitive");
+
+ @Override
+ public StubIndexKey getKey() {
+ return KEY;
+ }
+
+ public static Collection find(String name, Project project) {
+ return StubIndex.getInstance().get(KEY, name.toLowerCase(), project, ProjectScope.getProjectScope(project));
+ }
+}
diff --git a/python/testData/completion/classNameFromVarName.after.py b/python/testData/completion/classNameFromVarName.after.py
new file mode 100644
index 000000000000..750ff360bf11
--- /dev/null
+++ b/python/testData/completion/classNameFromVarName.after.py
@@ -0,0 +1,5 @@
+class Product:
+ def doStuff(self): pass
+
+def foo(product):
+ product.doStuff()
\ No newline at end of file
diff --git a/python/testData/completion/classNameFromVarName.py b/python/testData/completion/classNameFromVarName.py
new file mode 100644
index 000000000000..366c9a90df3a
--- /dev/null
+++ b/python/testData/completion/classNameFromVarName.py
@@ -0,0 +1,5 @@
+class Product:
+ def doStuff(self): pass
+
+def foo(product):
+ product.doS
\ 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 b95bc16fa227..c4dbc7c3419d 100644
--- a/python/testSrc/com/jetbrains/python/PythonCompletionTest.java
+++ b/python/testSrc/com/jetbrains/python/PythonCompletionTest.java
@@ -111,6 +111,10 @@ public class PythonCompletionTest extends PyLightFixtureTestCase {
doTest();
}
+ public void testClassNameFromVarName() throws Exception {
+ doTest();
+ }
+
public void testImportModule() throws Exception {
final String testName = "completion/" + getTestName(true);
myFixture.configureByFiles(testName + ".py", "completion/someModule.py");