PY-14216 Code completion for Model.objects does not work with Django 1.7.x
authorIlya.Kazakevich <Ilya.Kazakevich@jetbrains.com>
Wed, 31 Dec 2014 13:38:08 +0000 (16:38 +0300)
committerIlya.Kazakevich <Ilya.Kazakevich@jetbrains.com>
Wed, 31 Dec 2014 13:38:08 +0000 (16:38 +0300)
PY-14714 Unresolved attribute reference 'objects' for class 'Foo'

Docs added

python/psi-api/src/com/jetbrains/python/psi/PyFunction.java
python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java

index f1a2499c89075b69f9b642fb5eec025c691c0b56..7337c756eb885f5a5bd8dc3213f58babe060be4d 100644 (file)
@@ -104,8 +104,6 @@ extends
   @Nullable
   PyAnnotation getAnnotation();
 
-  // TODO: Doc
-  //
 
   /**
    * Searches for function attributes.
index 79fdf3c51c3d869a049410648996e2c37a1c72ab..d0f7ccd45f08df9606394cc5d974c5f9c69ad79b 100644 (file)
@@ -146,13 +146,16 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
     }
   }
 
+  /**
+   * @param providerToSkip provider that should not be used (use it to prevent recursion). Pass null to use any provider.
+   */
   @Nullable
   public List<? extends RatedResolveResult> doResolveMember(@NotNull String name,
                                                             @Nullable PyExpression location,
                                                             @NotNull AccessDirection direction,
                                                             @NotNull PyResolveContext resolveContext,
                                                             boolean inherited,
-                                                            @Nullable PyClassMembersProvider providerToSkip) {
+                                                            @Nullable final PyClassMembersProvider providerToSkip) {
     final TypeEvalContext context = resolveContext.getTypeEvalContext();
     PsiElement classMember =
       resolveByOverridingMembersProviders(this, name, location,
@@ -348,10 +351,13 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
     return null;
   }
 
+  /**
+   * @param providerToSkip provider that should not be used (use it to prevent recursion). Pass null to use any provider.
+   */
   @Nullable
   private static PsiElement resolveByMembersProviders(PyClassType aClass, String name,
                                                       @Nullable PsiElement location,
-                                                      @Nullable PyClassMembersProvider providerToSkip) {
+                                                      @Nullable final PyClassMembersProvider providerToSkip) {
     for (PyClassMembersProvider provider : Extensions.getExtensions(PyClassMembersProvider.EP_NAME)) {
       if (provider == providerToSkip) {
         continue;
@@ -363,9 +369,12 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
     return null;
   }
 
+  /**
+   * @param providerToSkip provider that should not be used (use it to prevent recursion). Pass null to use any provider.
+   */
   @Nullable
   private static PsiElement resolveByOverridingMembersProviders(PyClassType aClass, String name, @Nullable PsiElement location,
-                                                                @Nullable PyClassMembersProvider providerToSkip) {
+                                                                @Nullable final PyClassMembersProvider providerToSkip) {
     for (PyClassMembersProvider provider : Extensions.getExtensions(PyClassMembersProvider.EP_NAME)) {
       if (provider instanceof PyOverridingClassMembersProvider && provider != providerToSkip) {
         final PsiElement resolveResult = provider.resolveMember(aClass, name, location);
@@ -376,11 +385,14 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
     return null;
   }
 
+  /**
+   * @param providerToSkip provider that should not be used (use it to prevent recursion). Pass null to use any provider.
+   */
   @Nullable
   private static PsiElement resolveByOverridingAncestorsMembersProviders(PyClassType type, String name, @Nullable PyExpression location,
-                                                                         @Nullable PyClassMembersProvider providerToSkip) {
+                                                                         @Nullable final PyClassMembersProvider providerToSkip) {
     for (PyClassMembersProvider provider : Extensions.getExtensions(PyClassMembersProvider.EP_NAME)) {
-      if (provider instanceof PyOverridingAncestorsClassMembersProvider && !(provider == providerToSkip)) {
+      if (provider instanceof PyOverridingAncestorsClassMembersProvider && provider != providerToSkip) {
         final PsiElement resolveResult = provider.resolveMember(type, name, location);
         if (resolveResult != null) return resolveResult;
       }
@@ -421,7 +433,10 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
       namesAlready = new HashSet<String>();
     }
 
-    // TODO: Doc
+    /**
+     * [element_name] => (how_element_obtained, element_it_self).
+     * To be used to replace elements with providers that may override them.
+     */
     final Map<String, Pair<ElementType, Object>> usedNames = new HashMap<String, Pair<ElementType, Object>>();
 
 
@@ -438,22 +453,23 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
     namesAlready.addAll(usedNames.keySet());
 
 
-    // Move to func
-    // TODO: Override only if Overriding
-    // from providers
+    // TODO: extract method?
+    // Adding elements from providers
     for (final PyClassMembersProvider provider : Extensions.getExtensions(PyClassMembersProvider.EP_NAME)) {
       for (final PyCustomMember member : provider.getMembers(this, location)) {
         final String name = member.getName();
         final LookupElementBuilder element = PyCustomMemberUtils.toLookUpElement(member, getName());
 
         final Pair<ElementType, Object> usedNameInfo = usedNames.get(name);
-        // TODO: Doc
+        /**
+         * If element exists already (usedNameInfo != null) then we need to check if it is overwritable.
+         * OWN elements could be overwritten by PyOverridingClassMembersProvider
+         * INHERITED only by PyOverridingAncestorsClassMembersProvider
+         */
         if (usedNameInfo == null ||
             (usedNameInfo.first == ElementType.INHERITED && provider instanceof PyOverridingAncestorsClassMembersProvider) ||
             (usedNameInfo.first == ElementType.OWN && provider instanceof PyOverridingClassMembersProvider)) {
           usedNames.put(name, Pair.<ElementType, Object>create(ElementType.BY_PROVIDER, element));
-        } else {
-          int i = 1;
         }
       }
     }
@@ -533,11 +549,11 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
 
   @NotNull
   private List<Object> addInheritedMembers(String name,
-                                   PsiElement expressionHook,
-                                   Set<String> namesAlready,
-                                   ProcessingContext context,
-                                   @NotNull final Map<String, Pair<ElementType, Object>> usedNames,
-                                   @NotNull TypeEvalContext typeEvalContext) {
+                                           PsiElement expressionHook,
+                                           Set<String> namesAlready,
+                                           ProcessingContext context,
+                                           @NotNull final Map<String, Pair<ElementType, Object>> usedNames,
+                                           @NotNull TypeEvalContext typeEvalContext) {
     final List<Object> ret = new ArrayList<Object>();
     for (PyExpression expression : myClass.getSuperClassExpressions()) {
       final PsiReference reference = expression.getReference();
@@ -657,10 +673,21 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
     return ret;
   }
 
-  // TODO: Doc
+  /**
+   * How class member was obtained
+   */
   private enum ElementType {
+    /**
+     * Class own member
+     */
     OWN,
+    /**
+     * Inherited from parent
+     */
     INHERITED,
+    /**
+     * Added by provider (via extension point)
+     */
     BY_PROVIDER
   }
 }