3 * Copyright 2000-2009 JetBrains s.r.o.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 package com
.intellij
.codeInsight
;
19 import com
.intellij
.openapi
.diagnostic
.Logger
;
20 import com
.intellij
.psi
.*;
21 import org
.jetbrains
.annotations
.NotNull
;
23 public class ExpectedTypeInfoImpl
implements ExpectedTypeInfo
{
25 private static final Logger LOG
= Logger
.getInstance("#com.intellij.codeInsight.ExpectedTypeInfoImpl");
27 private final PsiType type
;
28 private final PsiType defaultType
;
29 private boolean myInsertExplicitTypeParams
;
35 private final int dimCount
;
37 public int getKind() {
43 public TailType
getTailType() {
47 public TailType myTailType
;
49 public String expectedName
;
50 private PsiMethod myCalledMethod
;
53 public ExpectedTypeInfoImpl(@NotNull PsiType type
, int kind
, int dimCount
, @NotNull PsiType defaultType
, @NotNull TailType myTailType
) {
57 this.myTailType
= myTailType
;
58 this.dimCount
= dimCount
;
60 if (type
== defaultType
&& type
instanceof PsiClassType
) {
61 final PsiClassType psiClassType
= (PsiClassType
)type
;
62 final PsiClass psiClass
= psiClassType
.resolve();
63 if (psiClass
!= null && CommonClassNames
.JAVA_LANG_CLASS
.equals(psiClass
.getQualifiedName())) {
64 final PsiType
[] parameters
= psiClassType
.getParameters();
65 if (parameters
.length
== 1 && parameters
[0] instanceof PsiWildcardType
) {
66 final PsiType bound
= ((PsiWildcardType
)parameters
[0]).getExtendsBound();
67 if (bound
instanceof PsiClassType
) {
68 final PsiElementFactory factory
= JavaPsiFacade
.getInstance(psiClass
.getProject()).getElementFactory();
69 defaultType
= factory
.createTypeFromText(CommonClassNames
.JAVA_LANG_CLASS
+ "<" + bound
.getCanonicalText() + ">", null);
75 this.defaultType
= defaultType
;
78 public PsiMethod
getCalledMethod() {
79 return myCalledMethod
;
82 public void setCalledMethod(final PsiMethod calledMethod
) {
83 myCalledMethod
= calledMethod
;
87 public PsiType
getType () {
91 while (dims
-- > 0) t
= t
.createArrayType();
96 public PsiType
getDefaultType () {
97 PsiType t
= defaultType
;
100 while (dims
-- > 0) t
= t
.createArrayType();
104 public boolean isInsertExplicitTypeParams() {
105 return myInsertExplicitTypeParams
;
108 public void setInsertExplicitTypeParams(final boolean insertExplicitTypeParams
) {
109 this.myInsertExplicitTypeParams
= insertExplicitTypeParams
;
112 public boolean equals(final Object o
) {
113 if (this == o
) return true;
114 if (!(o
instanceof ExpectedTypeInfoImpl
)) return false;
116 final ExpectedTypeInfoImpl that
= (ExpectedTypeInfoImpl
)o
;
118 if (dimCount
!= that
.dimCount
) return false;
119 if (kind
!= that
.kind
) return false;
120 if (defaultType
!= null ?
!defaultType
.equals(that
.defaultType
) : that
.defaultType
!= null) return false;
121 if (myTailType
!= null ?
!myTailType
.equals(that
.myTailType
) : that
.myTailType
!= null) return false;
122 if (type
!= null ?
!type
.equals(that
.type
) : that
.type
!= null) return false;
127 public int hashCode() {
129 result
= (type
!= null ? type
.hashCode() : 0);
130 result
= 31 * result
+ (defaultType
!= null ? defaultType
.hashCode() : 0);
131 result
= 31 * result
+ dimCount
;
132 result
= 31 * result
+ kind
;
133 result
= 31 * result
+ (myTailType
!= null ? myTailType
.hashCode() : 0);
137 public boolean equals(ExpectedTypeInfo obj
) {
138 return equals((Object
)obj
);
141 @SuppressWarnings({"HardCodedStringLiteral"})
142 public String
toString() {
143 return "ExpectedTypeInfo[type='" + type
+ "' kind='" + kind
+ "' dims='" + dimCount
+ "']";
146 public ExpectedTypeInfo
[] intersect(ExpectedTypeInfo info
) {
147 ExpectedTypeInfoImpl info1
= (ExpectedTypeInfoImpl
)info
;
148 LOG
.assertTrue(!(type
instanceof PsiArrayType
) && !(info1
.type
instanceof PsiArrayType
));
150 if (kind
== TYPE_STRICTLY
) {
151 if (info1
.kind
== TYPE_STRICTLY
) {
152 if (dimCount
!= info1
.dimCount
) return ExpectedTypeInfo
.EMPTY_ARRAY
;
153 if (info1
.type
.equals(type
)) return new ExpectedTypeInfoImpl
[] {this};
156 return info1
.intersect(this);
159 else if (kind
== TYPE_OR_SUBTYPE
) {
160 if (info1
.kind
== TYPE_STRICTLY
) {
161 if (dimCount
!= info1
.dimCount
) return ExpectedTypeInfo
.EMPTY_ARRAY
;
162 if (type
.isAssignableFrom(info1
.type
)) return new ExpectedTypeInfoImpl
[] {info1
};
164 else if (info1
.kind
== TYPE_OR_SUBTYPE
) {
165 PsiType type
= dimCount
== info1
.dimCount ?
this.type
: getType();
166 PsiType otherType
= dimCount
== info1
.dimCount ? info1
.type
: info1
.getType();
167 if (type
.isAssignableFrom(otherType
)) return new ExpectedTypeInfoImpl
[] {info1
};
168 else if (otherType
.isAssignableFrom(type
)) return new ExpectedTypeInfoImpl
[] {this};
171 return info1
.intersect(this);
174 else if (kind
== TYPE_OR_SUPERTYPE
) {
175 if (info1
.kind
== TYPE_STRICTLY
) {
176 if (dimCount
!= info1
.dimCount
) return ExpectedTypeInfo
.EMPTY_ARRAY
;
177 if (info1
.type
.isAssignableFrom(type
)) return new ExpectedTypeInfoImpl
[] {info1
};
179 else if (info1
.kind
== TYPE_OR_SUBTYPE
) {
180 PsiType type
= dimCount
== info1
.dimCount ?
this.type
: getType();
181 PsiType otherType
= dimCount
== info1
.dimCount ? info1
.type
: info1
.getType();
182 if (otherType
.isAssignableFrom(type
)) return new ExpectedTypeInfoImpl
[] {this};
184 else if (info1
.kind
== TYPE_OR_SUPERTYPE
) {
185 PsiType type
= dimCount
== info1
.dimCount ?
this.type
: getType();
186 PsiType otherType
= dimCount
== info1
.dimCount ? info1
.type
: info1
.getType();
187 if (type
.isAssignableFrom(otherType
)) return new ExpectedTypeInfoImpl
[] {this};
188 else if (otherType
.isAssignableFrom(type
)) return new ExpectedTypeInfoImpl
[] {info1
};
191 return info1
.intersect(this);
196 //todo: the following cases are not implemented: SUPERxSUB, SUBxSUPER
198 return ExpectedTypeInfo
.EMPTY_ARRAY
;
201 public boolean isArrayTypeInfo () {