Django forms and formset support added
[idea/community.git] / python / src / com / jetbrains / python / psi / types / PyCollectionTypeImpl.java
1 /*
2  * Copyright 2000-2014 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.jetbrains.python.psi.types;
17
18 import com.intellij.psi.PsiElement;
19 import com.jetbrains.python.psi.PyClass;
20 import com.jetbrains.python.psi.PyPsiFacade;
21 import org.jetbrains.annotations.NotNull;
22 import org.jetbrains.annotations.Nullable;
23
24 import java.util.List;
25
26 /**
27  * @author yole
28  */
29 public class PyCollectionTypeImpl extends PyClassTypeImpl implements PyCollectionType {
30   @NotNull private final List<PyType> myElementTypes;
31
32   public PyCollectionTypeImpl(@NotNull PyClass source, boolean isDefinition, @NotNull List<PyType> elementTypes) {
33     super(source, isDefinition);
34     myElementTypes = elementTypes;
35   }
36
37
38   @Nullable
39   @Override
40   public PyType getReturnType(@NotNull final TypeEvalContext context) {
41     if (isDefinition()) {
42       return new PyCollectionTypeImpl(getPyClass(), false, myElementTypes);
43     }
44     return null;
45   }
46
47   @NotNull
48   @Override
49   public List<PyType> getElementTypes(@NotNull TypeEvalContext context) {
50     return myElementTypes;
51   }
52
53   @Nullable
54   public static PyCollectionTypeImpl createTypeByQName(@NotNull final PsiElement anchor,
55                                                        @NotNull final String classQualifiedName,
56                                                        final boolean isDefinition,
57                                                        @NotNull final List<PyType> elementTypes) {
58     final PyClass pyClass = PyPsiFacade.getInstance(anchor.getProject()).createClassByQName(classQualifiedName, anchor);
59     if (pyClass == null) {
60       return null;
61     }
62     return new PyCollectionTypeImpl(pyClass, isDefinition, elementTypes);
63   }
64
65   @Override
66   public PyClassType toInstance() {
67     return myIsDefinition ? new PyCollectionTypeImpl(myClass, false, myElementTypes) : this;
68   }
69
70   @Override
71   public boolean equals(Object o) {
72     if (this == o) return true;
73     if (!(o instanceof PyCollectionType)) return false;
74     if (!super.equals(o)) return false;
75
76     PyCollectionType type = (PyCollectionType)o;
77
78     final TypeEvalContext context = TypeEvalContext.codeInsightFallback(myClass.getProject());
79     final List<PyType> otherElementTypes = type.getElementTypes(context);
80     if (myElementTypes.size() != otherElementTypes.size()) return false;
81     for (int i = 0; i < myElementTypes.size(); i++) {
82       final PyType elementType = myElementTypes.get(i);
83       final PyType otherElementType = otherElementTypes.get(i);
84       if (elementType == null && otherElementType != null) return false;
85       if (elementType != null && !elementType.equals(otherElementType)) return false;
86     }
87     return true;
88   }
89
90   @Override
91   public int hashCode() {
92     int result = super.hashCode();
93     result = 31 * result;
94     for (PyType type : myElementTypes) {
95       result += type != null ? type.hashCode() : 0;
96     }
97     return result;
98   }
99 }