void () { if (myConstraints.isEmpty()) { return; } if (myCurrentBinding.isCyclic()) { reduceCyclicVariables(); } final Map<PsiTypeVariable, Constraint> myTypeVarConstraints = new HashMap<>(); final Map<PsiTypeVariable, Constraint> myVarTypeConstraints = new HashMap<>(); for (final Constraint constr : myConstraints) { final PsiType left = constr.getLeft(); final PsiType right = constr.getRight(); switch ((left instanceof PsiTypeVariable ? 0 : 1) + (right instanceof PsiTypeVariable ? 0 : 2)) { case 0 -> { } case 1 -> { final Constraint c = myTypeVarConstraints.get(right); if (c == null) { final Constraint d = myVarTypeConstraints.get(right); if (d != null) { reduceInterval(constr, d); return; } myTypeVarConstraints.put((PsiTypeVariable)right, constr); } else { reduceTypeVar(constr, c); return; } } case 2 -> { final Constraint c = myVarTypeConstraints.get(left); if (c == null) { final Constraint d = myTypeVarConstraints.get(left); if (d != null) { reduceInterval(d, constr); return; } myVarTypeConstraints.put((PsiTypeVariable)left, constr); } else { reduceVarType(constr, c); return; } } case 3 -> { reduceTypeType(constr); return; } } } //T1 < a < b ... < T2 { for (final Constraint constr : myConstraints) { final PsiType left = constr.getLeft(); final PsiType right = constr.getRight(); if (!(left instanceof PsiTypeVariable) && right instanceof PsiTypeVariable) { Set<PsiTypeVariable> bound = new PsiTypeVarCollector().getSet(left); if (bound.contains(right)) { myConstraints.remove(constr); mySons = new ResolverTree[]{applyRule(myBindingFactory.create(((PsiTypeVariable)right), Bottom.BOTTOM))}; return; } final PsiManager manager = PsiManager.getInstance(myProject); final PsiType leftType = left instanceof PsiWildcardType ? ((PsiWildcardType)left).getBound() : left; final PsiType[] types = getTypeRange(PsiType.getJavaLangObject(manager, GlobalSearchScope.allScope(myProject)), leftType); mySons = new ResolverTree[types.length]; if (types.length > 0) { myConstraints.remove(constr); } for (int i = 0; i < types.length; i++) { final PsiType type = types[i]; mySons[i] = applyRule(myBindingFactory.create(((PsiTypeVariable)right), type)); } return; } } } //T1 < a < b < ... { Set<PsiTypeVariable> haveLeftBound = new HashSet<>(); Constraint target = null; Set<PsiTypeVariable> boundVariables = new HashSet<>(); for (final Constraint constr : myConstraints) { final PsiType leftType = constr.getLeft(); final PsiType rightType = constr.getRight(); if (leftType instanceof PsiTypeVariable) { boundVariables.add((PsiTypeVariable)leftType); if (rightType instanceof PsiTypeVariable) { boundVariables.add((PsiTypeVariable)rightType); haveLeftBound.add(((PsiTypeVariable)rightType)); } else if (!Util.bindsTypeVariables(rightType)) { target = constr; } } } if (target == null) { if (mySettings.exhaustive()) { for (final Constraint constr : myConstraints) { final PsiType left = constr.getLeft(); final PsiType right = constr.getRight(); PsiType[] range = null; PsiTypeVariable var = null; if (left instanceof PsiTypeVariable && !(right instanceof PsiTypeVariable)) { range = getTypeRange(PsiType.getJavaLangObject(PsiManager.getInstance(myProject), GlobalSearchScope.allScope(myProject)), right); var = (PsiTypeVariable)left; } if (range == null && right instanceof PsiTypeVariable && !(left instanceof PsiTypeVariable)) { range = new PsiType[]{right}; var = (PsiTypeVariable)right; } if (range != null) { mySons = new ResolverTree[range.length]; for (int i = 0; i < range.length; i++) { mySons[i] = applyRule(myBindingFactory.create(var, range[i])); } return; } } } Binding binding = myBindingFactory.create(); for (final PsiTypeVariable var : myBindingFactory.getBoundVariables()) { if (!myCurrentBinding.binds(var) && !boundVariables.contains(var)) { binding = binding.compose(myBindingFactory.create(var, Bottom.BOTTOM)); } } if (!binding.nonEmpty()) { myConstraints.clear(); } mySons = new ResolverTree[]{applyRule(binding)}; } else { final PsiType type = target.getRight(); final PsiTypeVariable var = (PsiTypeVariable)target.getLeft(); final Binding binding = (haveLeftBound.contains(var) || type instanceof PsiWildcardType) || !mySettings.cookToWildcards() ? myBindingFactory.create(var, type) : myBindingFactory.create(var, PsiWildcardType.createExtends(PsiManager.getInstance(myProject), type)); myConstraints.remove(target); mySons = new ResolverTree[]{applyRule(binding)}; } } }