@Override
  public PsiType visitClassType(final PsiClassType classType) {
    PsiClassType alreadyComputed = myResultMap.get(classType);
    if (alreadyComputed != null) {
      return alreadyComputed;
    }

    final PsiClassType.ClassResolveResult classResolveResult = classType.resolveGenerics();
    final PsiClass psiClass = classResolveResult.getElement();
    final PsiSubstitutor substitutor = classResolveResult.getSubstitutor();
    if (psiClass == null) return classType;

    PsiUtilCore.ensureValid(psiClass);

    final PsiClass mappedClass = mapClass(psiClass);
    if (mappedClass == null) return classType;

    PsiClassType mappedType =
        new PsiCorrectedClassType(
            classType.getLanguageLevel(),
            classType,
            new CorrectedResolveResult(psiClass, mappedClass, substitutor, classResolveResult));
    myResultMap.put(classType, mappedType);
    return mappedType;
  }
 @Nullable
 private static PsiType getExpectedTypeArg(
     PsiElement context,
     int index,
     PsiClassType.ClassResolveResult expectedType,
     PsiSubstitutor currentSubstitutor,
     PsiTypeParameter[] params) {
   PsiClass expectedClass = expectedType.getElement();
   assert expectedClass != null;
   for (PsiTypeParameter parameter : PsiUtil.typeParametersIterable(expectedClass)) {
     final PsiType argSubstitution = expectedType.getSubstitutor().substitute(parameter);
     final PsiType paramSubstitution = currentSubstitutor.substitute(parameter);
     final PsiType substitution =
         JavaPsiFacade.getInstance(context.getProject())
             .getResolveHelper()
             .getSubstitutionForTypeParameter(
                 params[index],
                 paramSubstitution,
                 argSubstitution,
                 false,
                 PsiUtil.getLanguageLevel(context));
     if (substitution != null && substitution != PsiType.NULL) {
       return substitution;
     }
   }
   return null;
 }
 public static boolean isReceiverType(
     PsiType functionalInterfaceType,
     PsiClass containingClass,
     @Nullable PsiMethod referencedMethod) {
   final PsiClassType.ClassResolveResult resolveResult =
       PsiUtil.resolveGenericsClassInType(functionalInterfaceType);
   final MethodSignature function = LambdaUtil.getFunction(resolveResult.getElement());
   if (function != null) {
     final int interfaceMethodParamsLength = function.getParameterTypes().length;
     if (interfaceMethodParamsLength > 0) {
       final PsiType firstParamType =
           resolveResult.getSubstitutor().substitute(function.getParameterTypes()[0]);
       boolean isReceiver =
           isReceiverType(
               firstParamType,
               containingClass,
               PsiUtil.resolveGenericsClassInType(firstParamType).getSubstitutor());
       if (isReceiver) {
         if (referencedMethod == null) {
           if (interfaceMethodParamsLength == 1) return true;
           return false;
         }
         if (referencedMethod.getParameterList().getParametersCount()
             != interfaceMethodParamsLength - 1) {
           return false;
         }
         return true;
       }
     }
   }
   return false;
 }
 public static void register(
     final HighlightInfo highlightInfo, PsiExpression expression, final PsiType lType) {
   expression = PsiUtil.deparenthesizeExpression(expression);
   if (!(expression instanceof PsiNewExpression)) return;
   final PsiType rType = expression.getType();
   PsiType newType = lType;
   if (rType instanceof PsiClassType && newType instanceof PsiClassType) {
     final PsiClassType.ClassResolveResult rResolveResult =
         ((PsiClassType) rType).resolveGenerics();
     final PsiClass rClass = rResolveResult.getElement();
     if (rClass != null) {
       final PsiClassType.ClassResolveResult lResolveResult =
           ((PsiClassType) newType).resolveGenerics();
       final PsiClass lClass = lResolveResult.getElement();
       if (lClass != null) {
         PsiSubstitutor substitutor =
             getInheritorSubstitutorForNewExpression(
                 lClass, rClass, lResolveResult.getSubstitutor(), expression);
         if (substitutor != null) {
           newType =
               JavaPsiFacade.getInstance(lClass.getProject())
                   .getElementFactory()
                   .createType(rClass, substitutor);
         }
       }
     }
   }
   PsiNewExpression newExpression = (PsiNewExpression) expression;
   QuickFixAction.registerQuickFixAction(
       highlightInfo, new ChangeNewOperatorTypeFix(newType, newExpression));
 }
Example #5
0
 private void getVariantsFromQualifierType(
     @NotNull PsiType qualifierType, @NotNull Project project) {
   final ResolveState state = ResolveState.initial();
   if (qualifierType instanceof PsiClassType) {
     PsiClassType.ClassResolveResult result = ((PsiClassType) qualifierType).resolveGenerics();
     PsiClass qualifierClass = result.getElement();
     if (qualifierClass != null) {
       qualifierClass.processDeclarations(
           myProcessor, state.put(PsiSubstitutor.KEY, result.getSubstitutor()), null, myRefExpr);
     }
   } else if (qualifierType instanceof PsiArrayType) {
     final GrTypeDefinition arrayClass =
         GroovyPsiManager.getInstance(project)
             .getArrayClass(((PsiArrayType) qualifierType).getComponentType());
     if (arrayClass != null) {
       if (!arrayClass.processDeclarations(myProcessor, state, null, myRefExpr)) return;
     }
   } else if (qualifierType instanceof PsiIntersectionType) {
     for (PsiType conjunct : ((PsiIntersectionType) qualifierType).getConjuncts()) {
       getVariantsFromQualifierType(conjunct, project);
     }
     return;
   }
   ResolveUtil.processNonCodeMembers(qualifierType, myProcessor, myRefExpr, state);
 }
 @Nullable
 private static PsiType getTypeFromMapAccess(@NotNull GrReferenceExpressionImpl ref) {
   // map access
   GrExpression qualifier = ref.getQualifierExpression();
   if (qualifier != null) {
     PsiType qType = qualifier.getNominalType();
     if (qType instanceof PsiClassType) {
       PsiClassType.ClassResolveResult qResult = ((PsiClassType) qType).resolveGenerics();
       PsiClass clazz = qResult.getElement();
       if (clazz != null) {
         PsiClass mapClass =
             JavaPsiFacade.getInstance(ref.getProject())
                 .findClass(CommonClassNames.JAVA_UTIL_MAP, ref.getResolveScope());
         if (mapClass != null && mapClass.getTypeParameters().length == 2) {
           PsiSubstitutor substitutor =
               TypeConversionUtil.getClassSubstitutor(mapClass, clazz, qResult.getSubstitutor());
           if (substitutor != null) {
             return TypeConversionUtil.erasure(
                 substitutor.substitute(mapClass.getTypeParameters()[1]));
           }
         }
       }
     }
   }
   return null;
 }
 @Nullable
 private static PsiType getInferredTypes(
     GrReferenceExpressionImpl refExpr, @Nullable PsiElement resolved) {
   final GrExpression qualifier = refExpr.getQualifier();
   if (qualifier == null && !(resolved instanceof PsiClass)) {
     return TypeInferenceHelper.getCurrentContext().getVariableType(refExpr);
   } else if (qualifier != null) {
     // map access
     PsiType qType = qualifier.getType();
     if (qType instanceof PsiClassType && !(qType instanceof GrMapType)) {
       PsiClassType.ClassResolveResult qResult = ((PsiClassType) qType).resolveGenerics();
       PsiClass clazz = qResult.getElement();
       if (clazz != null) {
         PsiClass mapClass =
             JavaPsiFacade.getInstance(refExpr.getProject())
                 .findClass(CommonClassNames.JAVA_UTIL_MAP, refExpr.getResolveScope());
         if (mapClass != null && mapClass.getTypeParameters().length == 2) {
           PsiSubstitutor substitutor =
               TypeConversionUtil.getClassSubstitutor(mapClass, clazz, qResult.getSubstitutor());
           if (substitutor != null) {
             return TypeConversionUtil.erasure(
                 substitutor.substitute(mapClass.getTypeParameters()[1]));
           }
         }
       }
     }
   }
   return null;
 }
  @Nullable
  public static PsiType getExpectedClosureReturnType(GrClosableBlock closure) {
    final Set<PsiType> expectedTypes = getDefaultExpectedTypes(closure);

    List<PsiType> expectedReturnTypes = new ArrayList<PsiType>();
    for (PsiType expectedType : expectedTypes) {
      if (!(expectedType instanceof PsiClassType)) return null;

      final PsiClassType.ClassResolveResult resolveResult =
          ((PsiClassType) expectedType).resolveGenerics();
      final PsiClass resolved = resolveResult.getElement();
      if (resolved == null
          || !(GroovyCommonClassNames.GROOVY_LANG_CLOSURE.equals(resolved.getQualifiedName())))
        return null;

      final PsiTypeParameter[] typeParameters = resolved.getTypeParameters();
      if (typeParameters.length != 1) return null;

      final PsiTypeParameter expected = typeParameters[0];
      final PsiType expectedReturnType = resolveResult.getSubstitutor().substitute(expected);
      if (expectedReturnType == PsiType.VOID || expectedReturnType == null) return null;

      expectedReturnTypes.add(expectedReturnType);
    }

    return TypesUtil.getLeastUpperBoundNullable(expectedReturnTypes, closure.getManager());
  }
    @Override
    public PsiType visitClassType(PsiClassType classType) {
      final PsiClassType.ClassResolveResult resolveResult = classType.resolveGenerics();
      final PsiClass aClass = resolveResult.getElement();
      if (aClass == null) return classType;

      PsiUtilCore.ensureValid(aClass);
      if (aClass instanceof PsiTypeParameter) {
        final PsiTypeParameter typeParameter = (PsiTypeParameter) aClass;
        if (containsInMap(typeParameter)) {
          PsiType result = substituteTypeParameter(typeParameter);
          if (result != null) {
            PsiUtil.ensureValidType(result);
          }
          return result;
        }
        return classType;
      }
      final Map<PsiTypeParameter, PsiType> hashMap = new HashMap<PsiTypeParameter, PsiType>(2);
      if (!processClass(aClass, resolveResult.getSubstitutor(), hashMap)) {
        return null;
      }
      PsiClassType result =
          JavaPsiFacade.getElementFactory(aClass.getProject())
              .createType(aClass, createSubstitutor(hashMap), classType.getLanguageLevel());
      PsiUtil.ensureValidType(result);
      return result;
    }
  /**
   * Adds all code methods of clazz add its super classes to signatures. Doesn't walk into
   * interfaces because all methods from them will be overloaded in any case. Besides Some of
   * interfaces came from delegates and they should be visited during the following processing.
   *
   * @param clazz current class
   * @param substitutor super class substitutor of clazz
   * @param signatures map to initialize
   * @param classes already visited classes
   */
  private static void initializeSignatures(
      PsiClass clazz,
      PsiSubstitutor substitutor,
      Map<MethodSignature, PsiMethod> signatures,
      Set<PsiClass> classes) {
    if (clazz.isInterface()) return;

    if (classes.add(clazz)) {
      final List<PsiMethod> methods;
      if (clazz instanceof GrTypeDefinition) {
        methods = new ArrayList<PsiMethod>();
        GrClassImplUtil.collectMethodsFromBody((GrTypeDefinition) clazz, methods);
      } else {
        methods = Arrays.asList(clazz.getMethods());
      }

      for (PsiMethod method : methods) {
        addMethodChecked(signatures, method, substitutor, null);
      }

      for (PsiClassType type : getSuperTypes(clazz)) {
        final PsiClassType.ClassResolveResult result = type.resolveGenerics();
        final PsiClass superClass = result.getElement();
        if (superClass == null) continue;
        final PsiSubstitutor superClassSubstitutor =
            TypeConversionUtil.getSuperClassSubstitutor(superClass, clazz, substitutor);
        initializeSignatures(superClass, superClassSubstitutor, signatures, classes);
      }
    }
  }
  private static boolean isPartiallySubstituted(PsiType type) {
    if (!(type instanceof PsiClassType)) return false;
    PsiType[] parameters = ((PsiClassType) type).getParameters();

    PsiClassType.ClassResolveResult classResolveResult = ((PsiClassType) type).resolveGenerics();
    PsiClass clazz = classResolveResult.getElement();
    if (clazz == null) return false;

    return clazz.getTypeParameters().length != parameters.length;
  }
    public PsiType substitute(final PsiType t) {
      if (t instanceof PsiWildcardType) {
        final PsiWildcardType wcType = (PsiWildcardType) t;
        final PsiType bound = wcType.getBound();

        if (bound == null) {
          return t;
        }

        final PsiManager manager = PsiManager.getInstance(myProject);
        final PsiType subst = substitute(bound);
        if (subst == null) return null;
        return subst instanceof PsiWildcardType
            ? subst
            : wcType.isExtends()
                ? PsiWildcardType.createExtends(manager, subst)
                : PsiWildcardType.createSuper(manager, subst);
      } else if (t instanceof PsiTypeVariable) {
        final PsiType b = apply(t);

        if (b instanceof Bottom || b instanceof PsiTypeVariable) {
          return null;
        }

        return substitute(b);
      } else if (t instanceof Bottom) {
        return null;
      } else if (t instanceof PsiArrayType) {
        return substitute(((PsiArrayType) t).getComponentType()).createArrayType();
      } else if (t instanceof PsiClassType) {
        final PsiClassType.ClassResolveResult result = ((PsiClassType) t).resolveGenerics();

        final PsiClass aClass = result.getElement();
        final PsiSubstitutor aSubst = result.getSubstitutor();

        if (aClass != null) {
          PsiSubstitutor theSubst = PsiSubstitutor.EMPTY;

          for (final PsiTypeParameter parm : aSubst.getSubstitutionMap().keySet()) {
            final PsiType type = aSubst.substitute(parm);

            theSubst = theSubst.put(parm, substitute(type));
          }

          return JavaPsiFacade.getInstance(aClass.getProject())
              .getElementFactory()
              .createType(aClass, theSubst);
        }
      }
      return t;
    }
  @NotNull
  @Override
  public PsiJavaCodeReferenceElement createReferenceElementByType(
      @NotNull final PsiClassType type) {
    if (type instanceof PsiClassReferenceType) {
      return ((PsiClassReferenceType) type).getReference();
    }

    final PsiClassType.ClassResolveResult resolveResult = type.resolveGenerics();
    final PsiClass refClass = resolveResult.getElement();
    assert refClass != null : type;
    return new LightClassReference(
        myManager, type.getCanonicalText(), refClass, resolveResult.getSubstitutor());
  }
Example #14
0
  @Nullable
  public static PsiType rawSecondGeneric(PsiType type, Project project) {
    if (!(type instanceof PsiClassType)) return null;

    final PsiClassType.ClassResolveResult result = ((PsiClassType) type).resolveGenerics();
    final PsiClass element = result.getElement();
    if (element == null) return null;

    final PsiType[] parameters = ((PsiClassType) type).getParameters();

    boolean changed = false;
    for (int i = 0; i < parameters.length; i++) {
      PsiType parameter = parameters[i];
      if (parameter == null) continue;

      final Ref<PsiType> newParam = new Ref<PsiType>();
      parameter.accept(
          new PsiTypeVisitorEx<Object>() {
            @Nullable
            @Override
            public Object visitClassType(PsiClassType classType) {
              if (classType.getParameterCount() > 0) {
                newParam.set(classType.rawType());
              }
              return null;
            }

            @Nullable
            @Override
            public Object visitCapturedWildcardType(PsiCapturedWildcardType capturedWildcardType) {
              newParam.set(capturedWildcardType.getWildcard().getBound());
              return null;
            }

            @Nullable
            @Override
            public Object visitWildcardType(PsiWildcardType wildcardType) {
              newParam.set(wildcardType.getBound());
              return null;
            }
          });

      if (!newParam.isNull()) {
        changed = true;
        parameters[i] = newParam.get();
      }
    }
    if (!changed) return null;
    return JavaPsiFacade.getElementFactory(project).createType(element, parameters);
  }
 @Nullable
 public static PsiType getFunctionalInterfaceReturnType(
     @Nullable PsiType functionalInterfaceType) {
   final PsiClassType.ClassResolveResult resolveResult =
       PsiUtil.resolveGenericsClassInType(functionalInterfaceType);
   final PsiClass psiClass = resolveResult.getElement();
   if (psiClass != null) {
     final MethodSignature methodSignature = getFunction(psiClass);
     if (methodSignature != null) {
       final PsiType returnType = getReturnType(psiClass, methodSignature);
       return resolveResult.getSubstitutor().substitute(returnType);
     }
   }
   return null;
 }
  @Override
  public Result calculateResult(@NotNull Expression[] params, ExpressionContext context) {
    if (params.length != 1) return null;
    final Result result = params[0].calculateResult(context);
    if (result == null) return null;

    Project project = context.getProject();

    PsiExpression expr = MacroUtil.resultToPsiExpression(result, context);
    if (expr == null) return null;
    PsiType type = expr.getType();

    if (type instanceof PsiArrayType) {
      return new PsiTypeResult(((PsiArrayType) type).getComponentType(), project);
    }

    if (type instanceof PsiClassType) {
      PsiClassType.ClassResolveResult resolveResult = ((PsiClassType) type).resolveGenerics();
      PsiClass aClass = resolveResult.getElement();

      if (aClass != null) {
        PsiClass iterableClass =
            JavaPsiFacade.getInstance(project)
                .findClass("java.lang.Iterable", aClass.getResolveScope());
        if (iterableClass != null) {
          PsiSubstitutor substitutor =
              TypeConversionUtil.getClassSubstitutor(
                  iterableClass, aClass, resolveResult.getSubstitutor());
          if (substitutor != null) {
            PsiType parameterType = substitutor.substitute(iterableClass.getTypeParameters()[0]);
            if (parameterType instanceof PsiCapturedWildcardType) {
              parameterType = ((PsiCapturedWildcardType) parameterType).getWildcard();
            }
            if (parameterType != null) {
              if (parameterType instanceof PsiWildcardType) {
                if (((PsiWildcardType) parameterType).isExtends()) {
                  return new PsiTypeResult(((PsiWildcardType) parameterType).getBound(), project);
                } else return null;
              }
              return new PsiTypeResult(parameterType, project);
            }
          }
        }
      }
    }

    return null;
  }
  // uses hierarchy signature tree if available, traverses class structure by itself otherwise
  public static boolean processDirectSuperMethodsSmart(
      @NotNull PsiMethod method, @NotNull Processor<PsiMethod> superMethodProcessor) {
    // boolean old = PsiSuperMethodUtil.isSuperMethod(method, superMethod);

    PsiClass aClass = method.getContainingClass();
    if (aClass == null) return false;

    if (!canHaveSuperMethod(method, true, false)) return false;

    Map<MethodSignature, HierarchicalMethodSignature> cachedMap =
        SIGNATURES_KEY.getCachedValueOrNull(aClass);
    if (cachedMap != null) {
      HierarchicalMethodSignature signature =
          cachedMap.get(method.getSignature(PsiSubstitutor.EMPTY));
      if (signature != null) {
        List<HierarchicalMethodSignature> superSignatures = signature.getSuperSignatures();
        for (HierarchicalMethodSignature superSignature : superSignatures) {
          if (!superMethodProcessor.process(superSignature.getMethod())) return false;
        }
        return true;
      }
    }

    PsiClassType[] directSupers = aClass.getSuperTypes();
    for (PsiClassType directSuper : directSupers) {
      PsiClassType.ClassResolveResult resolveResult = directSuper.resolveGenerics();
      if (resolveResult.getSubstitutor() != PsiSubstitutor.EMPTY) {
        // generics
        break;
      }
      PsiClass directSuperClass = resolveResult.getElement();
      if (directSuperClass == null) continue;
      PsiMethod[] candidates = directSuperClass.findMethodsBySignature(method, false);
      for (PsiMethod candidate : candidates) {
        if (PsiUtil.canBeOverriden(candidate)) {
          if (!superMethodProcessor.process(candidate)) return false;
        }
      }
      return true;
    }

    List<HierarchicalMethodSignature> superSignatures =
        method.getHierarchicalMethodSignature().getSuperSignatures();
    for (HierarchicalMethodSignature superSignature : superSignatures) {
      if (!superMethodProcessor.process(superSignature.getMethod())) return false;
    }
    return true;
  }
  @Nullable
  public <T extends PsiType> T correctType(@NotNull T type) {
    if (type instanceof PsiClassType) {
      PsiClassType classType = (PsiClassType) type;
      if (classType.getParameterCount() == 0) {
        final PsiClassType.ClassResolveResult classResolveResult = classType.resolveGenerics();
        final PsiClass psiClass = classResolveResult.getElement();
        if (psiClass != null && classResolveResult.getSubstitutor() == PsiSubstitutor.EMPTY) {
          final PsiClass mappedClass = mapClass(psiClass);
          if (mappedClass == null || mappedClass == psiClass) return (T) classType;
        }
      }
    }

    return (T) type.accept(this);
  }
  private static void processClassInner(
      PsiClassType type,
      PsiSubstitutor superClassSubstitutor,
      boolean shouldProcessDeprecated,
      List<PsiMethod> result,
      GrTypeDefinition classToDelegateTo,
      Set<PsiClass> processedWithoutDeprecated,
      Set<PsiClass> processedAll,
      boolean keepParameterAnnotationsNew) {
    final PsiClassType.ClassResolveResult resolveResult = type.resolveGenerics();
    final PsiClass psiClass = resolveResult.getElement();
    if (psiClass == null) return;

    final String qname = psiClass.getQualifiedName();
    if (CommonClassNames.JAVA_LANG_OBJECT.equals(qname)) return;
    if (GroovyCommonClassNames.GROOVY_OBJECT.equals(qname)) return;
    if (GroovyCommonClassNames.GROOVY_OBJECT_SUPPORT.equals(qname)) return;

    final PsiSubstitutor substitutor =
        TypesUtil.composeSubstitutors(resolveResult.getSubstitutor(), superClassSubstitutor);

    if (processedAll.contains(psiClass)) return;
    if (!shouldProcessDeprecated && processedWithoutDeprecated.contains(psiClass)) return;

    if (shouldProcessDeprecated) {
      processedAll.add(psiClass);
    } else {
      processedWithoutDeprecated.add(psiClass);
    }

    collectMethods(
        psiClass,
        substitutor,
        shouldProcessDeprecated,
        classToDelegateTo,
        result,
        keepParameterAnnotationsNew);
    process(
        psiClass,
        substitutor,
        shouldProcessDeprecated,
        processedWithoutDeprecated,
        processedAll,
        result,
        classToDelegateTo,
        keepParameterAnnotationsNew);
  }
    public PsiType apply(final PsiType type) {
      if (type instanceof PsiTypeVariable) {
        final PsiType t = myBindings.get(((PsiTypeVariable) type).getIndex());
        return t == null ? type : t;
      } else if (type instanceof PsiArrayType) {
        return apply(((PsiArrayType) type).getComponentType()).createArrayType();
      } else if (type instanceof PsiClassType) {
        final PsiClassType.ClassResolveResult result = Util.resolveType(type);
        final PsiClass theClass = result.getElement();
        final PsiSubstitutor aSubst = result.getSubstitutor();

        PsiSubstitutor theSubst = PsiSubstitutor.EMPTY;

        if (theClass != null) {
          for (final PsiTypeParameter aParm : aSubst.getSubstitutionMap().keySet()) {
            final PsiType aType = aSubst.substitute(aParm);

            theSubst = theSubst.put(aParm, apply(aType));
          }

          return JavaPsiFacade.getInstance(theClass.getProject())
              .getElementFactory()
              .createType(theClass, theSubst);
        } else {
          return type;
        }
      } else if (type instanceof PsiWildcardType) {
        final PsiWildcardType wcType = (PsiWildcardType) type;
        final PsiType bound = wcType.getBound();

        if (bound != null) {
          final PsiType abound = apply(bound);

          if (abound instanceof PsiWildcardType) {
            return null;
          }

          return wcType.isExtends()
              ? PsiWildcardType.createExtends(PsiManager.getInstance(myProject), abound)
              : PsiWildcardType.createSuper(PsiManager.getInstance(myProject), abound);
        }

        return type;
      } else {
        return type;
      }
    }
  @Nullable
  public static PsiType getSubstitutedType(@Nullable PsiParameter parameter) {
    if (parameter == null) return null;

    final PsiType type = getType(parameter);

    if (type instanceof PsiArrayType) {
      return type;
    }

    final PsiClassType.ClassResolveResult result = PsiUtil.resolveGenericsClassInType(type);
    final PsiClass psiClass = result.getElement();
    if (psiClass == null) return type;

    final Set<PsiTypeParameter> usedTypeParameters = new HashSet<PsiTypeParameter>();
    RefactoringUtil.collectTypeParameters(usedTypeParameters, parameter);
    for (Iterator<PsiTypeParameter> iterator = usedTypeParameters.iterator();
        iterator.hasNext(); ) {
      PsiTypeParameter usedTypeParameter = iterator.next();
      if (parameter.getDeclarationScope() != usedTypeParameter.getOwner()) {
        iterator.remove();
      }
    }

    PsiSubstitutor subst = PsiSubstitutor.EMPTY;
    for (PsiTypeParameter usedTypeParameter : usedTypeParameters) {
      subst =
          subst.put(usedTypeParameter, TypeConversionUtil.typeParameterErasure(usedTypeParameter));
    }

    PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
    final Map<PsiTypeParameter, PsiType> typeMap = result.getSubstitutor().getSubstitutionMap();
    for (PsiTypeParameter typeParameter : typeMap.keySet()) {
      final PsiType psiType = typeMap.get(typeParameter);
      substitutor =
          substitutor.put(typeParameter, psiType != null ? subst.substitute(psiType) : null);
    }

    if (psiClass instanceof PsiTypeParameter) {
      return subst.substitute((PsiTypeParameter) psiClass);
    } else {
      return JavaPsiFacade.getElementFactory(parameter.getProject())
          .createType(psiClass, substitutor);
    }
  }
  @Nullable
  private static PsiType getCollectionComponentType(PsiType type, Project project) {
    if (!(type instanceof PsiClassType)) return null;
    PsiClassType classType = (PsiClassType) type;
    PsiClassType.ClassResolveResult result = classType.resolveGenerics();
    PsiClass clazz = result.getElement();
    if (clazz == null) return null;
    JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
    @SuppressWarnings({"ConstantConditions"})
    PsiClass collectionClass = facade.findClass("java.util.Collection", type.getResolveScope());
    if (collectionClass == null || collectionClass.getTypeParameters().length != 1) return null;
    PsiSubstitutor substitutor =
        TypeConversionUtil.getClassSubstitutor(collectionClass, clazz, result.getSubstitutor());

    if (substitutor == null) return null;
    PsiType componentType = substitutor.substitute(collectionClass.getTypeParameters()[0]);
    return componentType instanceof PsiIntersectionType ? null : componentType;
  }
  private static PsiTypeLookupItem doCreateItem(
      final PsiType type,
      PsiElement context,
      int bracketsCount,
      boolean diamond,
      InsertHandler<PsiTypeLookupItem> importFixer) {
    if (type instanceof PsiClassType) {
      PsiClassType.ClassResolveResult classResolveResult = ((PsiClassType) type).resolveGenerics();
      final PsiClass psiClass = classResolveResult.getElement();

      if (psiClass != null) {
        String name = psiClass.getName();
        if (name != null) {
          final PsiSubstitutor substitutor = classResolveResult.getSubstitutor();

          PsiClass resolved =
              JavaPsiFacade.getInstance(psiClass.getProject())
                  .getResolveHelper()
                  .resolveReferencedClass(name, context);

          Set<String> allStrings = new HashSet<String>();
          allStrings.add(name);
          if (!psiClass.getManager().areElementsEquivalent(resolved, psiClass)
              && !PsiUtil.isInnerClass(psiClass)) {
            // inner class name should be shown qualified if its not accessible by single name
            PsiClass aClass = psiClass.getContainingClass();
            while (aClass != null && !PsiUtil.isInnerClass(aClass) && aClass.getName() != null) {
              name = aClass.getName() + '.' + name;
              allStrings.add(name);
              aClass = aClass.getContainingClass();
            }
          }

          PsiTypeLookupItem item =
              new PsiTypeLookupItem(
                  psiClass, name, diamond, bracketsCount, importFixer, substitutor);
          item.addLookupStrings(ArrayUtil.toStringArray(allStrings));
          return item;
        }
      }
    }
    return new PsiTypeLookupItem(
        type, type.getPresentableText(), false, bracketsCount, importFixer, PsiSubstitutor.EMPTY);
  }
  public static PsiSubstitutor getSubstitutor(
      @NotNull PsiMethod method, @NotNull PsiClassType.ClassResolveResult resolveResult) {
    final PsiClass derivedClass = resolveResult.getElement();
    LOG.assertTrue(derivedClass != null);

    final PsiClass methodContainingClass = method.getContainingClass();
    LOG.assertTrue(methodContainingClass != null);
    PsiSubstitutor initialSubst = resolveResult.getSubstitutor();
    final PsiSubstitutor superClassSubstitutor =
        TypeConversionUtil.getSuperClassSubstitutor(
            methodContainingClass, derivedClass, PsiSubstitutor.EMPTY);
    for (PsiTypeParameter param : superClassSubstitutor.getSubstitutionMap().keySet()) {
      final PsiType substitute = superClassSubstitutor.substitute(param);
      if (substitute != null) {
        initialSubst = initialSubst.put(param, initialSubst.substitute(substitute));
      }
    }
    return initialSubst;
  }
 @Nullable
 public static PsiMethod getFunctionalInterfaceMethod(PsiClassType.ClassResolveResult result) {
   final PsiClass psiClass = result.getElement();
   if (psiClass != null) {
     final MethodSignature methodSignature = getFunction(psiClass);
     if (methodSignature != null) {
       return getMethod(psiClass, methodSignature);
     }
   }
   return null;
 }
  @Override
  public void handleInsert(final InsertionContext context, LookupElement item) {
    final PsiClassType.ClassResolveResult resolveResult = myClassType.resolveGenerics();
    final PsiClass psiClass = resolveResult.getElement();
    if (psiClass == null || !psiClass.isValid()) {
      return;
    }

    GroovyPsiElement place =
        PsiTreeUtil.findElementOfClassAtOffset(
            context.getFile(), context.getStartOffset(), GroovyPsiElement.class, false);
    boolean hasParams =
        place != null && GroovyCompletionUtil.hasConstructorParameters(psiClass, place);
    if (myTriggerFeature) {
      FeatureUsageTracker.getInstance().triggerFeatureUsed(JavaCompletionFeatures.AFTER_NEW);
    }

    if (hasParams) {
      ParenthesesInsertHandler.WITH_PARAMETERS.handleInsert(context, item);
    } else {
      ParenthesesInsertHandler.NO_PARAMETERS.handleInsert(context, item);
    }

    shortenRefsInGenerics(context);
    if (hasParams) {
      AutoPopupController.getInstance(context.getProject())
          .autoPopupParameterInfo(context.getEditor(), null);
    }

    PsiDocumentManager.getInstance(context.getProject())
        .doPostponedOperationsAndUnblockDocument(context.getDocument());

    if (psiClass.hasModifierProperty(PsiModifier.ABSTRACT)) {
      final Editor editor = context.getEditor();
      final int offset = context.getTailOffset();
      editor.getDocument().insertString(offset, " {}");
      editor.getCaretModel().moveToOffset(offset + 2);

      context.setLaterRunnable(generateAnonymousBody(editor, context.getFile()));
    }
  }
 private static boolean processSuperTypes(
     @NotNull PsiClass aClass,
     @NotNull PsiScopeProcessor processor,
     @Nullable Set<PsiClass> visited,
     PsiElement last,
     @NotNull PsiElement place,
     @NotNull ResolveState state,
     boolean isRaw,
     @NotNull PsiElementFactory factory,
     @NotNull LanguageLevel languageLevel) {
   boolean resolved = false;
   for (final PsiClassType superType : aClass.getSuperTypes()) {
     final PsiClassType.ClassResolveResult superTypeResolveResult = superType.resolveGenerics();
     PsiClass superClass = superTypeResolveResult.getElement();
     if (superClass == null) continue;
     PsiSubstitutor finalSubstitutor =
         obtainFinalSubstitutor(
             superClass,
             superTypeResolveResult.getSubstitutor(),
             aClass,
             state.get(PsiSubstitutor.KEY),
             factory,
             languageLevel);
     if (aClass instanceof PsiTypeParameter
         && PsiUtil.isRawSubstitutor(superClass, finalSubstitutor)) {
       finalSubstitutor = PsiSubstitutor.EMPTY;
     }
     if (!processDeclarationsInClass(
         superClass,
         processor,
         state.put(PsiSubstitutor.KEY, finalSubstitutor),
         visited,
         last,
         place,
         isRaw)) {
       resolved = true;
     }
   }
   return !resolved;
 }
 public static boolean isReceiverType(
     PsiType receiverType, @Nullable PsiClass containingClass, PsiSubstitutor psiSubstitutor) {
   if (containingClass != null) {
     receiverType = getExpandedType(receiverType, containingClass);
   }
   final PsiClassType.ClassResolveResult resolveResult =
       PsiUtil.resolveGenericsClassInType(receiverType);
   final PsiClass receiverClass = resolveResult.getElement();
   if (receiverClass != null && isReceiverType(receiverClass, containingClass)) {
     if (emptyOrRaw(containingClass, psiSubstitutor)) {
       return true;
     }
     final PsiSubstitutor derivedSubstitutor =
         TypeConversionUtil.getClassSubstitutor(containingClass, receiverClass, psiSubstitutor);
     return derivedSubstitutor != null
         && TypeConversionUtil.isAssignable(
             JavaPsiFacade.getElementFactory(containingClass.getProject())
                 .createType(containingClass, derivedSubstitutor),
             receiverType);
   }
   return false;
 }
        private boolean hasTypeParametersToInfer(PsiClassType classType) {
          final PsiClassType.ClassResolveResult resolveResult = classType.resolveGenerics();
          PsiClass aClass = resolveResult.getElement();
          if (aClass == null) return false;

          final Iterable<PsiTypeParameter> iterable =
              com.intellij.psi.util.PsiUtil.typeParametersIterable(aClass);
          if (!iterable.iterator().hasNext()) {
            return false;
          }

          for (PsiTypeParameter parameter : iterable) {
            PsiType type = resolveResult.getSubstitutor().substitute(parameter);
            if (type != null) {
              if (!(type instanceof PsiWildcardType)
                  || ((PsiWildcardType) type).getBound() != null) {
                return false;
              }
            }
          }
          return true;
        }
  private Binding unify(final PsiType x, final PsiType y, final Unifier unifier) {
    final int indicator =
        (x instanceof PsiTypeVariable ? 1 : 0) + (y instanceof PsiTypeVariable ? 2 : 0);

    switch (indicator) {
      case 0:
        if (x instanceof PsiWildcardType || y instanceof PsiWildcardType) {
          return unifier.unify(x, y);
        } else if (x instanceof PsiArrayType || y instanceof PsiArrayType) {
          final PsiType xType =
              x instanceof PsiArrayType ? ((PsiArrayType) x).getComponentType() : x;
          final PsiType yType =
              y instanceof PsiArrayType ? ((PsiArrayType) y).getComponentType() : y;

          return unify(xType, yType, unifier);
        } else if (x instanceof PsiClassType && y instanceof PsiClassType) {
          final PsiClassType.ClassResolveResult resultX = Util.resolveType(x);
          final PsiClassType.ClassResolveResult resultY = Util.resolveType(y);

          final PsiClass xClass = resultX.getElement();
          final PsiClass yClass = resultY.getElement();

          if (xClass != null && yClass != null) {
            final PsiSubstitutor ySubst = resultY.getSubstitutor();

            final PsiSubstitutor xSubst = resultX.getSubstitutor();

            if (!xClass.equals(yClass)) {
              return null;
            }

            Binding b = create();

            for (final PsiTypeParameter aParm : xSubst.getSubstitutionMap().keySet()) {
              final PsiType xType = xSubst.substitute(aParm);
              final PsiType yType = ySubst.substitute(aParm);

              final Binding b1 = unify(xType, yType, unifier);

              if (b1 == null) {
                return null;
              }

              b = b.compose(b1);
            }

            return b;
          }
        } else if (y instanceof Bottom) {
          return create();
        } else {
          return null;
        }

      default:
        return unifier.unify(x, y);
    }
  }