2 * Copyright 2000-2009 JetBrains s.r.o.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package com
.intellij
.refactoring
.typeCook
.deductive
.resolver
;
18 import com
.intellij
.openapi
.diagnostic
.Logger
;
19 import com
.intellij
.openapi
.project
.Project
;
20 import com
.intellij
.openapi
.util
.Pair
;
21 import com
.intellij
.psi
.*;
22 import com
.intellij
.psi
.search
.GlobalSearchScope
;
23 import com
.intellij
.psi
.search
.searches
.ClassInheritorsSearch
;
24 import com
.intellij
.psi
.util
.InheritanceUtil
;
25 import com
.intellij
.psi
.util
.TypeConversionUtil
;
26 import com
.intellij
.refactoring
.typeCook
.Util
;
27 import com
.intellij
.refactoring
.typeCook
.deductive
.PsiExtendedTypeVisitor
;
28 import com
.intellij
.refactoring
.typeCook
.deductive
.PsiTypeVariableFactory
;
29 import com
.intellij
.refactoring
.typeCook
.deductive
.builder
.Constraint
;
30 import com
.intellij
.refactoring
.typeCook
.deductive
.builder
.ReductionSystem
;
31 import com
.intellij
.refactoring
.typeCook
.deductive
.builder
.Subtype
;
32 import com
.intellij
.util
.IncorrectOperationException
;
33 import gnu
.trove
.TIntObjectHashMap
;
34 import gnu
.trove
.TObjectProcedure
;
36 import java
.util
.HashSet
;
37 import java
.util
.LinkedHashSet
;
38 import java
.util
.LinkedList
;
44 @SuppressWarnings({"SuspiciousNameCombination"})
45 public class BindingFactory
{
46 private static final Logger LOG
= Logger
.getInstance("#com.intellij.refactoring.typeCook.deductive.resolver.BindingFactory");
48 private final HashSet
<PsiTypeVariable
> myBoundVariables
;
49 private final Project myProject
;
50 private final PsiTypeVariableFactory myFactory
;
52 private PsiClass
[] getGreatestLowerClasses(final PsiClass aClass
, final PsiClass bClass
) {
53 if (InheritanceUtil
.isInheritorOrSelf(aClass
, bClass
, true)) {
54 return new PsiClass
[]{aClass
};
57 if (InheritanceUtil
.isInheritorOrSelf(bClass
, aClass
, true)) {
58 return new PsiClass
[]{bClass
};
61 final Set
<PsiClass
> descendants
= new LinkedHashSet
<PsiClass
>();
64 public void getGreatestLowerClasses(final PsiClass aClass
, final PsiClass bClass
, final Set
<PsiClass
> descendants
) {
65 if (bClass
.hasModifierProperty(PsiModifier
.FINAL
)) return;
66 if (aClass
.isInheritor(bClass
, true)) {
67 descendants
.add(aClass
);
70 for (PsiClass bInheritor
: ClassInheritorsSearch
.search(bClass
, bClass
.getUseScope(), false)) {
71 getGreatestLowerClasses(bInheritor
, aClass
, descendants
);
75 }.getGreatestLowerClasses(aClass
, bClass
, descendants
);
77 return descendants
.toArray(new PsiClass
[descendants
.size()]);
80 private class BindingImpl
extends Binding
{
81 private final TIntObjectHashMap
<PsiType
> myBindings
;
82 private boolean myCyclic
;
84 BindingImpl(final PsiTypeVariable var
, final PsiType type
) {
85 myBindings
= new TIntObjectHashMap
<PsiType
>();
86 myCyclic
= type
instanceof PsiTypeVariable
;
88 myBindings
.put(var
.getIndex(), type
);
91 BindingImpl(final int index
, final PsiType type
) {
92 myBindings
= new TIntObjectHashMap
<PsiType
>();
93 myCyclic
= type
instanceof PsiTypeVariable
;
95 myBindings
.put(index
, type
);
97 if (type
instanceof Bottom
) {
98 final HashSet
<PsiTypeVariable
> cluster
= myFactory
.getClusterOf(index
);
100 if (cluster
!= null) {
101 for (PsiTypeVariable var
: cluster
) {
102 myBindings
.put(var
.getIndex(), type
);
109 myBindings
= new TIntObjectHashMap
<PsiType
>();
113 public PsiType
apply(final PsiType type
) {
114 if (type
instanceof PsiTypeVariable
) {
115 final PsiType t
= myBindings
.get(((PsiTypeVariable
) type
).getIndex());
116 return t
== null ? type
: t
;
118 else if (type
instanceof PsiArrayType
) {
119 return apply(((PsiArrayType
)type
).getComponentType()).createArrayType();
121 else if (type
instanceof PsiClassType
) {
122 final PsiClassType
.ClassResolveResult result
= Util
.resolveType(type
);
123 final PsiClass theClass
= result
.getElement();
124 final PsiSubstitutor aSubst
= result
.getSubstitutor();
126 PsiSubstitutor theSubst
= PsiSubstitutor
.EMPTY
;
128 if (theClass
!= null) {
129 for (final PsiTypeParameter aParm
: aSubst
.getSubstitutionMap().keySet()) {
130 final PsiType aType
= aSubst
.substitute(aParm
);
132 theSubst
= theSubst
.put(aParm
, apply(aType
));
135 return JavaPsiFacade
.getInstance(theClass
.getProject()).getElementFactory().createType(theClass
, theSubst
);
141 else if (type
instanceof PsiWildcardType
) {
142 final PsiWildcardType wcType
= (PsiWildcardType
)type
;
143 final PsiType bound
= wcType
.getBound();
146 final PsiType abound
= apply(bound
);
148 if (abound
instanceof PsiWildcardType
) {
154 ? PsiWildcardType
.createExtends(PsiManager
.getInstance(myProject
), abound
)
155 : PsiWildcardType
.createSuper(PsiManager
.getInstance(myProject
), abound
);
165 public boolean equals(final Object o
) {
166 if (this == o
) return true;
167 if (!(o
instanceof BindingImpl
)) return false;
169 final BindingImpl binding
= (BindingImpl
)o
;
171 if (!myBindings
.equals(binding
.myBindings
)) {
178 public Binding
compose(final Binding b
) {
179 LOG
.assertTrue(b
instanceof BindingImpl
);
181 final BindingImpl b1
= this;
182 final BindingImpl b2
= (BindingImpl
)b
;
184 final BindingImpl b3
= new BindingImpl();
186 for (PsiTypeVariable boundVariable
: myBoundVariables
) {
187 final int i
= boundVariable
.getIndex();
189 final PsiType b1i
= b1
.myBindings
.get(i
);
190 final PsiType b2i
= b2
.myBindings
.get(i
);
192 final int flag
= (b1i
== null ?
0 : 1) + (b2i
== null ?
0 : 2);
198 case 1: /* b1(i)\b2(i) */
200 final PsiType type
= b2
.apply(b1i
);
206 b3
.myBindings
.put(i
, type
);
207 b3
.myCyclic
= type
instanceof PsiTypeVariable
;
211 case 2: /* b2(i)\b1(i) */
213 final PsiType type
= b1
.apply(b2i
);
219 b3
.myBindings
.put(i
, type
);
220 b3
.myCyclic
= type
instanceof PsiTypeVariable
;
224 case 3: /* b2(i) \cap b1(i) */
226 final Binding common
= rise(b1i
, b2i
, null);
228 if (common
== null) {
232 final PsiType type
= common
.apply(b1i
);
241 b3
.myBindings
.put(i
, type
);
242 b3
.myCyclic
= type
instanceof PsiTypeVariable
;
250 public String
toString() {
251 final StringBuffer buffer
= new StringBuffer();
253 for (PsiTypeVariable boundVariable
: myBoundVariables
) {
254 final int i
= boundVariable
.getIndex();
255 final PsiType binding
= myBindings
.get(i
);
257 if (binding
!= null) {
258 buffer
.append("#").append(i
).append(" -> ").append(binding
.getPresentableText()).append("; ");
262 return buffer
.toString();
265 private PsiType
normalize(final PsiType t
) {
266 if (t
== null || t
instanceof PsiTypeVariable
) {
267 return Bottom
.BOTTOM
;
270 if (t
instanceof PsiWildcardType
) {
271 return ((PsiWildcardType
)t
).getBound();
277 public int compare(final Binding binding
) {
278 final BindingImpl b2
= (BindingImpl
)binding
;
279 final BindingImpl b1
= this;
281 int directoin
= Binding
.NONCOMPARABLE
;
282 boolean first
= true;
284 for (PsiTypeVariable boundVariable
: myBoundVariables
) {
285 final int index
= boundVariable
.getIndex();
287 final PsiType x
= normalize(b1
.myBindings
.get(index
));
288 final PsiType y
= normalize(b2
.myBindings
.get(index
));
290 final int comp
= new Object() {
291 int compare(final PsiType x
, final PsiType y
) {
292 final int[] kinds
= new Object() {
293 private int classify(final PsiType type
) {
298 if (type
instanceof PsiPrimitiveType
) {
302 if (type
instanceof PsiArrayType
) {
306 if (type
instanceof PsiClassType
) {
313 int[] classify2(final PsiType x
, final PsiType y
) {
314 return new int[]{classify(x
), classify(y
)};
318 final int kindX
= kinds
[0];
319 final int kindY
= kinds
[1];
321 // Break your brain here...
322 if (kindX
+ kindY
== 0) {
326 if (kindX
* kindY
== 0) {
328 return Binding
.WORSE
;
331 return Binding
.BETTER
;
334 if (kindX
* kindY
== 1) {
339 return Binding
.NONCOMPARABLE
;
342 if (kindX
!= kindY
) {
344 return Binding
.WORSE
;
348 return Binding
.BETTER
;
351 if (kindX
+ kindY
== 5) {
353 final PsiElementFactory f
= JavaPsiFacade
.getInstance(myProject
).getElementFactory();
354 final PsiType cloneable
= f
.createTypeFromText("java.lang.Cloneable", null);
355 final PsiType object
= f
.createTypeFromText("java.lang.Object", null);
356 final PsiType serializable
= f
.createTypeFromText("java.io.Serializable", null);
363 flag
= Binding
.WORSE
;
367 flag
= Binding
.BETTER
;
370 if (type
.equals(object
) || type
.equals(cloneable
) || type
.equals(serializable
)) {
374 catch (IncorrectOperationException e
) {
379 return Binding
.NONCOMPARABLE
;
383 return compare(((PsiArrayType
)x
).getComponentType(), ((PsiArrayType
)y
).getComponentType());
389 // End of breaking...
391 final PsiClassType
.ClassResolveResult resultX
= Util
.resolveType(x
);
392 final PsiClassType
.ClassResolveResult resultY
= Util
.resolveType(y
);
394 final PsiClass xClass
= resultX
.getElement();
395 final PsiClass yClass
= resultY
.getElement();
397 final PsiSubstitutor xSubst
= resultX
.getSubstitutor();
398 final PsiSubstitutor ySubst
= resultY
.getSubstitutor();
400 if (xClass
== null || yClass
== null) {
401 return Binding
.NONCOMPARABLE
;
404 if (xClass
.equals(yClass
)) {
405 boolean first
= true;
406 int direction
= Binding
.SAME
;
408 for (final PsiTypeParameter p
: xSubst
.getSubstitutionMap().keySet()) {
409 final PsiType xParm
= xSubst
.substitute(p
);
410 final PsiType yParm
= ySubst
.substitute(p
);
412 final int comp
= compare(xParm
, yParm
);
414 if (comp
== Binding
.NONCOMPARABLE
) {
415 return Binding
.NONCOMPARABLE
;
423 if (direction
!= comp
) {
424 return Binding
.NONCOMPARABLE
;
431 if (InheritanceUtil
.isCorrectDescendant(xClass
, yClass
, true)) {
432 return Binding
.BETTER
;
434 else if (InheritanceUtil
.isCorrectDescendant(yClass
, xClass
, true)) {
435 return Binding
.WORSE
;
438 return Binding
.NONCOMPARABLE
;
443 if (comp
== Binding
.NONCOMPARABLE
) {
444 return Binding
.NONCOMPARABLE
;
452 if (directoin
!= SAME
) {
453 if (comp
!= Binding
.SAME
&& directoin
!= comp
) {
454 return Binding
.NONCOMPARABLE
;
457 else if (comp
!= SAME
) {
465 public boolean nonEmpty() {
466 return myBindings
.size() > 0;
469 public boolean isCyclic() {
473 public Binding
reduceRecursive() {
474 final BindingImpl binding
= (BindingImpl
)create();
476 for (final PsiTypeVariable var
: myBoundVariables
) {
477 final int index
= var
.getIndex();
478 final PsiType type
= myBindings
.get(index
);
481 class Verifier
extends PsiExtendedTypeVisitor
<Void
> {
482 boolean myFlag
= false;
484 @Override public Void
visitTypeVariable(final PsiTypeVariable var
) {
485 if (var
.getIndex() == index
) {
493 final Verifier verifier
= new Verifier();
495 type
.accept(verifier
);
497 if (verifier
.myFlag
) {
498 myBindings
.put(index
, Bottom
.BOTTOM
);
499 binding
.myBindings
.put(index
, Bottom
.BOTTOM
);
502 binding
.myBindings
.put(index
, type
);
506 binding
.myBindings
.put(index
, type
);
510 for (final PsiTypeVariable var
: myBoundVariables
) {
511 final int index
= var
.getIndex();
512 final PsiType type
= myBindings
.get(index
);
515 myBindings
.put(index
, binding
.apply(type
));
522 public boolean binds(final PsiTypeVariable var
) {
523 return myBindings
.get(var
.getIndex()) != null;
526 public void merge(final Binding b
, final boolean removeObject
) {
527 for (final PsiTypeVariable var
: b
.getBoundVariables()) {
528 final int index
= var
.getIndex();
530 if (myBindings
.get(index
) != null) {
531 LOG
.error("Oops... Binding conflict...");
534 final PsiType type
= b
.apply(var
);
535 final PsiClassType javaLangObject
=
536 PsiType
.getJavaLangObject(PsiManager
.getInstance(myProject
), GlobalSearchScope
.allScope(myProject
));
539 javaLangObject
.equals(type
)) {
540 final HashSet
<PsiTypeVariable
> cluster
= myFactory
.getClusterOf(var
.getIndex());
542 if (cluster
!= null) {
543 for (final PsiTypeVariable war
: cluster
) {
544 final PsiType wtype
= b
.apply(war
);
546 if (!javaLangObject
.equals(wtype
)) {
547 myBindings
.put(index
, type
);
554 myBindings
.put(index
, type
);
560 public HashSet
<PsiTypeVariable
> getBoundVariables() {
561 return myBoundVariables
;
564 public int getWidth() {
565 class MyProcecure
implements TObjectProcedure
<PsiType
> {
567 public boolean execute(PsiType type
) {
568 if (substitute(type
) != null) width
++;
572 public int getWidth() {
577 MyProcecure procedure
= new MyProcecure();
578 myBindings
.forEachValue(procedure
);
579 return procedure
.getWidth();
582 public boolean isValid() {
583 for (final PsiTypeVariable var
: myBoundVariables
) {
584 final PsiType type
= substitute(var
);
586 if (!var
.isValidInContext(type
)) {
594 public void addTypeVariable(final PsiTypeVariable var
) {
595 myBoundVariables
.add(var
);
598 public PsiType
substitute(final PsiType t
) {
599 if (t
instanceof PsiWildcardType
) {
600 final PsiWildcardType wcType
= (PsiWildcardType
)t
;
601 final PsiType bound
= wcType
.getBound();
607 final PsiManager manager
= PsiManager
.getInstance(myProject
);
608 final PsiType subst
= substitute(bound
);
609 if (subst
== null) return null;
610 return subst
instanceof PsiWildcardType ? subst
: wcType
.isExtends()
611 ? PsiWildcardType
.createExtends(manager
, subst
)
612 : PsiWildcardType
.createSuper(manager
, subst
);
614 else if (t
instanceof PsiTypeVariable
) {
615 final PsiType b
= apply(t
);
617 if (b
instanceof Bottom
|| b
instanceof PsiTypeVariable
) {
621 return substitute(b
);
623 else if (t
instanceof Bottom
) {
626 else if (t
instanceof PsiArrayType
) {
627 return substitute(((PsiArrayType
)t
).getComponentType()).createArrayType();
629 else if (t
instanceof PsiClassType
) {
630 final PsiClassType
.ClassResolveResult result
= ((PsiClassType
)t
).resolveGenerics();
632 final PsiClass aClass
= result
.getElement();
633 final PsiSubstitutor aSubst
= result
.getSubstitutor();
635 if (aClass
!= null) {
636 PsiSubstitutor theSubst
= PsiSubstitutor
.EMPTY
;
638 for (final PsiTypeParameter parm
: aSubst
.getSubstitutionMap().keySet()) {
639 final PsiType type
= aSubst
.substitute(parm
);
641 theSubst
= theSubst
.put(parm
, substitute(type
));
644 return JavaPsiFacade
.getInstance(aClass
.getProject()).getElementFactory().createType(aClass
, theSubst
);
652 Binding
varType(PsiTypeVariable x
, PsiType y
);
654 Binding
varVar(PsiTypeVariable x
, PsiTypeVariable y
);
656 Binding
typeVar(PsiType x
, PsiTypeVariable y
);
660 Binding
unify(PsiType x
, PsiType y
);
663 public Binding
balance(final PsiType x
, final PsiType y
, final Balancer balancer
, final HashSet
<Constraint
> constraints
) {
664 final int indicator
= (x
instanceof PsiTypeVariable ?
1 : 0) + (y
instanceof PsiTypeVariable ?
2 : 0);
668 if (x
instanceof PsiWildcardType
|| y
instanceof PsiWildcardType
) {
669 final PsiType xType
= x
instanceof PsiWildcardType ?
((PsiWildcardType
)x
).getBound() : x
;
670 final PsiType yType
= y
instanceof PsiWildcardType ?
((PsiWildcardType
)y
).getBound() : y
;
672 switch ((x
instanceof PsiWildcardType ?
1 : 0) + (y
instanceof PsiWildcardType ?
2 : 0)) {
674 if (((PsiWildcardType
)x
).isExtends()) {
675 /* ? extends T1, T2 */
680 if (xType
!= null && !"java.lang.Object".equals(xType
.getCanonicalText())) {
687 if (((PsiWildcardType
)y
).isExtends()) {
688 /* T1, ? extends T2 */
689 if (yType
instanceof PsiTypeVariable
) {
690 final PsiTypeVariable beta
= myFactory
.create();
692 if (constraints
!= null) {
693 constraints
.add (new Subtype(beta
, yType
));
695 constraints
.add (new Subtype(x
, yType
));
702 if (constraints
!= null && xType
!= null && yType
!= null) {
703 constraints
.add(new Subtype(xType
, yType
));
706 return balance(xType
, yType
, balancer
, constraints
);
709 else {/* T1, ? super T2 */
710 if (yType
instanceof PsiTypeVariable
) {
711 final PsiTypeVariable beta
= myFactory
.create();
713 if (constraints
!= null) {
714 if (x
!= null) constraints
.add (new Subtype(x
, beta
));
715 constraints
.add (new Subtype(yType
, beta
));
721 if (constraints
!= null && yType
!= null && xType
!= null) {
722 constraints
.add(new Subtype(yType
, xType
));
725 return balance(xType
, yType
, balancer
, constraints
);
730 switch ((((PsiWildcardType
)x
).isExtends() ?
0 : 1) + (((PsiWildcardType
)y
).isExtends() ?
0 : 2)) {
731 case 0: /* ? super T1, ? super T2 */
732 if (constraints
!= null && xType
!= null && yType
!= null) {
733 constraints
.add(new Subtype(yType
, xType
));
735 return balance(xType
, yType
, balancer
, constraints
);
737 case 1: /* ? extends T1, ? super T2 */
738 if (constraints
!= null && xType
!= null && yType
!= null) {
739 constraints
.add(new Subtype(xType
, yType
));
741 return balance(xType
, yType
, balancer
, constraints
);
743 case 2: /* ? super T1, ? extends T2*/
746 case 3: /* ? extends T1, ? extends T2*/
747 if (constraints
!= null && xType
!= null && yType
!= null) {
748 constraints
.add(new Subtype(xType
, yType
));
750 return balance(xType
, yType
, balancer
, constraints
);
756 else if (x
instanceof PsiArrayType
|| y
instanceof PsiArrayType
) {
757 final PsiType xType
= x
instanceof PsiArrayType ?
((PsiArrayType
)x
).getComponentType() : x
;
758 final PsiType yType
= y
instanceof PsiArrayType ?
((PsiArrayType
)y
).getComponentType() : y
;
760 return balance(xType
, yType
, balancer
, constraints
);
762 else if (x
instanceof PsiClassType
&& y
instanceof PsiClassType
) {
763 final PsiClassType
.ClassResolveResult resultX
= Util
.resolveType(x
);
764 final PsiClassType
.ClassResolveResult resultY
= Util
.resolveType(y
);
766 final PsiClass xClass
= resultX
.getElement();
767 final PsiClass yClass
= resultY
.getElement();
769 if (xClass
!= null && yClass
!= null) {
770 final PsiSubstitutor ySubst
= resultY
.getSubstitutor();
772 PsiSubstitutor xSubst
= TypeConversionUtil
.getClassSubstitutor(yClass
, xClass
, resultX
.getSubstitutor());
773 if (xSubst
== null) return null;
775 Binding b
= create();
777 for (final PsiTypeParameter aParm
: xSubst
.getSubstitutionMap().keySet()) {
778 final PsiType xType
= xSubst
.substitute(aParm
);
779 final PsiType yType
= ySubst
.substitute(aParm
);
781 final Binding b1
= unify(xType
, yType
, new Unifier() {
782 public Binding
unify(final PsiType x
, final PsiType y
) {
783 return balance(x
, y
, balancer
, constraints
);
797 else if (y
instanceof Bottom
) {
806 return balancer
.varType((PsiTypeVariable
)x
, y
);
809 return balancer
.typeVar(x
, (PsiTypeVariable
)y
);
812 return balancer
.varVar((PsiTypeVariable
)x
, (PsiTypeVariable
)y
);
818 private Binding
unify(final PsiType x
, final PsiType y
, final Unifier unifier
) {
819 final int indicator
= (x
instanceof PsiTypeVariable ?
1 : 0) + (y
instanceof PsiTypeVariable ?
2 : 0);
823 if (x
instanceof PsiWildcardType
|| y
instanceof PsiWildcardType
) {
824 return unifier
.unify(x
, y
);
826 else if (x
instanceof PsiArrayType
|| y
instanceof PsiArrayType
) {
827 final PsiType xType
= x
instanceof PsiArrayType ?
((PsiArrayType
)x
).getComponentType() : x
;
828 final PsiType yType
= y
instanceof PsiArrayType ?
((PsiArrayType
)y
).getComponentType() : y
;
830 return unify(xType
, yType
, unifier
);
832 else if (x
instanceof PsiClassType
&& y
instanceof PsiClassType
) {
833 final PsiClassType
.ClassResolveResult resultX
= Util
.resolveType(x
);
834 final PsiClassType
.ClassResolveResult resultY
= Util
.resolveType(y
);
836 final PsiClass xClass
= resultX
.getElement();
837 final PsiClass yClass
= resultY
.getElement();
839 if (xClass
!= null && yClass
!= null) {
840 final PsiSubstitutor ySubst
= resultY
.getSubstitutor();
842 final PsiSubstitutor xSubst
= resultX
.getSubstitutor();
844 if (!xClass
.equals(yClass
)) {
848 Binding b
= create();
850 for (final PsiTypeParameter aParm
: xSubst
.getSubstitutionMap().keySet()) {
851 final PsiType xType
= xSubst
.substitute(aParm
);
852 final PsiType yType
= ySubst
.substitute(aParm
);
854 final Binding b1
= unify(xType
, yType
, unifier
);
866 else if (y
instanceof Bottom
) {
874 return unifier
.unify(x
, y
);
878 public Binding
riseWithWildcard(final PsiType x
, final PsiType y
, final HashSet
<Constraint
> constraints
) {
879 final Binding binding
= balance(x
, y
, new Balancer() {
880 public Binding
varType(final PsiTypeVariable x
, final PsiType y
) {
881 if (y
instanceof Bottom
) {
885 if (y
== null || y
instanceof PsiWildcardType
) {
889 final PsiTypeVariable var
= myFactory
.create();
890 final Binding binding
=
891 create(x
, PsiWildcardType
.createSuper(PsiManager
.getInstance(myProject
), var
));
893 binding
.addTypeVariable(var
);
894 constraints
.add(new Subtype(var
, y
));
899 public Binding
varVar(final PsiTypeVariable x
, final PsiTypeVariable y
) {
900 final int xi
= x
.getIndex();
901 final int yi
= y
.getIndex();
906 return create (y
, PsiWildcardType
.createExtends(PsiManager
.getInstance(myProject
), x
));
918 public Binding
typeVar(final PsiType x
, final PsiTypeVariable y
) {
920 return create(y
, Bottom
.BOTTOM
);
923 if (x
instanceof PsiWildcardType
) {
927 final PsiTypeVariable var
= myFactory
.create();
928 final Binding binding
=
929 create(y
, PsiWildcardType
.createExtends(PsiManager
.getInstance(myProject
), var
));
931 binding
.addTypeVariable(var
);
932 constraints
.add(new Subtype(x
, var
));
938 return binding
!= null ? binding
.reduceRecursive() : null;
941 public Binding
rise(final PsiType x
, final PsiType y
, final HashSet
<Constraint
> constraints
) {
942 final Binding binding
= balance(x
, y
, new Balancer() {
943 public Binding
varType(final PsiTypeVariable x
, final PsiType y
) {
944 if (y
instanceof Bottom
|| y
instanceof PsiWildcardType
) {
951 public Binding
varVar(final PsiTypeVariable x
, final PsiTypeVariable y
) {
952 final int xi
= x
.getIndex();
953 final int yi
= y
.getIndex();
966 public Binding
typeVar(final PsiType x
, final PsiTypeVariable y
) {
967 if (x
== null) return create(y
, Bottom
.BOTTOM
);
968 if (x
instanceof PsiWildcardType
) return create();
974 return binding
!= null ? binding
.reduceRecursive() : null;
977 public Binding
sink(final PsiType x
, final PsiType y
, final HashSet
<Constraint
> constraints
) {
978 return balance(x
, y
, new Balancer() {
979 public Binding
varType(final PsiTypeVariable x
, final PsiType y
) {
983 public Binding
varVar(final PsiTypeVariable x
, final PsiTypeVariable y
) {
984 return create(y
, Bottom
.BOTTOM
);
987 public Binding
typeVar(final PsiType x
, final PsiTypeVariable y
) {
988 return create(y
, Bottom
.BOTTOM
);
993 public LinkedList
<Pair
<PsiType
, Binding
>> union(final PsiType x
, final PsiType y
) {
994 final LinkedList
<Pair
<PsiType
, Binding
>> list
= new LinkedList
<Pair
<PsiType
, Binding
>>();
997 void union(final PsiType x
, final PsiType y
, final LinkedList
<Pair
<PsiType
, Binding
>> list
) {
998 if (x
instanceof PsiArrayType
&& y
instanceof PsiArrayType
) {
999 union(((PsiArrayType
)x
).getComponentType(), ((PsiArrayType
)y
).getComponentType(), list
);
1001 else if (x
instanceof PsiClassType
&& y
instanceof PsiClassType
) {
1002 final PsiClassType
.ClassResolveResult xResult
= Util
.resolveType(x
);
1003 final PsiClassType
.ClassResolveResult yResult
= Util
.resolveType(y
);
1005 final PsiClass xClass
= xResult
.getElement();
1006 final PsiClass yClass
= yResult
.getElement();
1008 final PsiSubstitutor xSubst
= xResult
.getSubstitutor();
1009 final PsiSubstitutor ySubst
= yResult
.getSubstitutor();
1011 if (xClass
== null || yClass
== null) {
1015 if (xClass
.equals(yClass
)) {
1016 final Binding risen
= rise(x
, y
, null);
1018 if (risen
== null) {
1022 list
.addFirst(new Pair
<PsiType
, Binding
>(risen
.apply(x
), risen
));
1025 final PsiClass
[] descendants
= getGreatestLowerClasses(xClass
, yClass
);
1027 for (final PsiClass descendant
: descendants
) {
1028 final PsiSubstitutor x2aSubst
= TypeConversionUtil
.getClassSubstitutor(xClass
, descendant
, xSubst
);
1029 final PsiSubstitutor y2aSubst
= TypeConversionUtil
.getClassSubstitutor(yClass
, descendant
, ySubst
);
1030 LOG
.assertTrue(x2aSubst
!= null && y2aSubst
!= null);
1032 final PsiElementFactory factory
= JavaPsiFacade
.getInstance(xClass
.getProject()).getElementFactory();
1034 union(factory
.createType(descendant
, x2aSubst
), factory
.createType(descendant
, y2aSubst
), list
);
1039 }.union(x
, y
, list
);
1044 public LinkedList
<Pair
<PsiType
, Binding
>> intersect(final PsiType x
, final PsiType y
) {
1045 final LinkedList
<Pair
<PsiType
, Binding
>> list
= new LinkedList
<Pair
<PsiType
, Binding
>>();
1048 void intersect(final PsiType x
, final PsiType y
, final LinkedList
<Pair
<PsiType
, Binding
>> list
) {
1049 if (x
instanceof PsiWildcardType
|| y
instanceof PsiWildcardType
) {
1050 final PsiType xType
= x
instanceof PsiWildcardType ?
((PsiWildcardType
)x
).getBound() : x
;
1051 final PsiType yType
= y
instanceof PsiWildcardType ?
((PsiWildcardType
)y
).getBound() : y
;
1053 intersect(xType
, yType
, list
);
1055 if (x
instanceof PsiArrayType
|| y
instanceof PsiArrayType
) {
1056 if (x
instanceof PsiClassType
|| y
instanceof PsiClassType
) {
1058 final PsiElementFactory f
= JavaPsiFacade
.getInstance(myProject
).getElementFactory();
1059 final PsiType keyType
= x
instanceof PsiClassType ? x
: y
;
1061 final PsiType object
= f
.createTypeFromText("java.lang.Object", null);
1062 final PsiType cloneable
= f
.createTypeFromText("java.lang.Cloneable", null);
1063 final PsiType serializable
= f
.createTypeFromText("java.io.Serializable", null);
1065 intersect(keyType
, object
, list
);
1066 intersect(keyType
, cloneable
, list
);
1067 intersect(keyType
, serializable
, list
);
1069 catch (IncorrectOperationException e
) {
1070 LOG
.error("Exception " + e
);
1073 else if (x
instanceof PsiArrayType
&& y
instanceof PsiArrayType
) {
1074 intersect(((PsiArrayType
)x
).getComponentType(), ((PsiArrayType
)y
).getComponentType(), list
);
1077 else if (x
instanceof PsiClassType
&& y
instanceof PsiClassType
) {
1078 final PsiClassType
.ClassResolveResult xResult
= Util
.resolveType(x
);
1079 final PsiClassType
.ClassResolveResult yResult
= Util
.resolveType(y
);
1081 final PsiClass xClass
= xResult
.getElement();
1082 final PsiClass yClass
= yResult
.getElement();
1084 final PsiSubstitutor xSubst
= xResult
.getSubstitutor();
1085 final PsiSubstitutor ySubst
= yResult
.getSubstitutor();
1087 if (xClass
== null || yClass
== null) {
1091 if (xClass
.equals(yClass
)) {
1092 final Binding risen
= rise(x
, y
, null);
1094 if (risen
== null) {
1095 final PsiElementFactory factory
= JavaPsiFacade
.getInstance(xClass
.getProject()).getElementFactory();
1097 list
.addFirst(new Pair
<PsiType
, Binding
>(Util
.banalize(factory
.createType(xClass
, factory
.createRawSubstitutor(xClass
))),
1101 list
.addFirst(new Pair
<PsiType
, Binding
>(risen
.apply(x
), risen
));
1105 final PsiClass
[] ancestors
= GenericsUtil
.getLeastUpperClasses(xClass
, yClass
);
1107 for (final PsiClass ancestor
: ancestors
) {
1108 if ("java.lang.Object".equals(ancestor
.getQualifiedName()) && ancestors
.length
> 1) {
1112 final PsiSubstitutor x2aSubst
= TypeConversionUtil
.getSuperClassSubstitutor(ancestor
, xClass
, xSubst
);
1113 final PsiSubstitutor y2aSubst
= TypeConversionUtil
.getSuperClassSubstitutor(ancestor
, yClass
, ySubst
);
1115 final PsiElementFactory factory
= JavaPsiFacade
.getInstance(xClass
.getProject()).getElementFactory();
1117 intersect(factory
.createType(ancestor
, x2aSubst
), factory
.createType(ancestor
, y2aSubst
), list
);
1122 }.intersect(x
, y
, list
);
1127 public BindingFactory(final ReductionSystem system
) {
1128 myBoundVariables
= system
.getBoundVariables();
1129 myProject
= system
.getProject();
1130 myFactory
= system
.getVariableFactory();
1133 public Binding
create(final PsiTypeVariable var
, final PsiType type
) {
1134 return new BindingImpl(var
, type
);
1137 public Binding
create() {
1138 return new BindingImpl();
1141 public HashSet
<PsiTypeVariable
> getBoundVariables() {
1142 return myBoundVariables
;