@Nullable
  static Pair<PsiClass, Integer> getTypeParameterInfo(PsiElement context) {
    final PsiReferenceParameterList parameterList =
        PsiTreeUtil.getContextOfType(context, PsiReferenceParameterList.class, true);
    if (parameterList == null) return null;

    PsiElement parent = parameterList.getParent();
    if (!(parent instanceof PsiJavaCodeReferenceElement)) return null;

    final PsiJavaCodeReferenceElement referenceElement = (PsiJavaCodeReferenceElement) parent;
    final int parameterIndex;

    int index = 0;
    final PsiTypeElement typeElement =
        PsiTreeUtil.getContextOfType(context, PsiTypeElement.class, true);
    if (typeElement != null) {
      final PsiTypeElement[] elements =
          referenceElement.getParameterList().getTypeParameterElements();
      while (index < elements.length) {
        final PsiTypeElement element = elements[index++];
        if (element == typeElement) break;
      }
    }
    parameterIndex = index - 1;

    if (parameterIndex < 0) return null;
    final PsiElement target = referenceElement.resolve();
    if (!(target instanceof PsiClass)) return null;

    final PsiClass referencedClass = (PsiClass) target;
    final PsiTypeParameter[] typeParameters = referencedClass.getTypeParameters();
    if (typeParameters.length <= parameterIndex) return null;

    return Pair.create(referencedClass, parameterIndex);
  }
  private void markTypeParameterUsages(
      final PsiClass psiClass,
      PsiClassType migrationType,
      PsiReferenceParameterList referenceParameterList,
      final Map<PsiElement, Pair<PsiReference[], PsiType>> roots) {

    final PsiSubstitutor[] fullHierarchySubstitutor = {
      migrationType.resolveGenerics().getSubstitutor()
    };
    RefactoringHierarchyUtil.processSuperTypes(
        migrationType,
        new RefactoringHierarchyUtil.SuperTypeVisitor() {
          @Override
          public void visitType(PsiType aType) {
            fullHierarchySubstitutor[0] =
                fullHierarchySubstitutor[0].putAll(
                    ((PsiClassType) aType).resolveGenerics().getSubstitutor());
          }

          @Override
          public void visitClass(PsiClass aClass) {
            // do nothing
          }
        });

    final PsiClass resolvedClass =
        (PsiClass) ((PsiJavaCodeReferenceElement) referenceParameterList.getParent()).resolve();
    ;
    LOG.assertTrue(resolvedClass != null);
    final Set<PsiClass> superClasses = new HashSet<PsiClass>();
    superClasses.add(resolvedClass);
    InheritanceUtil.getSuperClasses(resolvedClass, superClasses, true);
    for (PsiClass superSuperClass : superClasses) {
      final TypeParameterSearcher parameterSearcher =
          new TypeParameterSearcher(superSuperClass.getTypeParameters());
      superSuperClass.accept(
          new JavaRecursiveElementVisitor() {
            @Override
            public void visitMethod(final PsiMethod method) {
              super.visitMethod(method);
              processMemberType(
                  method, parameterSearcher, psiClass, fullHierarchySubstitutor[0], roots);
              for (PsiParameter parameter : method.getParameterList().getParameters()) {
                processMemberType(
                    parameter, parameterSearcher, psiClass, fullHierarchySubstitutor[0], roots);
              }
            }

            @Override
            public void visitField(final PsiField field) {
              super.visitField(field);
              processMemberType(
                  field, parameterSearcher, psiClass, fullHierarchySubstitutor[0], roots);
            }
          });
    }
  }
Esempio n. 3
0
  private static boolean changeClassTypeArgument(
      PsiMethod myMethod,
      Project project,
      PsiType superReturnType,
      PsiClass superClass,
      Editor editor,
      PsiType returnType) {
    if (superClass == null || !superClass.hasTypeParameters()) return true;
    final PsiClass superReturnTypeClass = PsiUtil.resolveClassInType(superReturnType);
    if (superReturnTypeClass == null
        || !(superReturnTypeClass instanceof PsiTypeParameter
            || superReturnTypeClass.hasTypeParameters())) return true;

    final PsiClass derivedClass = myMethod.getContainingClass();
    if (derivedClass == null) return true;

    final PsiReferenceParameterList referenceParameterList =
        findTypeArgumentsList(superClass, derivedClass);
    if (referenceParameterList == null) return true;

    final PsiElement resolve =
        ((PsiJavaCodeReferenceElement) referenceParameterList.getParent()).resolve();
    if (!(resolve instanceof PsiClass)) return true;
    final PsiClass baseClass = (PsiClass) resolve;

    if (returnType instanceof PsiPrimitiveType) {
      returnType = ((PsiPrimitiveType) returnType).getBoxedType(derivedClass);
    }

    final PsiSubstitutor superClassSubstitutor =
        TypeConversionUtil.getSuperClassSubstitutor(superClass, baseClass, PsiSubstitutor.EMPTY);
    final PsiType superReturnTypeInBaseClassType =
        superClassSubstitutor.substitute(superReturnType);
    final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(project).getResolveHelper();
    final PsiSubstitutor psiSubstitutor =
        resolveHelper.inferTypeArguments(
            PsiTypesUtil.filterUnusedTypeParameters(
                superReturnTypeInBaseClassType, baseClass.getTypeParameters()),
            new PsiType[] {superReturnTypeInBaseClassType},
            new PsiType[] {returnType},
            PsiUtil.getLanguageLevel(superClass));

    final TypeMigrationRules rules = new TypeMigrationRules();
    final PsiSubstitutor compoundSubstitutor =
        TypeConversionUtil.getSuperClassSubstitutor(superClass, derivedClass, PsiSubstitutor.EMPTY)
            .putAll(psiSubstitutor);
    rules.setBoundScope(new LocalSearchScope(derivedClass));
    TypeMigrationProcessor.runHighlightingTypeMigration(
        project,
        editor,
        rules,
        referenceParameterList,
        JavaPsiFacade.getElementFactory(project).createType(baseClass, compoundSubstitutor));

    return false;
  }